ETH Price: $1,864.41 (-8.27%)

Transaction Decoder

Block:
4687166 at Dec-06-2017 08:58:19 PM +UTC
Transaction Fee:
0.0027522516 ETH $5.13
Gas Used:
46,807 Gas / 58.8 Gwei

Account State Difference:

  Address   Before After State Difference Code
(F2Pool Old)
4,470.609276241890305708 Eth4,470.612028493490305708 Eth0.0027522516
0xd26114cd...edB8A0C07
0xFBb1b73C...f520fBB98
(Bittrex)
738,830.272619011263600925 Eth
Nonce: 3012422
738,830.269866759663600925 Eth
Nonce: 3012423
0.0027522516

Execution Trace

0xbe253743fa6c9eacced8f6d98f7f64a67bb764f2.6ea056a9( )
  • Controller.sweeperOf( _token=0xd26114cd6EE289AccF82350c8d8487fedB8A0C07 ) => ( 0xb2233FCEC42c588Ee71A594d9A25AA695345426c )
  • DefaultSweeper.sweep( _token=0xd26114cd6EE289AccF82350c8d8487fedB8A0C07, _amount=16014201370000000000 ) => ( True )
    • Controller.CALL( )
    • Controller.CALL( )
    • Controller.CALL( )
    • Controller.CALL( )
    • OMGToken.balanceOf( _owner=0xBE253743FA6c9eAcCed8F6D98F7F64A67BB764F2 ) => ( balance=16014201370000000000 )
    • OMGToken.transfer( _to=0xFBb1b73C4f0BDa4f67dcA266ce6Ef42f520fBB98, _value=16014201370000000000 )
    • Controller.logSweep( from=0xBE253743FA6c9eAcCed8F6D98F7F64A67BB764F2, to=0xFBb1b73C4f0BDa4f67dcA266ce6Ef42f520fBB98, token=0xd26114cd6EE289AccF82350c8d8487fedB8A0C07, amount=16014201370000000000 )
      File 1 of 3: OMGToken
      pragma solidity ^0.4.11;
      
      
      /**
       * Math operations with safety checks
       */
      library SafeMath {
        function mul(uint a, uint b) internal returns (uint) {
          uint c = a * b;
          assert(a == 0 || c / a == b);
          return c;
        }
      
        function div(uint a, uint b) internal returns (uint) {
          // assert(b > 0); // Solidity automatically throws when dividing by 0
          uint c = a / b;
          // assert(a == b * c + a % b); // There is no case in which this doesn't hold
          return c;
        }
      
        function sub(uint a, uint b) internal returns (uint) {
          assert(b <= a);
          return a - b;
        }
      
        function add(uint a, uint b) internal returns (uint) {
          uint c = a + b;
          assert(c >= a);
          return c;
        }
      
        function max64(uint64 a, uint64 b) internal constant returns (uint64) {
          return a >= b ? a : b;
        }
      
        function min64(uint64 a, uint64 b) internal constant returns (uint64) {
          return a < b ? a : b;
        }
      
        function max256(uint256 a, uint256 b) internal constant returns (uint256) {
          return a >= b ? a : b;
        }
      
        function min256(uint256 a, uint256 b) internal constant returns (uint256) {
          return a < b ? a : b;
        }
      
        function assert(bool assertion) internal {
          if (!assertion) {
            throw;
          }
        }
      }
      
      
      /**
       * @title ERC20Basic
       * @dev Simpler version of ERC20 interface
       * @dev see https://github.com/ethereum/EIPs/issues/20
       */
      contract ERC20Basic {
        uint public totalSupply;
        function balanceOf(address who) constant returns (uint);
        function transfer(address to, uint value);
        event Transfer(address indexed from, address indexed to, uint value);
      }
      
      
      /**
       * @title Basic token
       * @dev Basic version of StandardToken, with no allowances.
       */
      contract BasicToken is ERC20Basic {
        using SafeMath for uint;
      
        mapping(address => uint) balances;
      
        /**
         * @dev Fix for the ERC20 short address attack.
         */
        modifier onlyPayloadSize(uint size) {
           if(msg.data.length < size + 4) {
             throw;
           }
           _;
        }
      
        /**
        * @dev transfer token for a specified address
        * @param _to The address to transfer to.
        * @param _value The amount to be transferred.
        */
        function transfer(address _to, uint _value) onlyPayloadSize(2 * 32) {
          balances[msg.sender] = balances[msg.sender].sub(_value);
          balances[_to] = balances[_to].add(_value);
          Transfer(msg.sender, _to, _value);
        }
      
        /**
        * @dev Gets the balance of the specified address.
        * @param _owner The address to query the the balance of.
        * @return An uint representing the amount owned by the passed address.
        */
        function balanceOf(address _owner) constant returns (uint balance) {
          return balances[_owner];
        }
      
      }
      
      
      /**
       * @title ERC20 interface
       * @dev see https://github.com/ethereum/EIPs/issues/20
       */
      contract ERC20 is ERC20Basic {
        function allowance(address owner, address spender) constant returns (uint);
        function transferFrom(address from, address to, uint value);
        function approve(address spender, uint value);
        event Approval(address indexed owner, address indexed spender, uint value);
      }
      
      
      /**
       * @title Standard ERC20 token
       *
       * @dev Implemantation of the basic standart token.
       * @dev https://github.com/ethereum/EIPs/issues/20
       * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
       */
      contract StandardToken is BasicToken, ERC20 {
      
        mapping (address => mapping (address => uint)) allowed;
      
      
        /**
         * @dev Transfer tokens from one address to another
         * @param _from address The address which you want to send tokens from
         * @param _to address The address which you want to transfer to
         * @param _value uint the amout of tokens to be transfered
         */
        function transferFrom(address _from, address _to, uint _value) onlyPayloadSize(3 * 32) {
          var _allowance = allowed[_from][msg.sender];
      
          // Check is not needed because sub(_allowance, _value) will already throw if this condition is not met
          // if (_value > _allowance) throw;
      
          balances[_to] = balances[_to].add(_value);
          balances[_from] = balances[_from].sub(_value);
          allowed[_from][msg.sender] = _allowance.sub(_value);
          Transfer(_from, _to, _value);
        }
      
        /**
         * @dev Aprove the passed address to spend the specified amount of tokens on beahlf of msg.sender.
         * @param _spender The address which will spend the funds.
         * @param _value The amount of tokens to be spent.
         */
        function approve(address _spender, uint _value) {
      
          // To change the approve amount you first have to reduce the addresses`
          //  allowance to zero by calling `approve(_spender, 0)` if it is not
          //  already 0 to mitigate the race condition described here:
          //  https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
          if ((_value != 0) && (allowed[msg.sender][_spender] != 0)) throw;
      
          allowed[msg.sender][_spender] = _value;
          Approval(msg.sender, _spender, _value);
        }
      
        /**
         * @dev Function to check the amount of tokens than an owner allowed to a spender.
         * @param _owner address The address which owns the funds.
         * @param _spender address The address which will spend the funds.
         * @return A uint specifing the amount of tokens still avaible for the spender.
         */
        function allowance(address _owner, address _spender) constant returns (uint remaining) {
          return allowed[_owner][_spender];
        }
      
      }
      
      
      /**
       * @title Ownable
       * @dev The Ownable contract has an owner address, and provides basic authorization control
       * functions, this simplifies the implementation of "user permissions".
       */
      contract Ownable {
        address public owner;
      
      
        /**
         * @dev The Ownable constructor sets the original `owner` of the contract to the sender
         * account.
         */
        function Ownable() {
          owner = msg.sender;
        }
      
      
        /**
         * @dev Throws if called by any account other than the owner.
         */
        modifier onlyOwner() {
          if (msg.sender != owner) {
            throw;
          }
          _;
        }
      
      
        /**
         * @dev Allows the current owner to transfer control of the contract to a newOwner.
         * @param newOwner The address to transfer ownership to.
         */
        function transferOwnership(address newOwner) onlyOwner {
          if (newOwner != address(0)) {
            owner = newOwner;
          }
        }
      
      }
      
      
      /**
       * @title Mintable token
       * @dev Simple ERC20 Token example, with mintable token creation
       * @dev Issue: * https://github.com/OpenZeppelin/zeppelin-solidity/issues/120
       * Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
       */
      
      contract MintableToken is StandardToken, Ownable {
        event Mint(address indexed to, uint value);
        event MintFinished();
      
        bool public mintingFinished = false;
        uint public totalSupply = 0;
      
      
        modifier canMint() {
          if(mintingFinished) throw;
          _;
        }
      
        /**
         * @dev Function to mint tokens
         * @param _to The address that will recieve the minted tokens.
         * @param _amount The amount of tokens to mint.
         * @return A boolean that indicates if the operation was successful.
         */
        function mint(address _to, uint _amount) onlyOwner canMint returns (bool) {
          totalSupply = totalSupply.add(_amount);
          balances[_to] = balances[_to].add(_amount);
          Mint(_to, _amount);
          return true;
        }
      
        /**
         * @dev Function to stop minting new tokens.
         * @return True if the operation was successful.
         */
        function finishMinting() onlyOwner returns (bool) {
          mintingFinished = true;
          MintFinished();
          return true;
        }
      }
      
      
      /**
       * @title Pausable
       * @dev Base contract which allows children to implement an emergency stop mechanism.
       */
      contract Pausable is Ownable {
        event Pause();
        event Unpause();
      
        bool public paused = false;
      
      
        /**
         * @dev modifier to allow actions only when the contract IS paused
         */
        modifier whenNotPaused() {
          if (paused) throw;
          _;
        }
      
        /**
         * @dev modifier to allow actions only when the contract IS NOT paused
         */
        modifier whenPaused {
          if (!paused) throw;
          _;
        }
      
        /**
         * @dev called by the owner to pause, triggers stopped state
         */
        function pause() onlyOwner whenNotPaused returns (bool) {
          paused = true;
          Pause();
          return true;
        }
      
        /**
         * @dev called by the owner to unpause, returns to normal state
         */
        function unpause() onlyOwner whenPaused returns (bool) {
          paused = false;
          Unpause();
          return true;
        }
      }
      
      
      /**
       * Pausable token
       *
       * Simple ERC20 Token example, with pausable token creation
       **/
      
      contract PausableToken is StandardToken, Pausable {
      
        function transfer(address _to, uint _value) whenNotPaused {
          super.transfer(_to, _value);
        }
      
        function transferFrom(address _from, address _to, uint _value) whenNotPaused {
          super.transferFrom(_from, _to, _value);
        }
      }
      
      
      /**
       * @title TokenTimelock
       * @dev TokenTimelock is a token holder contract that will allow a
       * beneficiary to extract the tokens after a time has passed
       */
      contract TokenTimelock {
      
        // ERC20 basic token contract being held
        ERC20Basic token;
      
        // beneficiary of tokens after they are released
        address beneficiary;
      
        // timestamp where token release is enabled
        uint releaseTime;
      
        function TokenTimelock(ERC20Basic _token, address _beneficiary, uint _releaseTime) {
          require(_releaseTime > now);
          token = _token;
          beneficiary = _beneficiary;
          releaseTime = _releaseTime;
        }
      
        /**
         * @dev beneficiary claims tokens held by time lock
         */
        function claim() {
          require(msg.sender == beneficiary);
          require(now >= releaseTime);
      
          uint amount = token.balanceOf(this);
          require(amount > 0);
      
          token.transfer(beneficiary, amount);
        }
      }
      
      
      /**
       * @title OMGToken
       * @dev Omise Go Token contract
       */
      contract OMGToken is PausableToken, MintableToken {
        using SafeMath for uint256;
      
        string public name = "OMGToken";
        string public symbol = "OMG";
        uint public decimals = 18;
      
        /**
         * @dev mint timelocked tokens
         */
        function mintTimelocked(address _to, uint256 _amount, uint256 _releaseTime)
          onlyOwner canMint returns (TokenTimelock) {
      
          TokenTimelock timelock = new TokenTimelock(this, _to, _releaseTime);
          mint(timelock, _amount);
      
          return timelock;
        }
      
      }

      File 2 of 3: Controller
      pragma solidity ^0.4.10;
      
      // Copyright 2017 Bittrex
      
      contract AbstractSweeper {
          function sweep(address token, uint amount) returns (bool);
      
          function () { throw; }
      
          Controller controller;
      
          function AbstractSweeper(address _controller) {
              controller = Controller(_controller);
          }
      
          modifier canSweep() {
              if (msg.sender != controller.authorizedCaller() && msg.sender != controller.owner()) throw;
              if (controller.halted()) throw;
              _;
          }
      }
      
      contract Token {
          function balanceOf(address a) returns (uint) {
              (a);
              return 0;
          }
      
          function transfer(address a, uint val) returns (bool) {
              (a);
              (val);
              return false;
          }
      }
      
      contract DefaultSweeper is AbstractSweeper {
          function DefaultSweeper(address controller)
                   AbstractSweeper(controller) {}
      
          function sweep(address _token, uint _amount)
          canSweep
          returns (bool) {
              bool success = false;
              address destination = controller.destination();
      
              if (_token != address(0)) {
                  Token token = Token(_token);
                  uint amount = _amount;
                  if (amount > token.balanceOf(this)) {
                      return false;
                  }
      
                  success = token.transfer(destination, amount);
              }
              else {
                  uint amountInWei = _amount;
                  if (amountInWei > this.balance) {
                      return false;
                  }
      
                  success = destination.send(amountInWei);
              }
      
              if (success) {
                  controller.logSweep(this, destination, _token, _amount);
              }
              return success;
          }
      }
      
      contract UserWallet {
          AbstractSweeperList sweeperList;
          function UserWallet(address _sweeperlist) {
              sweeperList = AbstractSweeperList(_sweeperlist);
          }
      
          function () public payable { }
      
          function tokenFallback(address _from, uint _value, bytes _data) {
              (_from);
              (_value);
              (_data);
           }
      
          function sweep(address _token, uint _amount)
          returns (bool) {
              (_amount);
              return sweeperList.sweeperOf(_token).delegatecall(msg.data);
          }
      }
      
      contract AbstractSweeperList {
          function sweeperOf(address _token) returns (address);
      }
      
      contract Controller is AbstractSweeperList {
          address public owner;
          address public authorizedCaller;
      
          address public destination;
      
          bool public halted;
      
          event LogNewWallet(address receiver);
          event LogSweep(address indexed from, address indexed to, address indexed token, uint amount);
          
          modifier onlyOwner() {
              if (msg.sender != owner) throw; 
              _;
          }
      
          modifier onlyAuthorizedCaller() {
              if (msg.sender != authorizedCaller) throw; 
              _;
          }
      
          modifier onlyAdmins() {
              if (msg.sender != authorizedCaller && msg.sender != owner) throw; 
              _;
          }
      
          function Controller() 
          {
              owner = msg.sender;
              destination = msg.sender;
              authorizedCaller = msg.sender;
          }
      
          function changeAuthorizedCaller(address _newCaller) onlyOwner {
              authorizedCaller = _newCaller;
          }
      
          function changeDestination(address _dest) onlyOwner {
              destination = _dest;
          }
      
          function changeOwner(address _owner) onlyOwner {
              owner = _owner;
          }
      
          function makeWallet() onlyAdmins returns (address wallet)  {
              wallet = address(new UserWallet(this));
              LogNewWallet(wallet);
          }
      
          function halt() onlyAdmins {
              halted = true;
          }
      
          function start() onlyOwner {
              halted = false;
          }
      
          address public defaultSweeper = address(new DefaultSweeper(this));
          mapping (address => address) sweepers;
      
          function addSweeper(address _token, address _sweeper) onlyOwner {
              sweepers[_token] = _sweeper;
          }
      
          function sweeperOf(address _token) returns (address) {
              address sweeper = sweepers[_token];
              if (sweeper == 0) sweeper = defaultSweeper;
              return sweeper;
          }
      
          function logSweep(address from, address to, address token, uint amount) {
              LogSweep(from, to, token, amount);
          }
      }

      File 3 of 3: DefaultSweeper
      pragma solidity ^0.4.10;
      
      // Copyright 2017 Bittrex
      
      contract AbstractSweeper {
          function sweep(address token, uint amount) returns (bool);
      
          function () { throw; }
      
          Controller controller;
      
          function AbstractSweeper(address _controller) {
              controller = Controller(_controller);
          }
      
          modifier canSweep() {
              if (msg.sender != controller.authorizedCaller() && msg.sender != controller.owner()) throw;
              if (controller.halted()) throw;
              _;
          }
      }
      
      contract Token {
          function balanceOf(address a) returns (uint) {
              (a);
              return 0;
          }
      
          function transfer(address a, uint val) returns (bool) {
              (a);
              (val);
              return false;
          }
      }
      
      contract DefaultSweeper is AbstractSweeper {
          function DefaultSweeper(address controller)
                   AbstractSweeper(controller) {}
      
          function sweep(address _token, uint _amount)
          canSweep
          returns (bool) {
              bool success = false;
              address destination = controller.destination();
      
              if (_token != address(0)) {
                  Token token = Token(_token);
                  uint amount = _amount;
                  if (amount > token.balanceOf(this)) {
                      return false;
                  }
      
                  success = token.transfer(destination, amount);
              }
              else {
                  uint amountInWei = _amount;
                  if (amountInWei > this.balance) {
                      return false;
                  }
      
                  success = destination.send(amountInWei);
              }
      
              if (success) {
                  controller.logSweep(this, destination, _token, _amount);
              }
              return success;
          }
      }
      
      contract UserWallet {
          AbstractSweeperList sweeperList;
          function UserWallet(address _sweeperlist) {
              sweeperList = AbstractSweeperList(_sweeperlist);
          }
      
          function () public payable { }
      
          function tokenFallback(address _from, uint _value, bytes _data) {
              (_from);
              (_value);
              (_data);
           }
      
          function sweep(address _token, uint _amount)
          returns (bool) {
              (_amount);
              return sweeperList.sweeperOf(_token).delegatecall(msg.data);
          }
      }
      
      contract AbstractSweeperList {
          function sweeperOf(address _token) returns (address);
      }
      
      contract Controller is AbstractSweeperList {
          address public owner;
          address public authorizedCaller;
      
          address public destination;
      
          bool public halted;
      
          event LogNewWallet(address receiver);
          event LogSweep(address indexed from, address indexed to, address indexed token, uint amount);
          
          modifier onlyOwner() {
              if (msg.sender != owner) throw; 
              _;
          }
      
          modifier onlyAuthorizedCaller() {
              if (msg.sender != authorizedCaller) throw; 
              _;
          }
      
          modifier onlyAdmins() {
              if (msg.sender != authorizedCaller && msg.sender != owner) throw; 
              _;
          }
      
          function Controller() 
          {
              owner = msg.sender;
              destination = msg.sender;
              authorizedCaller = msg.sender;
          }
      
          function changeAuthorizedCaller(address _newCaller) onlyOwner {
              authorizedCaller = _newCaller;
          }
      
          function changeDestination(address _dest) onlyOwner {
              destination = _dest;
          }
      
          function changeOwner(address _owner) onlyOwner {
              owner = _owner;
          }
      
          function makeWallet() onlyAdmins returns (address wallet)  {
              wallet = address(new UserWallet(this));
              LogNewWallet(wallet);
          }
      
          function halt() onlyAdmins {
              halted = true;
          }
      
          function start() onlyOwner {
              halted = false;
          }
      
          address public defaultSweeper = address(new DefaultSweeper(this));
          mapping (address => address) sweepers;
      
          function addSweeper(address _token, address _sweeper) onlyOwner {
              sweepers[_token] = _sweeper;
          }
      
          function sweeperOf(address _token) returns (address) {
              address sweeper = sweepers[_token];
              if (sweeper == 0) sweeper = defaultSweeper;
              return sweeper;
          }
      
          function logSweep(address from, address to, address token, uint amount) {
              LogSweep(from, to, token, amount);
          }
      }