ETH Price: $1,966.27 (-0.87%)

Transaction Decoder

Block:
4114133 at Aug-04-2017 01:56:12 AM +UTC
Transaction Fee:
0.002225538 ETH $4.38
Gas Used:
43,638 Gas / 51 Gwei

Emitted Events:

Account State Difference:

  Address   Before After State Difference Code
(ethfans.org)
1,529.16297456383741025 Eth1,529.16520010183741025 Eth0.002225538
0xa7447644...4d7D4aC0d
0xFBb1b73C...f520fBB98
(Bittrex)
216,592.602800306687777118 Eth
Nonce: 712713
216,592.600574768687777118 Eth
Nonce: 712714
0.002225538

Execution Trace

0xa546736585438999799501aedcc3e3563da27218.6ea056a9( )
  • Controller.sweeperOf( _token=0xa74476443119A942dE498590Fe1f2454d7D4aC0d ) => ( 0x88de41a34871E239C52926F920efB4EEFa0f3dE3 )
  • 0x88de41a34871e239c52926f920efb4eefa0f3de3.6ea056a9( )
    • Controller.CALL( )
    • Controller.CALL( )
    • GolemNetworkToken.balanceOf( _owner=0xA546736585438999799501AeDCc3e3563dA27218 ) => ( 18179272485720000000000 )
    • Controller.CALL( )
    • GolemNetworkToken.transfer( _to=0xFBb1b73C4f0BDa4f67dcA266ce6Ef42f520fBB98, _value=18179272485720000000000 ) => ( True )
    • Controller.logSweep( from=0xA546736585438999799501AeDCc3e3563dA27218, token=0xa74476443119A942dE498590Fe1f2454d7D4aC0d, amount=18179272485720000000000 )
      File 1 of 2: GolemNetworkToken
      pragma solidity ^0.4.4;
      
      
      /// @title Golem Network Token (GNT) - crowdfunding code for Golem Project
      contract GolemNetworkToken {
          string public constant name = "Golem Network Token";
          string public constant symbol = "GNT";
          uint8 public constant decimals = 18;  // 18 decimal places, the same as ETH.
      
          uint256 public constant tokenCreationRate = 1000;
      
          // The funding cap in weis.
          uint256 public constant tokenCreationCap = 820000 ether * tokenCreationRate;
          uint256 public constant tokenCreationMin = 150000 ether * tokenCreationRate;
      
          uint256 public fundingStartBlock;
          uint256 public fundingEndBlock;
      
          // The flag indicates if the GNT contract is in Funding state.
          bool public funding = true;
      
          // Receives ETH and its own GNT endowment.
          address public golemFactory;
      
          // Has control over token migration to next version of token.
          address public migrationMaster;
      
          GNTAllocation lockedAllocation;
      
          // The current total token supply.
          uint256 totalTokens;
      
          mapping (address => uint256) balances;
      
          address public migrationAgent;
          uint256 public totalMigrated;
      
          event Transfer(address indexed _from, address indexed _to, uint256 _value);
          event Migrate(address indexed _from, address indexed _to, uint256 _value);
          event Refund(address indexed _from, uint256 _value);
      
          function GolemNetworkToken(address _golemFactory,
                                     address _migrationMaster,
                                     uint256 _fundingStartBlock,
                                     uint256 _fundingEndBlock) {
      
              if (_golemFactory == 0) throw;
              if (_migrationMaster == 0) throw;
              if (_fundingStartBlock <= block.number) throw;
              if (_fundingEndBlock   <= _fundingStartBlock) throw;
      
              lockedAllocation = new GNTAllocation(_golemFactory);
              migrationMaster = _migrationMaster;
              golemFactory = _golemFactory;
              fundingStartBlock = _fundingStartBlock;
              fundingEndBlock = _fundingEndBlock;
          }
      
          /// @notice Transfer `_value` GNT tokens from sender's account
          /// `msg.sender` to provided account address `_to`.
          /// @notice This function is disabled during the funding.
          /// @dev Required state: Operational
          /// @param _to The address of the tokens recipient
          /// @param _value The amount of token to be transferred
          /// @return Whether the transfer was successful or not
          function transfer(address _to, uint256 _value) returns (bool) {
              // Abort if not in Operational state.
              if (funding) throw;
      
              var senderBalance = balances[msg.sender];
              if (senderBalance >= _value && _value > 0) {
                  senderBalance -= _value;
                  balances[msg.sender] = senderBalance;
                  balances[_to] += _value;
                  Transfer(msg.sender, _to, _value);
                  return true;
              }
              return false;
          }
      
          function totalSupply() external constant returns (uint256) {
              return totalTokens;
          }
      
          function balanceOf(address _owner) external constant returns (uint256) {
              return balances[_owner];
          }
      
          // Token migration support:
      
          /// @notice Migrate tokens to the new token contract.
          /// @dev Required state: Operational Migration
          /// @param _value The amount of token to be migrated
          function migrate(uint256 _value) external {
              // Abort if not in Operational Migration state.
              if (funding) throw;
              if (migrationAgent == 0) throw;
      
              // Validate input value.
              if (_value == 0) throw;
              if (_value > balances[msg.sender]) throw;
      
              balances[msg.sender] -= _value;
              totalTokens -= _value;
              totalMigrated += _value;
              MigrationAgent(migrationAgent).migrateFrom(msg.sender, _value);
              Migrate(msg.sender, migrationAgent, _value);
          }
      
          /// @notice Set address of migration target contract and enable migration
      	/// process.
          /// @dev Required state: Operational Normal
          /// @dev State transition: -> Operational Migration
          /// @param _agent The address of the MigrationAgent contract
          function setMigrationAgent(address _agent) external {
              // Abort if not in Operational Normal state.
              if (funding) throw;
              if (migrationAgent != 0) throw;
              if (msg.sender != migrationMaster) throw;
              migrationAgent = _agent;
          }
      
          function setMigrationMaster(address _master) external {
              if (msg.sender != migrationMaster) throw;
              if (_master == 0) throw;
              migrationMaster = _master;
          }
      
          // Crowdfunding:
      
          /// @notice Create tokens when funding is active.
          /// @dev Required state: Funding Active
          /// @dev State transition: -> Funding Success (only if cap reached)
          function create() payable external {
              // Abort if not in Funding Active state.
              // The checks are split (instead of using or operator) because it is
              // cheaper this way.
              if (!funding) throw;
              if (block.number < fundingStartBlock) throw;
              if (block.number > fundingEndBlock) throw;
      
              // Do not allow creating 0 or more than the cap tokens.
              if (msg.value == 0) throw;
              if (msg.value > (tokenCreationCap - totalTokens) / tokenCreationRate)
                  throw;
      
              var numTokens = msg.value * tokenCreationRate;
              totalTokens += numTokens;
      
              // Assign new tokens to the sender
              balances[msg.sender] += numTokens;
      
              // Log token creation event
              Transfer(0, msg.sender, numTokens);
          }
      
          /// @notice Finalize crowdfunding
          /// @dev If cap was reached or crowdfunding has ended then:
          /// create GNT for the Golem Factory and developer,
          /// transfer ETH to the Golem Factory address.
          /// @dev Required state: Funding Success
          /// @dev State transition: -> Operational Normal
          function finalize() external {
              // Abort if not in Funding Success state.
              if (!funding) throw;
              if ((block.number <= fundingEndBlock ||
                   totalTokens < tokenCreationMin) &&
                  totalTokens < tokenCreationCap) throw;
      
              // Switch to Operational state. This is the only place this can happen.
              funding = false;
      
              // Create additional GNT for the Golem Factory and developers as
              // the 18% of total number of tokens.
              // All additional tokens are transfered to the account controller by
              // GNTAllocation contract which will not allow using them for 6 months.
              uint256 percentOfTotal = 18;
              uint256 additionalTokens =
                  totalTokens * percentOfTotal / (100 - percentOfTotal);
              totalTokens += additionalTokens;
              balances[lockedAllocation] += additionalTokens;
              Transfer(0, lockedAllocation, additionalTokens);
      
              // Transfer ETH to the Golem Factory address.
              if (!golemFactory.send(this.balance)) throw;
          }
      
          /// @notice Get back the ether sent during the funding in case the funding
          /// has not reached the minimum level.
          /// @dev Required state: Funding Failure
          function refund() external {
              // Abort if not in Funding Failure state.
              if (!funding) throw;
              if (block.number <= fundingEndBlock) throw;
              if (totalTokens >= tokenCreationMin) throw;
      
              var gntValue = balances[msg.sender];
              if (gntValue == 0) throw;
              balances[msg.sender] = 0;
              totalTokens -= gntValue;
      
              var ethValue = gntValue / tokenCreationRate;
              Refund(msg.sender, ethValue);
              if (!msg.sender.send(ethValue)) throw;
          }
      }
      
      
      /// @title Migration Agent interface
      contract MigrationAgent {
          function migrateFrom(address _from, uint256 _value);
      }
      
      
      /// @title GNT Allocation - Time-locked vault of tokens allocated
      /// to developers and Golem Factory
      contract GNTAllocation {
          // Total number of allocations to distribute additional tokens among
          // developers and the Golem Factory. The Golem Factory has right to 20000
          // allocations, developers to 10000 allocations, divides among individual
          // developers by numbers specified in  `allocations` table.
          uint256 constant totalAllocations = 30000;
      
          // Addresses of developer and the Golem Factory to allocations mapping.
          mapping (address => uint256) allocations;
      
          GolemNetworkToken gnt;
          uint256 unlockedAt;
      
          uint256 tokensCreated = 0;
      
          function GNTAllocation(address _golemFactory) internal {
              gnt = GolemNetworkToken(msg.sender);
              unlockedAt = now + 6 * 30 days;
      
              // For the Golem Factory:
              allocations[_golemFactory] = 20000; // 12/18 pp of 30000 allocations.
      
              // For developers:
              allocations[0x9d3F257827B17161a098d380822fa2614FF540c8] = 2500; // 25.0% of developers' allocations (10000).
              allocations[0xd7406E50b73972Fa4aa533a881af68B623Ba3F66] =  730; //  7.3% of developers' allocations.
              allocations[0xd15356D05A7990dE7eC94304B0fD538e550c09C0] =  730;
              allocations[0x3971D17B62b825b151760E2451F818BfB64489A7] =  730;
              allocations[0x95e337d09f1bc67681b1cab7ed1125ea2bae5ca8] =  730;
              allocations[0x0025C58dB686b8CEce05CB8c50C1858b63Aa396E] =  730;
              allocations[0xB127FC62dE6ca30aAc9D551591daEDdeBB2eFD7A] =  630; //  6.3% of developers' allocations.
              allocations[0x21AF2E2c240a71E9fB84e90d71c2B2AddE0D0e81] =  630;
              allocations[0x682AA1C3b3E102ACB9c97B861d595F9fbfF0f1B8] =  630;
              allocations[0x6edd429c77803606cBd6Bb501CC701a6CAD6be01] =  630;
              allocations[0x5E455624372FE11b39464e93d41D1F6578c3D9f6] =  310; //  3.1% of developers' allocations.
              allocations[0xB7c7EaD515Ca275d53e30B39D8EBEdb3F19dA244] =  138; //  1.38% of developers' allocations.
              allocations[0xD513b1c3fe31F3Fe0b1E42aa8F55e903F19f1730] =  135; //  1.35% of developers' allocations.
              allocations[0x70cac7f8E404EEFce6526823452e428b5Ab09b00] =  100; //  1.0% of developers' allocations.
              allocations[0xe0d5861e7be0fac6c85ecde6e8bf76b046a96149] =  100;
              allocations[0x17488694D2feE4377Ec718836bb9d4910E81D9Cf] =  100;
              allocations[0xb481372086dEc3ca2FCCD3EB2f462c9C893Ef3C5] =  100;
              allocations[0xFB6D91E69CD7990651f26a3aa9f8d5a89159fC92] =   70; //  0.7% of developers' allocations.
              allocations[0xE2ABdAe2980a1447F445cb962f9c0bef1B63EE13] =   70;
              allocations[0x729A5c0232712caAf365fDd03c39cb361Bd41b1C] =   70;
              allocations[0x12FBD8fef4903f62e30dD79AC7F439F573E02697] =   70;
              allocations[0x657013005e5cFAF76f75d03b465cE085d402469A] =   42; //  0.42% of developers' allocations.
              allocations[0xD0AF9f75EA618163944585bF56aCA98204d0AB66] =   25; //  0.25% of developers' allocations.
          }
      
          /// @notice Allow developer to unlock allocated tokens by transferring them
          /// from GNTAllocation to developer's address.
          function unlock() external {
              if (now < unlockedAt) throw;
      
              // During first unlock attempt fetch total number of locked tokens.
              if (tokensCreated == 0)
                  tokensCreated = gnt.balanceOf(this);
      
              var allocation = allocations[msg.sender];
              allocations[msg.sender] = 0;
              var toTransfer = tokensCreated * allocation / totalAllocations;
      
              // Will fail if allocation (and therefore toTransfer) is 0.
              if (!gnt.transfer(msg.sender, toTransfer)) throw;
          }
      }

      File 2 of 2: Controller
      pragma solidity ^0.4.4;
      
      //copyright 2017 NewAlchemy
      //Written by Dennis Peterson
      
      contract AbstractSweeper {
          //abstract:
          function sweep(address token, uint amount) returns (bool);
      
          //concrete:
          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) {return 0;}
          function transfer(address a, uint val) returns (bool) {return false;}
      }
      
      contract DefaultSweeper is AbstractSweeper {
          function DefaultSweeper(address controller) 
                   AbstractSweeper(controller) {}
      
          function sweep(address _token, uint _amount)  
          canSweep
          returns (bool) {
              Token token = Token(_token);
              uint amount = _amount;
              if (amount > token.balanceOf(this)) {
                  return false;
              }
      
              address destination = controller.destination();
      
      	// Because sweep is called with delegatecall, this typically
      	// comes from the UserWallet.
              bool success = token.transfer(destination, amount); 
              if (success) { 
                  controller.logSweep(this, _token, _amount);
              } 
              return success;
          }
      }
      
      contract UserWallet {
          AbstractSweeperList c;
          function UserWallet(address _sweeperlist) {
              c = AbstractSweeperList(_sweeperlist);
          }
      
          function sweep(address _token, uint _amount) 
          returns (bool) {
              return c.sweeperOf(_token).delegatecall(msg.data);
          }
      }
      
      contract AbstractSweeperList {
          function sweeperOf(address _token) returns (address);
      }
      
      contract Controller is AbstractSweeperList {
          address public owner;
          address public authorizedCaller;
      
          //destination defaults to same as owner
          //but is separate to allow never exposing cold storage
          address public destination; 
      
          bool public halted;
      
          event LogNewWallet(address receiver);
          event LogSweep(address from, address 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);
          }
      
          //assuming halt because caller is compromised
          //so let caller stop for speed, only owner can restart
      
          function halt() onlyAdmins {
              halted = true;
          }
      
          function start() onlyOwner {
              halted = false;
          }
      
          //***********
          //SweeperList
          //***********
          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 token, uint amount) {
              LogSweep(from, token, amount);
          }
      }