ETH Price: $2,003.55 (-0.97%)
Gas: 0.13 Gwei

Transaction Decoder

Block:
5117572 at Feb-19-2018 08:20:38 AM +UTC
Transaction Fee:
0.00265209 ETH $5.31
Gas Used:
88,403 Gas / 30 Gwei

Account State Difference:

  Address   Before After State Difference Code
0x89e9062B...997dC4ccf
0xC1D5E361...A2fb30F0b
0.47 Eth
Nonce: 0
0.00734791 Eth
Nonce: 1
0.46265209
0xe3954999...2541E9b18 408.213585293896480095 Eth408.673585293896480095 Eth0.46
(Ethermine)
2,767.19405843950893969 Eth2,767.19671052950893969 Eth0.00265209

Execution Trace

ETH 0.46 SimpleTGE.CALL( )
  • ETH 0.46 0xe39549998782169d1e91587a0d2e8652541e9b18.CALL( )
    pragma solidity ^0.4.17;
    
    /**
     * @title SafeMath
     * @dev Math operations with safety checks that throw on error
     */
    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;
      }
    }
    
    /**
     * @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;
      event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
      /**
       * @dev The Ownable constructor sets the original `owner` of the contract to the sender
       * account.
       */
      function Ownable() public {
        owner = msg.sender;
      }
    
      /**
       * @dev Throws if called by any account other than the owner.
       */
      modifier onlyOwner() {
        require(msg.sender == owner);
        _;
      }
    
      /**
       * @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) public onlyOwner {
        require(newOwner != address(0));
        OwnershipTransferred(owner, newOwner);
        owner = newOwner;
      }
    
    }
    
    contract SimpleTGE is Ownable {
      using SafeMath for uint256;
    
      // start and end timestamps (both inclusive) when sale is open
      uint256 public publicTGEStartBlockTimeStamp;
    
      uint256 public publicTGEEndBlockTimeStamp;
    
      // address where funds are collected
      address public fundsWallet;
    
      // amount of raised money in wei
      uint256 public weiRaised;
    
      // sale cap in wei
      uint256 public totalCapInWei;
    
      // individual cap in wei
      uint256 public individualCapInWei;
    
      // how long the TRS subscription is open after the TGE.
      uint256 public TRSOffset = 5 days;
    
      mapping (address => bool) public whitelist;
    
      address[] public contributors;
      struct Contribution {
        bool hasVested;
        uint256 weiContributed;
      }
    
      mapping (address => Contribution)  public contributions;
    
      modifier whilePublicTGEIsActive() {
        require(block.timestamp >= publicTGEStartBlockTimeStamp && block.timestamp <= publicTGEEndBlockTimeStamp);
        _;
      }
    
      modifier isWhitelisted() {
        require(whitelist[msg.sender]);
        _;
      }
    
      function blacklistAddresses(address[] addrs) external onlyOwner returns(bool) {
        require(addrs.length <= 100);
        for (uint i = 0; i < addrs.length; i++) {
          require(addrs[i] != address(0));
          whitelist[addrs[i]] = false;
        }
        return true;
      }
    
      function whitelistAddresses(address[] addrs) external onlyOwner returns(bool) {
        require(addrs.length <= 100);
        for (uint i = 0; i < addrs.length; i++) {
          require(addrs[i] != address(0));
          whitelist[addrs[i]] = true;
        }
        return true;
      }
    
      /**
       * @dev Transfer all Ether held by the contract to the address specified by owner.
       */
      function reclaimEther(address _beneficiary) external onlyOwner {
        _beneficiary.transfer(this.balance);
      }
    
      function SimpleTGE (
        address _fundsWallet,
        uint256 _publicTGEStartBlockTimeStamp,
        uint256 _publicTGEEndBlockTimeStamp,
        uint256 _individualCapInWei,
        uint256 _totalCapInWei
      ) public 
      {
        require(_publicTGEStartBlockTimeStamp >= block.timestamp);
        require(_publicTGEEndBlockTimeStamp > _publicTGEStartBlockTimeStamp);
        require(_fundsWallet != address(0));
        require(_individualCapInWei > 0);
        require(_individualCapInWei <= _totalCapInWei);
        require(_totalCapInWei > 0);
    
        fundsWallet = _fundsWallet;
        publicTGEStartBlockTimeStamp = _publicTGEStartBlockTimeStamp;
        publicTGEEndBlockTimeStamp = _publicTGEEndBlockTimeStamp;
        individualCapInWei = _individualCapInWei;
        totalCapInWei = _totalCapInWei;
      }
    
      // allows changing the individual cap.
      function changeIndividualCapInWei(uint256 _individualCapInWei) onlyOwner external returns(bool) {
          require(_individualCapInWei > 0);
          require(_individualCapInWei < totalCapInWei);
          individualCapInWei = _individualCapInWei;
          return true;
      }
    
      // low level token purchase function
      function contribute(bool _vestingDecision) internal {
        // validations
        require(msg.sender != address(0));
        require(msg.value != 0);
        require(weiRaised.add(msg.value) <= totalCapInWei);
        require(contributions[msg.sender].weiContributed.add(msg.value) <= individualCapInWei);
        // if we have not received any WEI from this address until now, then we add this address to contributors list.
        if (contributions[msg.sender].weiContributed == 0) {
          contributors.push(msg.sender);
        }
        contributions[msg.sender].weiContributed = contributions[msg.sender].weiContributed.add(msg.value);
        weiRaised = weiRaised.add(msg.value);
        contributions[msg.sender].hasVested = _vestingDecision;
        fundsWallet.transfer(msg.value);
      }
    
      function contributeAndVest() external whilePublicTGEIsActive isWhitelisted payable {
        contribute(true);
      }
    
      function contributeWithoutVesting() public whilePublicTGEIsActive isWhitelisted payable {
        contribute(false);
      }
    
      // fallback function can be used to buy tokens
      function () external payable {
        contributeWithoutVesting();
      }
    
      // Vesting logic
      // The following cases are checked for _beneficiary's actions:
      function vest(bool _vestingDecision) external isWhitelisted returns(bool) {
        bool existingDecision = contributions[msg.sender].hasVested;
        require(existingDecision != _vestingDecision);
        require(block.timestamp >= publicTGEStartBlockTimeStamp);
        require(contributions[msg.sender].weiContributed > 0);
        // Ensure vesting cannot be done once TRS starts
        if (block.timestamp > publicTGEEndBlockTimeStamp) {
          require(block.timestamp.sub(publicTGEEndBlockTimeStamp) <= TRSOffset);
        }
        contributions[msg.sender].hasVested = _vestingDecision;
        return true;
      }
    }