ETH Price: $1,974.08 (+1.86%)

Transaction Decoder

Block:
5077140 at Feb-12-2018 01:32:42 PM +UTC
Transaction Fee:
0.00028374 ETH $0.56
Gas Used:
47,290 Gas / 6 Gwei

Emitted Events:

80 Object.Mint( to=[Sender] 0x2673f5abf4a3cc5da45e8eff66b20164918bf22b, amount=1000000000000000000 )
81 Object.Transfer( from=0x0000000000000000000000000000000000000000, to=[Sender] 0x2673f5abf4a3cc5da45e8eff66b20164918bf22b, value=1000000000000000000 )
82 FreeShop.ObjectPurchase( purchaser=[Sender] 0x2673f5abf4a3cc5da45e8eff66b20164918bf22b, beneficiary=[Sender] 0x2673f5abf4a3cc5da45e8eff66b20164918bf22b, value=0, amount=1000000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x234FcB7f...03A261cf9
0x2673f5Ab...4918BF22B
0.060773027000000001 Eth
Nonce: 41
0.060489287000000001 Eth
Nonce: 42
0.00028374
(F2Pool Old)
3,017.120013671557332584 Eth3,017.120297411557332584 Eth0.00028374

Execution Trace

FreeShop.CALL( )
  • Object.mint( _to=0x2673f5AbF4a3CC5da45e8eFF66B20164918BF22B, _amount=1000000000000000000 ) => ( True )
  • Null: 0x000...000.CALL( )
    File 1 of 2: FreeShop
    pragma solidity ^0.4.18;
    
    // zeppelin-solidity: 1.5.0
    
    /**
     * @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;
      }
    
    }
    
    /**
     * @title ERC20Basic
     * @dev Simpler version of ERC20 interface
     * @dev see https://github.com/ethereum/EIPs/issues/179
     */
    contract ERC20Basic {
      uint256 public totalSupply;
      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);
    }
    
    /**
     * @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 Basic token
     * @dev Basic version of StandardToken, with no allowances.
     */
    contract BasicToken is ERC20Basic {
      using SafeMath for uint256;
    
      mapping(address => uint256) balances;
    
      /**
      * @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, 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);
        Transfer(msg.sender, _to, _value);
        return true;
      }
    
      /**
      * @dev Gets the balance of the specified address.
      * @param _owner The address to query the the balance of.
      * @return An uint256 representing the amount owned by the passed address.
      */
      function balanceOf(address _owner) public view returns (uint256 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) 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);
    }
    
    /**
     * @title Standard ERC20 token
     *
     * @dev Implementation of the basic standard 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 ERC20, BasicToken {
    
      mapping (address => mapping (address => uint256)) internal 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 uint256 the amount of tokens to be transferred
       */
      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);
        Transfer(_from, _to, _value);
        return true;
      }
    
      /**
       * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
       *
       * Beware that changing an allowance with this method brings the risk that someone may use both the old
       * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
       * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
       * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
       * @param _spender The address which will spend the funds.
       * @param _value The amount of tokens to be spent.
       */
      function approve(address _spender, uint256 _value) public returns (bool) {
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
      }
    
      /**
       * @dev Function to check the amount of tokens that 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 uint256 specifying the amount of tokens still available for the spender.
       */
      function allowance(address _owner, address _spender) public view returns (uint256) {
        return allowed[_owner][_spender];
      }
    
      /**
       * @dev Increase the amount of tokens that an owner allowed to a spender.
       *
       * approve should be called when allowed[_spender] == 0. To increment
       * allowed value is better to use this function to avoid 2 calls (and wait until
       * the first transaction is mined)
       * From MonolithDAO Token.sol
       * @param _spender The address which will spend the funds.
       * @param _addedValue The amount of tokens to increase the allowance by.
       */
      function increaseApproval(address _spender, uint _addedValue) public returns (bool) {
        allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
        Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
      }
    
      /**
       * @dev Decrease the amount of tokens that an owner allowed to a spender.
       *
       * approve should be called when allowed[_spender] == 0. To decrement
       * allowed value is better to use this function to avoid 2 calls (and wait until
       * the first transaction is mined)
       * From MonolithDAO Token.sol
       * @param _spender The address which will spend the funds.
       * @param _subtractedValue The amount of tokens to decrease the allowance by.
       */
      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);
        }
        Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
      }
    
    }
    
    contract Object is StandardToken, Ownable {
        string public name;
        string public symbol;
        uint8 public constant decimals = 18;
        bool public mintingFinished = false;
    
        event Burn(address indexed burner, uint value);
        event Mint(address indexed to, uint amount);
        event MintFinished();
    
        modifier canMint() {
            require(!mintingFinished);
            _;
        }
    
        function Object(string _name, string _symbol) public {
            name = _name;
            symbol = _symbol;
        }
    
        function burn(uint _value) public {
            require(_value <= balances[msg.sender]);
            address burner = msg.sender;
            balances[burner] = balances[burner].sub(_value);
            totalSupply = totalSupply.sub(_value);
            Burn(burner, _value);
        }
    
        function mint(address _to, uint _amount) onlyOwner canMint public returns(bool) {
            totalSupply = totalSupply.add(_amount);
            balances[_to] = balances[_to].add(_amount);
            Mint(_to, _amount);
            Transfer(address(0), _to, _amount);
            return true;
        }
    
        function finishMinting() onlyOwner canMint public returns(bool) {
            mintingFinished = true;
            MintFinished();
            return true;
        }
    
        function transfer(address _to, uint256 _value) public returns (bool) {
            require(_to != address(0));
            require(_value <= balances[msg.sender]);
            require(_value % (1 ether) == 0); // require whole token transfers
    
            // SafeMath.sub will throw if there is not enough balance.
            balances[msg.sender] = balances[msg.sender].sub(_value);
            balances[_to] = balances[_to].add(_value);
            Transfer(msg.sender, _to, _value);
            return true;
        }
    }
    
    contract Shop is Ownable {
        using SafeMath for *;
    
        struct ShopSettings {
            address bank;
            uint32 startTime;
            uint32 endTime;
            uint fundsRaised;
            uint rate;
            uint price;
            //uint recommendedBid;
        }
    
        Object public object;
        ShopSettings public shopSettings;
    
        modifier onlyValidPurchase() {
            require(msg.value % shopSettings.price == 0); // whole numbers only
            require((now >= shopSettings.startTime && now <= shopSettings.endTime) && msg.value != 0);
            _;
        }
    
        modifier whenClosed() { // not actually implemented?
            require(now > shopSettings.endTime);
            _;
        }
    
        modifier whenOpen() {
            require(now < shopSettings.endTime);
            _;
        }
    
        modifier onlyValidAddress(address _bank) {
            require(_bank != address(0));
            _;
        }
    
        modifier onlyOne() {
            require(calculateTokens() == 1 ether);
            _;
        }
    
        modifier onlyBuyer(address _beneficiary) {
            require(_beneficiary == msg.sender);
            _;
        }
    
        event ShopClosed(uint32 date);
        event ObjectPurchase(address indexed purchaser, address indexed beneficiary, uint value, uint amount);
    
        function () external payable {
            buyObject(msg.sender);
        }
    
        function Shop(address _bank, string _name, string _symbol, uint _rate, uint32 _endTime)
        onlyValidAddress(_bank) public {
            require(_rate >= 0);
            require(_endTime > now);
            shopSettings = ShopSettings(_bank, uint32(now), _endTime, 0, _rate, 0);
            calculatePrice(); // set initial price based on initial rate
            object = new Object(_name, _symbol);
        }
    
        function buyObject(address _beneficiary) onlyValidPurchase
        onlyBuyer(_beneficiary)
        onlyValidAddress(_beneficiary) public payable {
            uint numTokens = calculateTokens();
            shopSettings.fundsRaised = shopSettings.fundsRaised.add(msg.value);
            object.mint(_beneficiary, numTokens);
            ObjectPurchase(msg.sender, _beneficiary, msg.value, numTokens);
            forwardFunds();
        }
    
        function calculateTokens() internal returns(uint) {
            // rate is literally tokens per eth in wei;
            // passing in a rate of 10 ETH (10*10^18) equates to 10 tokens per ETH, or a price of 0.1 ETH per token
            // rate is always 1/price!
            calculatePrice(); // update price
            return msg.value.mul(1 ether).div(1 ether.mul(1 ether).div(shopSettings.rate));
        }
    
        function calculatePrice() internal returns(uint) {
            shopSettings.price = (1 ether).mul(1 ether).div(shopSettings.rate); // update price based on current rate
            //shopSettings.recommendedBid = shopSettings.price.add((1 ether).div(100)); // update recommended bid based on current price
        }
    
        function closeShop() onlyOwner whenOpen public {
            shopSettings.endTime = uint32(now);
            ShopClosed(uint32(now));
        }
    
        function forwardFunds() internal {
            shopSettings.bank.transfer(msg.value);
        }
    }
    
    contract FreeShop is Shop {
    
        modifier onlyValidPurchase() { // override to require 0-ETH transactions
            require(msg.value == 0); // 0 ETH only
            require(now >= shopSettings.startTime && now <= shopSettings.endTime);
            _;
        }
    
        modifier onlyValidAddress(address _bank) { // override so we can use a bank address of 0
            _;
        }
    
        function FreeShop(string _name, string _symbol,  uint32 _endTime)
        Shop(0, _name, _symbol, 0, _endTime) public
        {}
    
        function calculateTokens() internal returns(uint) { // override to always return 1 token per 'purchase'
            return (1 ether);
        }
    
        function calculatePrice() internal returns(uint) { // override to fix divide by zero error in Shop
            shopSettings.price = 0;
        }
    
    }

    File 2 of 2: Object
    pragma solidity ^0.4.18;
    
    // zeppelin-solidity: 1.5.0
    
    /**
     * @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 ERC20Basic
     * @dev Simpler version of ERC20 interface
     * @dev see https://github.com/ethereum/EIPs/issues/179
     */
    contract ERC20Basic {
      uint256 public totalSupply;
      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);
    }
    
    /**
     * @title ERC20 interface
     * @dev see https://github.com/ethereum/EIPs/issues/20
     */
    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);
    }
    
    /**
     * @title Basic token
     * @dev Basic version of StandardToken, with no allowances.
     */
    contract BasicToken is ERC20Basic {
      using SafeMath for uint256;
    
      mapping(address => uint256) balances;
    
      /**
      * @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, 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);
        Transfer(msg.sender, _to, _value);
        return true;
      }
    
      /**
      * @dev Gets the balance of the specified address.
      * @param _owner The address to query the the balance of.
      * @return An uint256 representing the amount owned by the passed address.
      */
      function balanceOf(address _owner) public view returns (uint256 balance) {
        return balances[_owner];
      }
    
    }
    
    /**
     * @title Standard ERC20 token
     *
     * @dev Implementation of the basic standard 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 ERC20, BasicToken {
    
      mapping (address => mapping (address => uint256)) internal 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 uint256 the amount of tokens to be transferred
       */
      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);
        Transfer(_from, _to, _value);
        return true;
      }
    
      /**
       * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
       *
       * Beware that changing an allowance with this method brings the risk that someone may use both the old
       * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
       * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
       * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
       * @param _spender The address which will spend the funds.
       * @param _value The amount of tokens to be spent.
       */
      function approve(address _spender, uint256 _value) public returns (bool) {
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
      }
    
      /**
       * @dev Function to check the amount of tokens that 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 uint256 specifying the amount of tokens still available for the spender.
       */
      function allowance(address _owner, address _spender) public view returns (uint256) {
        return allowed[_owner][_spender];
      }
    
      /**
       * @dev Increase the amount of tokens that an owner allowed to a spender.
       *
       * approve should be called when allowed[_spender] == 0. To increment
       * allowed value is better to use this function to avoid 2 calls (and wait until
       * the first transaction is mined)
       * From MonolithDAO Token.sol
       * @param _spender The address which will spend the funds.
       * @param _addedValue The amount of tokens to increase the allowance by.
       */
      function increaseApproval(address _spender, uint _addedValue) public returns (bool) {
        allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
        Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
      }
    
      /**
       * @dev Decrease the amount of tokens that an owner allowed to a spender.
       *
       * approve should be called when allowed[_spender] == 0. To decrement
       * allowed value is better to use this function to avoid 2 calls (and wait until
       * the first transaction is mined)
       * From MonolithDAO Token.sol
       * @param _spender The address which will spend the funds.
       * @param _subtractedValue The amount of tokens to decrease the allowance by.
       */
      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);
        }
        Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
      }
    
    }
    
    /**
     * @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 Object is StandardToken, Ownable {
        string public name;
        string public symbol;
        uint8 public constant decimals = 18;
        bool public mintingFinished = false;
    
        event Burn(address indexed burner, uint value);
        event Mint(address indexed to, uint amount);
        event MintFinished();
    
        modifier canMint() {
            require(!mintingFinished);
            _;
        }
    
        function Object(string _name, string _symbol) public {
            name = _name;
            symbol = _symbol;
        }
    
        function burn(uint _value) public {
            require(_value <= balances[msg.sender]);
            address burner = msg.sender;
            balances[burner] = balances[burner].sub(_value);
            totalSupply = totalSupply.sub(_value);
            Burn(burner, _value);
        }
    
        function mint(address _to, uint _amount) onlyOwner canMint public returns(bool) {
            totalSupply = totalSupply.add(_amount);
            balances[_to] = balances[_to].add(_amount);
            Mint(_to, _amount);
            Transfer(address(0), _to, _amount);
            return true;
        }
    
        function finishMinting() onlyOwner canMint public returns(bool) {
            mintingFinished = true;
            MintFinished();
            return true;
        }
    
        function transfer(address _to, uint256 _value) public returns (bool) {
            require(_to != address(0));
            require(_value <= balances[msg.sender]);
            require(_value % (1 ether) == 0); // require whole token transfers
    
            // SafeMath.sub will throw if there is not enough balance.
            balances[msg.sender] = balances[msg.sender].sub(_value);
            balances[_to] = balances[_to].add(_value);
            Transfer(msg.sender, _to, _value);
            return true;
        }
    }