ETH Price: $1,999.31 (+0.51%)

Transaction Decoder

Block:
7462920 at Mar-29-2019 10:37:18 AM +UTC
Transaction Fee:
0.000617442 ETH $1.23
Gas Used:
44,103 Gas / 14 Gwei

Emitted Events:

84 OIOToken.Transfer( from=[Sender] 0x03ed42cd978950103826fb1d6f5ae04521f44a42, to=[Receiver] Exchange, value=1554303925000000000000 )
85 Exchange.Deposit( token=OIOToken, user=[Sender] 0x03ed42cd978950103826fb1d6f5ae04521f44a42, amount=1554303925000000000000, balance=1554303925000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x03ED42Cd...521f44A42
0.022983181582316716 Eth
Nonce: 45
0.022365739582316716 Eth
Nonce: 46
0.000617442
0x2a0c0DBE...44050c208
(IDEX)
(Spark Pool)
6,196.387134979777589299 Eth6,196.387752421777589299 Eth0.000617442
0xa3Efef1a...084C2c08B

Execution Trace

Exchange.depositToken( token=0xa3Efef1a1e3d1AD72b9D0f4253e7c9c084C2c08B, amount=1554303925000000000000 )
  • OIOToken.transferFrom( _from=0x03ED42Cd978950103826fB1d6F5Ae04521f44A42, _to=0x2a0c0DBEcC7E4D658f48E01e3fA353F44050c208, _value=1554303925000000000000 ) => ( True )
    File 1 of 2: Exchange
    pragma solidity ^0.4.16;
    
    contract Token {
        bytes32 public standard;
        bytes32 public name;
        bytes32 public symbol;
        uint256 public totalSupply;
        uint8 public decimals;
        bool public allowTransactions;
        mapping (address => uint256) public balanceOf;
        mapping (address => mapping (address => uint256)) public allowance;
        function transfer(address _to, uint256 _value) returns (bool success);
        function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success);
        function approve(address _spender, uint256 _value) returns (bool success);
        function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
    }
    
    contract Exchange {
      function assert(bool assertion) {
        if (!assertion) throw;
      }
      function safeMul(uint a, uint b) returns (uint) {
        uint c = a * b;
        assert(a == 0 || c / a == b);
        return c;
      }
    
      function safeSub(uint a, uint b) returns (uint) {
        assert(b <= a);
        return a - b;
      }
    
      function safeAdd(uint a, uint b) returns (uint) {
        uint c = a + b;
        assert(c>=a && c>=b);
        return c;
      }
      address public owner;
      mapping (address => uint256) public invalidOrder;
      event SetOwner(address indexed previousOwner, address indexed newOwner);
      modifier onlyOwner {
        assert(msg.sender == owner);
        _;
      }
      function setOwner(address newOwner) onlyOwner {
        SetOwner(owner, newOwner);
        owner = newOwner;
      }
      function getOwner() returns (address out) {
        return owner;
      }
      function invalidateOrdersBefore(address user, uint256 nonce) onlyAdmin {
        if (nonce < invalidOrder[user]) throw;
        invalidOrder[user] = nonce;
      }
    
      mapping (address => mapping (address => uint256)) public tokens; //mapping of token addresses to mapping of account balances
    
      mapping (address => bool) public admins;
      mapping (address => uint256) public lastActiveTransaction;
      mapping (bytes32 => uint256) public orderFills;
      address public feeAccount;
      uint256 public inactivityReleasePeriod;
      mapping (bytes32 => bool) public traded;
      mapping (bytes32 => bool) public withdrawn;
      event Order(address tokenBuy, uint256 amountBuy, address tokenSell, uint256 amountSell, uint256 expires, uint256 nonce, address user, uint8 v, bytes32 r, bytes32 s);
      event Cancel(address tokenBuy, uint256 amountBuy, address tokenSell, uint256 amountSell, uint256 expires, uint256 nonce, address user, uint8 v, bytes32 r, bytes32 s);
      event Trade(address tokenBuy, uint256 amountBuy, address tokenSell, uint256 amountSell, address get, address give);
      event Deposit(address token, address user, uint256 amount, uint256 balance);
      event Withdraw(address token, address user, uint256 amount, uint256 balance);
    
      function setInactivityReleasePeriod(uint256 expiry) onlyAdmin returns (bool success) {
        if (expiry > 1000000) throw;
        inactivityReleasePeriod = expiry;
        return true;
      }
    
      function Exchange(address feeAccount_) {
        owner = msg.sender;
        feeAccount = feeAccount_;
        inactivityReleasePeriod = 100000;
      }
    
      function setAdmin(address admin, bool isAdmin) onlyOwner {
        admins[admin] = isAdmin;
      }
    
      modifier onlyAdmin {
        if (msg.sender != owner && !admins[msg.sender]) throw;
        _;
      }
    
      function() external {
        throw;
      }
    
      function depositToken(address token, uint256 amount) {
        tokens[token][msg.sender] = safeAdd(tokens[token][msg.sender], amount);
        lastActiveTransaction[msg.sender] = block.number;
        if (!Token(token).transferFrom(msg.sender, this, amount)) throw;
        Deposit(token, msg.sender, amount, tokens[token][msg.sender]);
      }
    
      function deposit() payable {
        tokens[address(0)][msg.sender] = safeAdd(tokens[address(0)][msg.sender], msg.value);
        lastActiveTransaction[msg.sender] = block.number;
        Deposit(address(0), msg.sender, msg.value, tokens[address(0)][msg.sender]);
      }
    
      function withdraw(address token, uint256 amount) returns (bool success) {
        if (safeSub(block.number, lastActiveTransaction[msg.sender]) < inactivityReleasePeriod) throw;
        if (tokens[token][msg.sender] < amount) throw;
        tokens[token][msg.sender] = safeSub(tokens[token][msg.sender], amount);
        if (token == address(0)) {
          if (!msg.sender.send(amount)) throw;
        } else {
          if (!Token(token).transfer(msg.sender, amount)) throw;
        }
        Withdraw(token, msg.sender, amount, tokens[token][msg.sender]);
      }
    
      function adminWithdraw(address token, uint256 amount, address user, uint256 nonce, uint8 v, bytes32 r, bytes32 s, uint256 feeWithdrawal) onlyAdmin returns (bool success) {
        bytes32 hash = keccak256(this, token, amount, user, nonce);
        if (withdrawn[hash]) throw;
        withdrawn[hash] = true;
        if (ecrecover(keccak256("\x19Ethereum Signed Message:\n32", hash), v, r, s) != user) throw;
        if (feeWithdrawal > 50 finney) feeWithdrawal = 50 finney;
        if (tokens[token][user] < amount) throw;
        tokens[token][user] = safeSub(tokens[token][user], amount);
        tokens[token][feeAccount] = safeAdd(tokens[token][feeAccount], safeMul(feeWithdrawal, amount) / 1 ether);
        amount = safeMul((1 ether - feeWithdrawal), amount) / 1 ether;
        if (token == address(0)) {
          if (!user.send(amount)) throw;
        } else {
          if (!Token(token).transfer(user, amount)) throw;
        }
        lastActiveTransaction[user] = block.number;
        Withdraw(token, user, amount, tokens[token][user]);
      }
    
      function balanceOf(address token, address user) constant returns (uint256) {
        return tokens[token][user];
      }
    
      function trade(uint256[8] tradeValues, address[4] tradeAddresses, uint8[2] v, bytes32[4] rs) onlyAdmin returns (bool success) {
        /* amount is in amountBuy terms */
        /* tradeValues
           [0] amountBuy
           [1] amountSell
           [2] expires
           [3] nonce
           [4] amount
           [5] tradeNonce
           [6] feeMake
           [7] feeTake
         tradeAddressses
           [0] tokenBuy
           [1] tokenSell
           [2] maker
           [3] taker
         */
        if (invalidOrder[tradeAddresses[2]] > tradeValues[3]) throw;
        bytes32 orderHash = keccak256(this, tradeAddresses[0], tradeValues[0], tradeAddresses[1], tradeValues[1], tradeValues[2], tradeValues[3], tradeAddresses[2]);
        if (ecrecover(keccak256("\x19Ethereum Signed Message:\n32", orderHash), v[0], rs[0], rs[1]) != tradeAddresses[2]) throw;
        bytes32 tradeHash = keccak256(orderHash, tradeValues[4], tradeAddresses[3], tradeValues[5]); 
        if (ecrecover(keccak256("\x19Ethereum Signed Message:\n32", tradeHash), v[1], rs[2], rs[3]) != tradeAddresses[3]) throw;
        if (traded[tradeHash]) throw;
        traded[tradeHash] = true;
        if (tradeValues[6] > 100 finney) tradeValues[6] = 100 finney;
        if (tradeValues[7] > 100 finney) tradeValues[7] = 100 finney;
        if (safeAdd(orderFills[orderHash], tradeValues[4]) > tradeValues[0]) throw;
        if (tokens[tradeAddresses[0]][tradeAddresses[3]] < tradeValues[4]) throw;
        if (tokens[tradeAddresses[1]][tradeAddresses[2]] < (safeMul(tradeValues[1], tradeValues[4]) / tradeValues[0])) throw;
        tokens[tradeAddresses[0]][tradeAddresses[3]] = safeSub(tokens[tradeAddresses[0]][tradeAddresses[3]], tradeValues[4]);
        tokens[tradeAddresses[0]][tradeAddresses[2]] = safeAdd(tokens[tradeAddresses[0]][tradeAddresses[2]], safeMul(tradeValues[4], ((1 ether) - tradeValues[6])) / (1 ether));
        tokens[tradeAddresses[0]][feeAccount] = safeAdd(tokens[tradeAddresses[0]][feeAccount], safeMul(tradeValues[4], tradeValues[6]) / (1 ether));
        tokens[tradeAddresses[1]][tradeAddresses[2]] = safeSub(tokens[tradeAddresses[1]][tradeAddresses[2]], safeMul(tradeValues[1], tradeValues[4]) / tradeValues[0]);
        tokens[tradeAddresses[1]][tradeAddresses[3]] = safeAdd(tokens[tradeAddresses[1]][tradeAddresses[3]], safeMul(safeMul(((1 ether) - tradeValues[7]), tradeValues[1]), tradeValues[4]) / tradeValues[0] / (1 ether));
        tokens[tradeAddresses[1]][feeAccount] = safeAdd(tokens[tradeAddresses[1]][feeAccount], safeMul(safeMul(tradeValues[7], tradeValues[1]), tradeValues[4]) / tradeValues[0] / (1 ether));
        orderFills[orderHash] = safeAdd(orderFills[orderHash], tradeValues[4]);
        lastActiveTransaction[tradeAddresses[2]] = block.number;
        lastActiveTransaction[tradeAddresses[3]] = block.number;
      }
    }

    File 2 of 2: OIOToken
    pragma solidity ^0.4.18;
    
    contract ERC20Basic {
      function totalSupply() public view returns (uint256);
      function balanceOf(address who) public view returns (uint256);
      function transfer(address to, uint256 value) public returns (bool);
      event Transfer(address indexed from, address indexed to, uint256 value);
    }
    
    contract ERC20 is ERC20Basic {
      function allowance(address owner, address spender) public view returns (uint256);
      function transferFrom(address from, address to, uint256 value) public returns (bool);
      function approve(address spender, uint256 value) public returns (bool);
      event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    
    library SafeMath {
    
      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;
      }
    
      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;
      }
    }
    
    contract Ownable {
      address public owner;
    
    
      event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
    
      constructor() public {
        owner = msg.sender;
      }
    
      modifier onlyOwner() {
        require(msg.sender == owner);
        _;
      }
    
      function transferOwnership(address newOwner) public onlyOwner {
        require(newOwner != address(0));
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
      }
    
    }
    
    contract BasicToken is ERC20Basic {
      using SafeMath for uint256;
    
      mapping(address => uint256) balances;
    
      uint256 totalSupply_;
    
    
      function totalSupply() public view returns (uint256) {
        return totalSupply_;
      }
    
    
      function transfer(address _to, uint256 _value) public returns (bool) {
        require(_to != address(0));
        require(_value <= balances[msg.sender]);
    
        // SafeMath.sub will throw if there is not enough balance.
        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);
        emit Transfer(msg.sender, _to, _value);
        return true;
      }
    
    
      function balanceOf(address _owner) public view returns (uint256 balance) {
        return balances[_owner];
      }
    
    }
    
    contract BurnableToken is BasicToken {
    
      event Burn(address indexed burner, uint256 value);
    
      function burn(uint256 _value) public {
        _burn(msg.sender, _value);
      }
    
      function _burn(address _who, uint256 _value) internal {
        require(_value <= balances[_who]);
    
        balances[_who] = balances[_who].sub(_value);
        totalSupply_ = totalSupply_.sub(_value);
        emit Burn(_who, _value);
        emit Transfer(_who, address(0), _value);
      }
    }
    
    contract ERC20Implementation is ERC20, BurnableToken, Ownable {
    
      mapping (address => mapping (address => uint256)) internal allowed;
    
      function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
        require(_to != address(0));
        require(_value <= balances[_from]);
        require(_value <= allowed[_from][msg.sender]);
    
        balances[_from] = balances[_from].sub(_value);
        balances[_to] = balances[_to].add(_value);
        allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
        emit Transfer(_from, _to, _value);
        return true;
      }
    
      function approve(address _spender, uint256 _value) public returns (bool) {
        allowed[msg.sender][_spender] = _value;
        emit Approval(msg.sender, _spender, _value);
        return true;
      }
    
      function allowance(address _owner, address _spender) public view returns (uint256) {
        return allowed[_owner][_spender];
      }
    
      function increaseApproval(address _spender, uint _addedValue) public returns (bool) {
        allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
        emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
      }
    
      function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) {
        uint oldValue = allowed[msg.sender][_spender];
        if (_subtractedValue > oldValue) {
          allowed[msg.sender][_spender] = 0;
        } else {
          allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
        }
        emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
      }
    }
    
    
    
    contract BasicFreezableToken is ERC20Implementation {
    
      address[] internal investors;
      mapping (address => bool) internal isInvestor;
      bool frozen;
    
      function transfer(address _to, uint256 _value) public returns (bool) {
        require(!frozen);
        require(_to != address(0));
        require(_value <= balances[msg.sender]);
        
        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);
        emit Transfer(msg.sender, _to, _value);
        return true;
      }
    
    }
    
    contract ERC20FreezableImplementation is BasicFreezableToken {
    
      function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
        require(!frozen);
        require(_to != address(0));
        require(_value <= balances[_from]);
        require(_value <= allowed[_from][msg.sender]);
    
        balances[_from] = balances[_from].sub(_value);
        balances[_to] = balances[_to].add(_value);
        allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
        emit Transfer(_from, _to, _value);
        return true;
      }
    
      function approve(address _spender, uint256 _value) public returns (bool) {
        require(!frozen);
        allowed[msg.sender][_spender] = _value;
        emit Approval(msg.sender, _spender, _value);
        return true;
      }
    
      function increaseApproval(address _spender, uint _addedValue) public returns (bool) {
        require(!frozen);
        allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
        emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
      }
    
      function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) {
        require(!frozen);
        uint oldValue = allowed[msg.sender][_spender];
        if (_subtractedValue > oldValue) {
          allowed[msg.sender][_spender] = 0;
        } else {
          allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
        }
        emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
      }
    
    
      function freeze() onlyOwner public {
        frozen = true;
      }
    
    
      function unFreeze() onlyOwner public {
        frozen = false;
      }
    
    }
    
    contract OIOToken is ERC20FreezableImplementation {
    
      string public name;
      string public symbol;
      uint8 public decimals;
      
      
      constructor(address[] _investors, uint256[] _tokenAmount, uint256 _totalSupply, string _name, string _symbol, uint8 _decimals) public {
        require(_investors.length == _tokenAmount.length);
    
        name = _name;
        symbol = _symbol;
        decimals = _decimals;
        
        uint256 dif = 0;
        totalSupply_ = _totalSupply;
        for (uint i=0; i<_investors.length; i++) {
          balances[_investors[i]] = balances[_investors[i]].add(_tokenAmount[i]);
          isInvestor[_investors[i]] = true;
          investors.push(_investors[i]);
          dif = dif.add(_tokenAmount[i]);
        }
        balances[msg.sender] = totalSupply_.sub(dif);
        isInvestor[msg.sender] = true;
        investors.push(msg.sender);
        frozen = false;
      }
    
      
      function transferBack(address _from, uint256 _tokenAmount) onlyOwner public {
        require(_from != address(0));
        require(_tokenAmount <= balances[_from]);
        
        balances[_from] = balances[_from].sub(_tokenAmount);
        balances[msg.sender] = balances[msg.sender].add(_tokenAmount);
        emit Transfer(_from, msg.sender, _tokenAmount);
      }
    
     
      function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
        require(!frozen);
        require(_to != address(0));
        require(_value <= balances[_from]);
        require(_value <= allowed[_from][msg.sender]);
    
        balances[_from] = balances[_from].sub(_value);
        balances[_to] = balances[_to].add(_value);
        allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
        if (!isInvestor[_to]) {
          isInvestor[_to] = true;
          investors.push(_to);
        }
        emit Transfer(_from, _to, _value);
        return true;
      }
    
     
      function transfer(address _to, uint256 _value) public returns (bool) {
        require(!frozen);
        require(_to != address(0));
        require(_value <= balances[msg.sender]);
    
        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);
        if (!isInvestor[_to]) {
          isInvestor[_to] = true;
          investors.push(_to);
        }
        emit Transfer(msg.sender, _to, _value);
        return true;
      }
    
      
      function transferBulk(address[] _toAccounts, uint256[] _tokenAmount) onlyOwner public {
        require(_toAccounts.length == _tokenAmount.length);
        for(uint i=0; i<_toAccounts.length; i++) {
          balances[msg.sender] = balances[msg.sender].sub(_tokenAmount[i]); 
          balances[_toAccounts[i]] = balances[_toAccounts[i]].add(_tokenAmount[i]);
          if(!isInvestor[_toAccounts[i]]){
            isInvestor[_toAccounts[i]] = true;
            investors.push(_toAccounts[i]);
          }
        }
      }
    
      
      function getInvestorsAndTheirBalances() public view returns (address[], uint[]) {
          uint[] memory tempBalances = new uint[](investors.length);
          for(uint i=0; i<investors.length; i++) {
            tempBalances[i] = balances[investors[i]];
          }
           return (investors, tempBalances);
      }
    
    }