ETH Price: $2,114.01 (+1.08%)

Transaction Decoder

Block:
6187468 at Aug-21-2018 12:57:50 PM +UTC
Transaction Fee:
0.0003173016 ETH $0.67
Gas Used:
151,096 Gas / 2.1 Gwei

Emitted Events:

59 LivepeerToken.Transfer( from=[Receiver] MerkleMine, to=[Sender] 0xd293c81397f762e21a10f7cb78253e44f692ea72, value=149792199720484929 )
60 LivepeerToken.Transfer( from=[Receiver] MerkleMine, to=0x281ceA258Bd51086332Fa6F225c80453154f9694, value=2291903966396607329 )
61 MerkleMine.Generate( _recipient=0x281ceA258Bd51086332Fa6F225c80453154f9694, _caller=[Sender] 0xd293c81397f762e21a10f7cb78253e44f692ea72, _recipientTokenAmount=2291903966396607329, _callerTokenAmount=149792199720484929, _block=6187468 )

Account State Difference:

  Address   Before After State Difference Code
(Nanopool)
7,667.97791843668946959 Eth7,667.97823573828946959 Eth0.0003173016
0x58b6A8A3...e733aB239
0x8e306b00...766cC15c8
(Livepeer: Merkle Mine)
0xD293C813...4f692ea72
0.171098487 Eth
Nonce: 88
0.1707811854 Eth
Nonce: 89
0.0003173016

Execution Trace

MerkleMine.generate( _recipient=0x281ceA258Bd51086332Fa6F225c80453154f9694, _merkleProof=0x56CB2FCEB66EFDF6A1F6976F5E2E80BC2D9CE8843BE8C628CC96FB9B9F6ACF712E53D1A328D7EE83F6890EE00161FE99F820F1EE570414C8698568562AA817601EF0BAAEBDA5C6310D05AEB17651FCDC119B5A6C76089BDE4A44B4B9FBD8C8A02F8B513D184EAF362DF717C39A4FA5783EC8A220C032BC379B3C02EFD3252474669496D8074E47631607F176CEC95FDB929A7A129BEB7520A471D084C155DA7F595B659717592BC6C2FC8ED28405AF5ED0503AC1D8CA5543565F8E48C630C6EAE781550EC52917713796263F2548DF29958BB747018DB0CDDC8B1492E6F0C1BCF76D69D794234A3BB72A6276F8991CE7A42EA12C9E130811EAB097289BD0A84285189FA17C2ADCF1D4EE377DDB22A66B80BAB4407C27D8A9ACFAB865052DF3FD02C37248D6A47DEE228CBBEC29C1322160C21851DAC90DE9BC2FB006247115547B5803A7CEA9732F42F163F673AEB2C0250B3FEF37C839897FB48FB43C25E0834ADC87EDAA7E5661040FD0A99631D1B287D77397A92E2129BDF0EE631FDCA67AD4C7A4AC99B3D007982355BB9DDDFFCA6AE6F025EF30320D71E01D7078C9A65A9879622E5108FFDC811AAB6B27C63B6A333932E3BAADD7F81B0BC6A5F59FF3EC44B6FAD9205BEE2805485C556AA2C8E9E6F334E7C2F992A3A4E1EBCE4F3E5B65AC41A5692CCA8B82A2C03D436C3E00B08A714F932ECE58644CFD0685B12497F0E5E590E498C7B28B5E4060E81BBFF379882CC5251004B547924D7F16A93B20EB9CAF2611660388715BC8D3554DAE199E700A8F12A6E798C3AAEF4D7C96A9D64559DE69342DF69503B70424F7D2642AFF4658E0097C4520A06FC6B25B7BBA84C1CCB9167971B92FE9762830D3F20908FB10FAFA9929ADFDE2F65A4E90327EBC1F7460F55592404A5BD804DD4060FBBAF11A6BDC0557C70C812EC5CD9AA8007ED51E74A86B2F0ACEAA39987CE1EE5E1150DC99DB6336CCA1BF9A005C776D0E3FC3 )
  • MerkleProof.verifyProof( _proof=0x56CB2FCEB66EFDF6A1F6976F5E2E80BC2D9CE8843BE8C628CC96FB9B9F6ACF712E53D1A328D7EE83F6890EE00161FE99F820F1EE570414C8698568562AA817601EF0BAAEBDA5C6310D05AEB17651FCDC119B5A6C76089BDE4A44B4B9FBD8C8A02F8B513D184EAF362DF717C39A4FA5783EC8A220C032BC379B3C02EFD3252474669496D8074E47631607F176CEC95FDB929A7A129BEB7520A471D084C155DA7F595B659717592BC6C2FC8ED28405AF5ED0503AC1D8CA5543565F8E48C630C6EAE781550EC52917713796263F2548DF29958BB747018DB0CDDC8B1492E6F0C1BCF76D69D794234A3BB72A6276F8991CE7A42EA12C9E130811EAB097289BD0A84285189FA17C2ADCF1D4EE377DDB22A66B80BAB4407C27D8A9ACFAB865052DF3FD02C37248D6A47DEE228CBBEC29C1322160C21851DAC90DE9BC2FB006247115547B5803A7CEA9732F42F163F673AEB2C0250B3FEF37C839897FB48FB43C25E0834ADC87EDAA7E5661040FD0A99631D1B287D77397A92E2129BDF0EE631FDCA67AD4C7A4AC99B3D007982355BB9DDDFFCA6AE6F025EF30320D71E01D7078C9A65A9879622E5108FFDC811AAB6B27C63B6A333932E3BAADD7F81B0BC6A5F59FF3EC44B6FAD9205BEE2805485C556AA2C8E9E6F334E7C2F992A3A4E1EBCE4F3E5B65AC41A5692CCA8B82A2C03D436C3E00B08A714F932ECE58644CFD0685B12497F0E5E590E498C7B28B5E4060E81BBFF379882CC5251004B547924D7F16A93B20EB9CAF2611660388715BC8D3554DAE199E700A8F12A6E798C3AAEF4D7C96A9D64559DE69342DF69503B70424F7D2642AFF4658E0097C4520A06FC6B25B7BBA84C1CCB9167971B92FE9762830D3F20908FB10FAFA9929ADFDE2F65A4E90327EBC1F7460F55592404A5BD804DD4060FBBAF11A6BDC0557C70C812EC5CD9AA8007ED51E74A86B2F0ACEAA39987CE1EE5E1150DC99DB6336CCA1BF9A005C776D0E3FC3, _root=53F35A304A1E1E20D6648E09BB3073CCD44A5BF1638A01355897A71E801879F8, _leaf=489F71BB60A21B5510BCA9C695FE86E705CDE832AF555AFC7655B6A281F791E2 ) => ( True )
  • LivepeerToken.transfer( _to=0xD293C81397F762E21A10F7cb78253E44f692ea72, _value=149792199720484929 ) => ( True )
  • LivepeerToken.transfer( _to=0x281ceA258Bd51086332Fa6F225c80453154f9694, _value=2291903966396607329 ) => ( True )
    File 1 of 3: MerkleMine
    pragma solidity 0.4.18;
    
    /**
     * @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 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 MerkleProof
     * @dev Merkle proof verification
     * @note Based on https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol
     */
    library MerkleProof {
      /*
       * @dev Verifies a Merkle proof proving the existence of a leaf in a Merkle tree. Assumes that each pair of leaves
       * and each pair of pre-images is sorted.
       * @param _proof Merkle proof containing sibling hashes on the branch from the leaf to the root of the Merkle tree
       * @param _root Merkle root
       * @param _leaf Leaf of Merkle tree
       */
      function verifyProof(bytes _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {
        // Check if proof length is a multiple of 32
        if (_proof.length % 32 != 0) return false;
    
        bytes32 proofElement;
        bytes32 computedHash = _leaf;
    
        for (uint256 i = 32; i <= _proof.length; i += 32) {
          assembly {
            // Load the current element of the proof
            proofElement := mload(add(_proof, i))
          }
    
          if (computedHash < proofElement) {
            // Hash(current computed hash + current element of the proof)
            computedHash = keccak256(computedHash, proofElement);
          } else {
            // Hash(current element of the proof + current computed hash)
            computedHash = keccak256(proofElement, computedHash);
          }
        }
    
        // Check if the computed hash (root) is equal to the provided root
        return computedHash == _root;
      }
    }
    
    /**
     * @title MerkleMine
     * @dev Token distribution based on providing Merkle proofs of inclusion in genesis state to generate allocation
     */
    contract MerkleMine {
        using SafeMath for uint256;
    
        // ERC20 token being distributed
        ERC20 public token;
        // Merkle root representing genesis state which encodes token recipients
        bytes32 public genesisRoot;
        // Total amount of tokens that can be generated
        uint256 public totalGenesisTokens;
        // Total number of recipients included in genesis state
        uint256 public totalGenesisRecipients;
        // Amount of tokens per recipient allocation. Equal to `totalGenesisTokens` / `totalGenesisRecipients`
        uint256 public tokensPerAllocation;
        // Minimum ETH balance threshold for recipients included in genesis state
        uint256 public balanceThreshold;
        // Block number of genesis - used to determine which ETH accounts are included in the genesis state
        uint256 public genesisBlock;
        // Start block where a third party caller (not the recipient) can generate and split the allocation with the recipient
        // As the current block gets closer to `callerAllocationEndBlock`, the caller receives a larger precentage of the allocation
        uint256 public callerAllocationStartBlock;
        // From this block onwards, a third party caller (not the recipient) can generate and claim the recipient's full allocation
        uint256 public callerAllocationEndBlock;
        // Number of blocks in the caller allocation period as defined by `callerAllocationEndBlock` - `callerAllocationStartBlock`
        uint256 public callerAllocationPeriod;
    
        // Track if the generation process is started
        bool public started;
    
        // Track the already generated allocations for recipients
        mapping (address => bool) public generated;
    
        // Check that a recipient's allocation has not been generated
        modifier notGenerated(address _recipient) {
            require(!generated[_recipient]);
            _;
        }
    
        // Check that the generation period is started
        modifier isStarted() {
            require(started);
            _;
        }
    
        // Check that the generation period is not started
        modifier isNotStarted() {
            require(!started);
            _;
        }
    
        event Generate(address indexed _recipient, address indexed _caller, uint256 _recipientTokenAmount, uint256 _callerTokenAmount, uint256 _block);
    
        /**
         * @dev MerkleMine constructor
         * @param _token ERC20 token being distributed
         * @param _genesisRoot Merkle root representing genesis state which encodes token recipients
         * @param _totalGenesisTokens Total amount of tokens that can be generated
         * @param _totalGenesisRecipients Total number of recipients included in genesis state
         * @param _balanceThreshold Minimum ETH balance threshold for recipients included in genesis state
         * @param _genesisBlock Block number of genesis - used to determine which ETH accounts are included in the genesis state
         * @param _callerAllocationStartBlock Start block where a third party caller (not the recipient) can generate and split the allocation with the recipient
         * @param _callerAllocationEndBlock From this block onwards, a third party caller (not the recipient) can generate and claim the recipient's full allocation
         */
        function MerkleMine(
            address _token,
            bytes32 _genesisRoot,
            uint256 _totalGenesisTokens,
            uint256 _totalGenesisRecipients,
            uint256 _balanceThreshold,
            uint256 _genesisBlock,
            uint256 _callerAllocationStartBlock,
            uint256 _callerAllocationEndBlock
        )
            public
        {
            // Address of token contract must not be null
            require(_token != address(0));
            // Number of recipients must be non-zero
            require(_totalGenesisRecipients > 0);
            // Genesis block must be at or before the current block
            require(_genesisBlock <= block.number);
            // Start block for caller allocation must be after current block
            require(_callerAllocationStartBlock > block.number);
            // End block for caller allocation must be after caller allocation start block
            require(_callerAllocationEndBlock > _callerAllocationStartBlock);
    
            token = ERC20(_token);
            genesisRoot = _genesisRoot;
            totalGenesisTokens = _totalGenesisTokens;
            totalGenesisRecipients = _totalGenesisRecipients;
            tokensPerAllocation = _totalGenesisTokens.div(_totalGenesisRecipients);
            balanceThreshold = _balanceThreshold;
            genesisBlock = _genesisBlock;
            callerAllocationStartBlock = _callerAllocationStartBlock;
            callerAllocationEndBlock = _callerAllocationEndBlock;
            callerAllocationPeriod = _callerAllocationEndBlock.sub(_callerAllocationStartBlock);
        }
    
        /**
         * @dev Start the generation period - first checks that this contract's balance is equal to `totalGenesisTokens`
         * The generation period must not already be started
         */
        function start() external isNotStarted {
            // Check that this contract has a sufficient balance for the generation period
            require(token.balanceOf(this) >= totalGenesisTokens);
    
            started = true;
        }
    
        /**
         * @dev Generate a recipient's token allocation. Generation period must be started. Starting from `callerAllocationStartBlock`
         * a third party caller (not the recipient) can invoke this function to generate the recipient's token
         * allocation and claim a percentage of it. The percentage of the allocation claimed by the
         * third party caller is determined by how many blocks have elapsed since `callerAllocationStartBlock`.
         * After `callerAllocationEndBlock`, a third party caller can claim the full allocation
         * @param _recipient Recipient of token allocation
         * @param _merkleProof Proof of recipient's inclusion in genesis state Merkle root
         */
        function generate(address _recipient, bytes _merkleProof) external isStarted notGenerated(_recipient) {
            // Check the Merkle proof
            bytes32 leaf = keccak256(_recipient);
            // _merkleProof must prove inclusion of _recipient in the genesis state root
            require(MerkleProof.verifyProof(_merkleProof, genesisRoot, leaf));
    
            generated[_recipient] = true;
    
            address caller = msg.sender;
    
            if (caller == _recipient) {
                // If the caller is the recipient, transfer the full allocation to the caller/recipient
                require(token.transfer(_recipient, tokensPerAllocation));
    
                Generate(_recipient, _recipient, tokensPerAllocation, 0, block.number);
            } else {
                // If the caller is not the recipient, the token allocation generation
                // can only take place if we are in the caller allocation period
                require(block.number >= callerAllocationStartBlock);
    
                uint256 callerTokenAmount = callerTokenAmountAtBlock(block.number);
                uint256 recipientTokenAmount = tokensPerAllocation.sub(callerTokenAmount);
    
                if (callerTokenAmount > 0) {
                    require(token.transfer(caller, callerTokenAmount));
                }
    
                if (recipientTokenAmount > 0) {
                    require(token.transfer(_recipient, recipientTokenAmount));
                }
    
                Generate(_recipient, caller, recipientTokenAmount, callerTokenAmount, block.number);
            }
        }
    
        /**
         * @dev Return the amount of tokens claimable by a third party caller when generating a recipient's token allocation at a given block
         * @param _blockNumber Block at which to compute the amount of tokens claimable by a third party caller
         */
        function callerTokenAmountAtBlock(uint256 _blockNumber) public view returns (uint256) {
            if (_blockNumber < callerAllocationStartBlock) {
                // If the block is before the start of the caller allocation period, the third party caller can claim nothing
                return 0;
            } else if (_blockNumber >= callerAllocationEndBlock) {
                // If the block is at or after the end block of the caller allocation period, the third party caller can claim everything
                return tokensPerAllocation;
            } else {
                // During the caller allocation period, the third party caller can claim an increasing percentage
                // of the recipient's allocation based on a linear curve - as more blocks pass in the caller allocation
                // period, the amount claimable by the third party caller increases linearly
                uint256 blocksSinceCallerAllocationStartBlock = _blockNumber.sub(callerAllocationStartBlock);
                return tokensPerAllocation.mul(blocksSinceCallerAllocationStartBlock).div(callerAllocationPeriod);
            }
        }
    }

    File 2 of 3: LivepeerToken
    /**
     *Submitted for verification at Etherscan.io on 2018-04-30
    */
    
    pragma solidity 0.4.18;
    
    /**
     * @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 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 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 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 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, uint256 amount);
      event MintFinished();
    
      bool public mintingFinished = false;
    
    
      modifier canMint() {
        require(!mintingFinished);
        _;
      }
    
      /**
       * @dev Function to mint tokens
       * @param _to The address that will receive 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, uint256 _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;
      }
    
      /**
       * @dev Function to stop minting new tokens.
       * @return True if the operation was successful.
       */
      function finishMinting() onlyOwner canMint public returns (bool) {
        mintingFinished = true;
        MintFinished();
        return true;
      }
    }
    
    contract VariableSupplyToken is MintableToken {
        event Burn(address indexed burner, uint256 value);
    
        /*
         * @dev Burns a specific amount of the sender's tokens
         * @param _value The amount of tokens to be burned
         */
        function burn(uint256 _amount) public {
            // Must not burn more than the sender owns
            require(_amount <= balances[msg.sender]);
    
            address burner = msg.sender;
            balances[burner] = balances[burner].sub(_amount);
            totalSupply = totalSupply.sub(_amount);
    
            Burn(burner, _amount);
        }
    }
    
    contract ILivepeerToken is ERC20, Ownable {
        function mint(address _to, uint256 _amount) public returns (bool);
        function burn(uint256 _amount) public;
    }
    
    contract LivepeerToken is ILivepeerToken, VariableSupplyToken {
        string public name = "Livepeer Token";
        uint8 public decimals = 18;
        string public symbol = "LPT";
        string public version = "0.1";
    }

    File 3 of 3: MerkleProof
    pragma solidity 0.4.18;
    
    /*
     * @title MerkleProof
     * @dev Merkle proof verification
     * @note Based on https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol
     */
    library MerkleProof {
      /*
       * @dev Verifies a Merkle proof proving the existence of a leaf in a Merkle tree. Assumes that each pair of leaves
       * and each pair of pre-images is sorted.
       * @param _proof Merkle proof containing sibling hashes on the branch from the leaf to the root of the Merkle tree
       * @param _root Merkle root
       * @param _leaf Leaf of Merkle tree
       */
      function verifyProof(bytes _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {
        // Check if proof length is a multiple of 32
        if (_proof.length % 32 != 0) return false;
    
        bytes32 proofElement;
        bytes32 computedHash = _leaf;
    
        for (uint256 i = 32; i <= _proof.length; i += 32) {
          assembly {
            // Load the current element of the proof
            proofElement := mload(add(_proof, i))
          }
    
          if (computedHash < proofElement) {
            // Hash(current computed hash + current element of the proof)
            computedHash = keccak256(computedHash, proofElement);
          } else {
            // Hash(current element of the proof + current computed hash)
            computedHash = keccak256(proofElement, computedHash);
          }
        }
    
        // Check if the computed hash (root) is equal to the provided root
        return computedHash == _root;
      }
    }