ETH Price: $1,882.91 (-0.56%)

Transaction Decoder

Block:
4968251 at Jan-25-2018 05:27:11 AM +UTC
Transaction Fee:
0.00558333 ETH $10.51
Gas Used:
62,037 Gas / 90 Gwei

Emitted Events:

11 SmartToken.Transfer( _from=[Receiver] UserWallet, _to=[Sender] 0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98, _value=5000000000000000000000 )
12 Controller.LogSweep( from=[Receiver] UserWallet, to=[Sender] 0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98, token=SmartToken, amount=5000000000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x1F573D6F...d79a7FF1C
(F2Pool Old)
6,514.404012126506792662 Eth6,514.409595456506792662 Eth0.00558333
0xFBb1b73C...f520fBB98
(Bittrex)
769,224.510816555982898173 Eth
Nonce: 4495649
769,224.505233225982898173 Eth
Nonce: 4495650
0.00558333

Execution Trace

UserWallet.sweep( _token=0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C, _amount=5000000000000000000000 ) => ( True )
  • Controller.sweeperOf( _token=0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C ) => ( 0xb2233FCEC42c588Ee71A594d9A25AA695345426c )
  • DefaultSweeper.sweep( _token=0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C, _amount=5000000000000000000000 ) => ( True )
    • Controller.CALL( )
    • Controller.CALL( )
    • Controller.CALL( )
    • Controller.CALL( )
    • SmartToken.balanceOf( 0xaCe649F083E9852C51Eb4056fD3382a610E25E65 ) => ( 5000000000004133801996 )
    • SmartToken.transfer( _to=0xFBb1b73C4f0BDa4f67dcA266ce6Ef42f520fBB98, _value=5000000000000000000000 ) => ( success=True )
    • Controller.logSweep( from=0xaCe649F083E9852C51Eb4056fD3382a610E25E65, to=0xFBb1b73C4f0BDa4f67dcA266ce6Ef42f520fBB98, token=0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C, amount=5000000000000000000000 )
      File 1 of 4: UserWallet
      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 2 of 4: SmartToken
      pragma solidity ^0.4.11;
      
      /*
          Overflow protected math functions
      */
      contract SafeMath {
          /**
              constructor
          */
          function SafeMath() {
          }
      
          /**
              @dev returns the sum of _x and _y, asserts if the calculation overflows
      
              @param _x   value 1
              @param _y   value 2
      
              @return sum
          */
          function safeAdd(uint256 _x, uint256 _y) internal returns (uint256) {
              uint256 z = _x + _y;
              assert(z >= _x);
              return z;
          }
      
          /**
              @dev returns the difference of _x minus _y, asserts if the subtraction results in a negative number
      
              @param _x   minuend
              @param _y   subtrahend
      
              @return difference
          */
          function safeSub(uint256 _x, uint256 _y) internal returns (uint256) {
              assert(_x >= _y);
              return _x - _y;
          }
      
          /**
              @dev returns the product of multiplying _x by _y, asserts if the calculation overflows
      
              @param _x   factor 1
              @param _y   factor 2
      
              @return product
          */
          function safeMul(uint256 _x, uint256 _y) internal returns (uint256) {
              uint256 z = _x * _y;
              assert(_x == 0 || z / _x == _y);
              return z;
          }
      } 
      
      /*
          Owned contract interface
      */
      contract IOwned {
          // this function isn't abstract since the compiler emits automatically generated getter functions as external
          function owner() public constant returns (address owner) { owner; }
      
          function transferOwnership(address _newOwner) public;
          function acceptOwnership() public;
      }
      
      /*
          Provides support and utilities for contract ownership
      */
      contract Owned is IOwned {
          address public owner;
          address public newOwner;
      
          event OwnerUpdate(address _prevOwner, address _newOwner);
      
          /**
              @dev constructor
          */
          function Owned() {
              owner = msg.sender;
          }
      
          // allows execution by the owner only
          modifier ownerOnly {
              assert(msg.sender == owner);
              _;
          }
      
          /**
              @dev allows transferring the contract ownership
              the new owner still need to accept the transfer
              can only be called by the contract owner
      
              @param _newOwner    new contract owner
          */
          function transferOwnership(address _newOwner) public ownerOnly {
              require(_newOwner != owner);
              newOwner = _newOwner;
          }
      
          /**
              @dev used by a new owner to accept an ownership transfer
          */
          function acceptOwnership() public {
              require(msg.sender == newOwner);
              OwnerUpdate(owner, newOwner);
              owner = newOwner;
              newOwner = 0x0;
          }
      }
      
      /*
          Token Holder interface
      */
      contract ITokenHolder is IOwned {
          function withdrawTokens(IERC20Token _token, address _to, uint256 _amount) public;
      }
      
      /*
          We consider every contract to be a 'token holder' since it's currently not possible
          for a contract to deny receiving tokens.
      
          The TokenHolder's contract sole purpose is to provide a safety mechanism that allows
          the owner to send tokens that were sent to the contract by mistake back to their sender.
      */
      contract TokenHolder is ITokenHolder, Owned {
          /**
              @dev constructor
          */
          function TokenHolder() {
          }
      
          // validates an address - currently only checks that it isn't null
          modifier validAddress(address _address) {
              require(_address != 0x0);
              _;
          }
      
          // verifies that the address is different than this contract address
          modifier notThis(address _address) {
              require(_address != address(this));
              _;
          }
      
          /**
              @dev withdraws tokens held by the contract and sends them to an account
              can only be called by the owner
      
              @param _token   ERC20 token contract address
              @param _to      account to receive the new amount
              @param _amount  amount to withdraw
          */
          function withdrawTokens(IERC20Token _token, address _to, uint256 _amount)
              public
              ownerOnly
              validAddress(_token)
              validAddress(_to)
              notThis(_to)
          {
              assert(_token.transfer(_to, _amount));
          }
      }
      
      /*
          ERC20 Standard Token interface
      */
      contract IERC20Token {
          // these functions aren't abstract since the compiler emits automatically generated getter functions as external
          function name() public constant returns (string name) { name; }
          function symbol() public constant returns (string symbol) { symbol; }
          function decimals() public constant returns (uint8 decimals) { decimals; }
          function totalSupply() public constant returns (uint256 totalSupply) { totalSupply; }
          function balanceOf(address _owner) public constant returns (uint256 balance) { _owner; balance; }
          function allowance(address _owner, address _spender) public constant returns (uint256 remaining) { _owner; _spender; remaining; }
      
          function transfer(address _to, uint256 _value) public returns (bool success);
          function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
          function approve(address _spender, uint256 _value) public returns (bool success);
      }
      
      /**
          ERC20 Standard Token implementation
      */
      contract ERC20Token is IERC20Token, SafeMath {
          string public standard = 'Token 0.1';
          string public name = '';
          string public symbol = '';
          uint8 public decimals = 0;
          uint256 public totalSupply = 0;
          mapping (address => uint256) public balanceOf;
          mapping (address => mapping (address => uint256)) public allowance;
      
          event Transfer(address indexed _from, address indexed _to, uint256 _value);
          event Approval(address indexed _owner, address indexed _spender, uint256 _value);
      
          /**
              @dev constructor
      
              @param _name        token name
              @param _symbol      token symbol
              @param _decimals    decimal points, for display purposes
          */
          function ERC20Token(string _name, string _symbol, uint8 _decimals) {
              require(bytes(_name).length > 0 && bytes(_symbol).length > 0); // validate input
      
              name = _name;
              symbol = _symbol;
              decimals = _decimals;
          }
      
          // validates an address - currently only checks that it isn't null
          modifier validAddress(address _address) {
              require(_address != 0x0);
              _;
          }
      
          /**
              @dev send coins
              throws on any error rather then return a false flag to minimize user errors
      
              @param _to      target address
              @param _value   transfer amount
      
              @return true if the transfer was successful, false if it wasn't
          */
          function transfer(address _to, uint256 _value)
              public
              validAddress(_to)
              returns (bool success)
          {
              balanceOf[msg.sender] = safeSub(balanceOf[msg.sender], _value);
              balanceOf[_to] = safeAdd(balanceOf[_to], _value);
              Transfer(msg.sender, _to, _value);
              return true;
          }
      
          /**
              @dev an account/contract attempts to get the coins
              throws on any error rather then return a false flag to minimize user errors
      
              @param _from    source address
              @param _to      target address
              @param _value   transfer amount
      
              @return true if the transfer was successful, false if it wasn't
          */
          function transferFrom(address _from, address _to, uint256 _value)
              public
              validAddress(_from)
              validAddress(_to)
              returns (bool success)
          {
              allowance[_from][msg.sender] = safeSub(allowance[_from][msg.sender], _value);
              balanceOf[_from] = safeSub(balanceOf[_from], _value);
              balanceOf[_to] = safeAdd(balanceOf[_to], _value);
              Transfer(_from, _to, _value);
              return true;
          }
      
          /**
              @dev allow another account/contract to spend some tokens on your behalf
              throws on any error rather then return a false flag to minimize user errors
      
              also, to minimize the risk of the approve/transferFrom attack vector
              (see https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/), approve has to be called twice
              in 2 separate transactions - once to change the allowance to 0 and secondly to change it to the new allowance value
      
              @param _spender approved address
              @param _value   allowance amount
      
              @return true if the approval was successful, false if it wasn't
          */
          function approve(address _spender, uint256 _value)
              public
              validAddress(_spender)
              returns (bool success)
          {
              // if the allowance isn't 0, it can only be updated to 0 to prevent an allowance change immediately after withdrawal
              require(_value == 0 || allowance[msg.sender][_spender] == 0);
      
              allowance[msg.sender][_spender] = _value;
              Approval(msg.sender, _spender, _value);
              return true;
          }
      }
      
      /*
          Smart Token interface
      */
      contract ISmartToken is ITokenHolder, IERC20Token {
          function disableTransfers(bool _disable) public;
          function issue(address _to, uint256 _amount) public;
          function destroy(address _from, uint256 _amount) public;
      }
      
      /*
          Smart Token v0.2
      
          'Owned' is specified here for readability reasons
      */
      contract SmartToken is ISmartToken, ERC20Token, Owned, TokenHolder {
          string public version = '0.2';
      
          bool public transfersEnabled = true;    // true if transfer/transferFrom are enabled, false if not
      
          // triggered when a smart token is deployed - the _token address is defined for forward compatibility, in case we want to trigger the event from a factory
          event NewSmartToken(address _token);
          // triggered when the total supply is increased
          event Issuance(uint256 _amount);
          // triggered when the total supply is decreased
          event Destruction(uint256 _amount);
      
          /**
              @dev constructor
      
              @param _name       token name
              @param _symbol     token short symbol, 1-6 characters
              @param _decimals   for display purposes only
          */
          function SmartToken(string _name, string _symbol, uint8 _decimals)
              ERC20Token(_name, _symbol, _decimals)
          {
              require(bytes(_symbol).length <= 6); // validate input
              NewSmartToken(address(this));
          }
      
          // allows execution only when transfers aren't disabled
          modifier transfersAllowed {
              assert(transfersEnabled);
              _;
          }
      
          /**
              @dev disables/enables transfers
              can only be called by the contract owner
      
              @param _disable    true to disable transfers, false to enable them
          */
          function disableTransfers(bool _disable) public ownerOnly {
              transfersEnabled = !_disable;
          }
      
          /**
              @dev increases the token supply and sends the new tokens to an account
              can only be called by the contract owner
      
              @param _to         account to receive the new amount
              @param _amount     amount to increase the supply by
          */
          function issue(address _to, uint256 _amount)
              public
              ownerOnly
              validAddress(_to)
              notThis(_to)
          {
              totalSupply = safeAdd(totalSupply, _amount);
              balanceOf[_to] = safeAdd(balanceOf[_to], _amount);
      
              Issuance(_amount);
              Transfer(this, _to, _amount);
          }
      
          /**
              @dev removes tokens from an account and decreases the token supply
              can only be called by the contract owner
      
              @param _from       account to remove the amount from
              @param _amount     amount to decrease the supply by
          */
          function destroy(address _from, uint256 _amount)
              public
              ownerOnly
          {
              balanceOf[_from] = safeSub(balanceOf[_from], _amount);
              totalSupply = safeSub(totalSupply, _amount);
      
              Transfer(_from, this, _amount);
              Destruction(_amount);
          }
      
          // ERC20 standard method overrides with some extra functionality
      
          /**
              @dev send coins
              throws on any error rather then return a false flag to minimize user errors
              note that when transferring to the smart token's address, the coins are actually destroyed
      
              @param _to      target address
              @param _value   transfer amount
      
              @return true if the transfer was successful, false if it wasn't
          */
          function transfer(address _to, uint256 _value) public transfersAllowed returns (bool success) {
              assert(super.transfer(_to, _value));
      
              // transferring to the contract address destroys tokens
              if (_to == address(this)) {
                  balanceOf[_to] -= _value;
                  totalSupply -= _value;
                  Destruction(_value);
              }
      
              return true;
          }
      
          /**
              @dev an account/contract attempts to get the coins
              throws on any error rather then return a false flag to minimize user errors
              note that when transferring to the smart token's address, the coins are actually destroyed
      
              @param _from    source address
              @param _to      target address
              @param _value   transfer amount
      
              @return true if the transfer was successful, false if it wasn't
          */
          function transferFrom(address _from, address _to, uint256 _value) public transfersAllowed returns (bool success) {
              assert(super.transferFrom(_from, _to, _value));
      
              // transferring to the contract address destroys tokens
              if (_to == address(this)) {
                  balanceOf[_to] -= _value;
                  totalSupply -= _value;
                  Destruction(_value);
              }
      
              return true;
          }
      }

      File 3 of 4: 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 4 of 4: 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);
          }
      }