ETH Price: $2,139.59 (+4.96%)

Transaction Decoder

Block:
13549116 at Nov-04-2021 08:22:00 AM +UTC
Transaction Fee:
0.01972371396233415 ETH $42.20
Gas Used:
200,105 Gas / 98.56682223 Gwei

Emitted Events:

Account State Difference:

  Address   Before After State Difference Code
(F2Pool Old)
949.788537702162177128 Eth949.788757763652837103 Eth0.000220061490659975
0xa80f2C8f...e72c45d4C
0xBBEa1eBD...13711C377
0xD4C1C2E1...AAb3d8022
0.042422014033228 Eth
Nonce: 1
0.02269830007089385 Eth
Nonce: 2
0.01972371396233415

Execution Trace

TransferExclusive.transferExclusive( ) => ( 1 )
  • UniqueUtilityToken.allowance( tokenOwner=0xD74902b67d4429A50791033b4bDFEA41a7D0Bce7, spender=0xBBEa1eBD631862A1686205860d6E79913711C377 ) => ( remaining=31952689000000000000000000 )
  • UniqueUtilityToken.transferFrom( from=0xD74902b67d4429A50791033b4bDFEA41a7D0Bce7, to=0xD4C1C2E157C8f3CD5d76b856f3306dbAAb3d8022, tokens=1912000000000000000000 ) => ( success=True )
    File 1 of 2: TransferExclusive
    pragma solidity >=0.7.0 <0.9.0;
    pragma experimental ABIEncoderV2;
    
    //SPDX-License-Identifier: MIT
    
    interface IERC20 {
        function allowance(address owner, address spender) external view returns (uint256);
        function approve(address spender, uint256 amount) external returns (bool);
        function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    }
      
    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.
       */
      constructor() {
        owner = msg.sender;
      }
      /**
       * @dev Throws if called by any account other than the owner.
       */
      modifier onlyOwner() {
        require(msg.sender == owner, "Only for 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));
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
      }
    }
    
    
    contract TransferExclusive is Ownable {
        IERC20 public _tokenContract;
        address public _tokenAddress;
        address public _ownerAddress;
        
        mapping (address => uint256) claims;
        
        bytes32 _merkleRoot;
        
        struct inputModel {
            address addr;
            uint64 val;
        }
    
        constructor (address contractAddress, address ownerAddress) {
            _tokenContract = IERC20(contractAddress);
            _ownerAddress = ownerAddress;
            _tokenAddress = contractAddress;
        }
        
        function uint2str(uint _i) internal pure returns (string memory _uintAsString) {
            if (_i == 0) {
                return "0";
            }
            uint j = _i;
            uint len;
            while (j != 0) {
                len++;
                j /= 10;
            }
            bytes memory bstr = new bytes(len);
            uint k = len;
            while (_i != 0) {
                k = k-1;
                uint8 temp = (48 + uint8(_i - _i / 10 * 10));
                bytes1 b1 = bytes1(temp);
                bstr[k] = b1;
                _i /= 10;
            }
            return string(bstr);
        }
        
        function toAsciiString(address x) internal pure returns (string memory) {
            bytes memory s = new bytes(40);
            for (uint i = 0; i < 20; i++) {
                bytes1 b = bytes1(uint8(uint(uint160(x)) / (2**(8*(19 - i)))));
                bytes1 hi = bytes1(uint8(b) / 16);
                bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));
                s[2*i] = char(hi);
                s[2*i+1] = char(lo);            
            }
            return string(s);
        }
    
        function char(bytes1 b) internal pure returns (bytes1 c) {
            if (uint8(b) < 10) return bytes1(uint8(b) + 0x30);
            else return bytes1(uint8(b) + 0x57);
        }
        
        function verify(bytes32 root, bytes32 leaf, bytes32[] memory proof) private pure returns (bool)
        {
            bytes32 computedHash = leaf;
        
            for (uint256 i = 0; i < proof.length; i++) {
              bytes32 proofElement = proof[i];
        
              if (computedHash < proofElement) {
                computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
              } else {
                computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
              }
            }
        
            return computedHash == root;
        }
     
        function setMerkleRoot(bytes32 merkleRoot) public onlyOwner  {
            _merkleRoot = merkleRoot;
        }
    
        function setPrimaryContract(address contractAddress, address ownerAddress) public onlyOwner returns (uint256){
            _tokenContract = IERC20(contractAddress);
            _ownerAddress = ownerAddress;
            _tokenAddress = contractAddress;
            
            return 1;
        }
        
        function getPrimaryAllowance() public onlyOwner view returns (uint256){
            return _tokenContract.allowance(_ownerAddress, address(this));
        }
        
        function getClaimedValue(address _address) public view returns (uint256){
            return claims[_address];
        }
            
        function transferExclusive(uint256 amount, uint256 max, bytes32[] memory proof) public returns (uint256){
            require(_tokenContract.allowance(_ownerAddress, address(this)) >= amount, "Allowance too low");
            
            bytes32 leaf=keccak256(abi.encode(abi.encodePacked("0x",toAsciiString(msg.sender), uint2str(max))));
            
            require(verify(_merkleRoot, leaf, proof), "Verify failed");
            
            require(claims[msg.sender]+amount <= max, "Amount not allowed");
            
           _internalTransferFrom(_tokenContract, _ownerAddress, msg.sender, amount);
           
           return 1;
        }
        
        function _internalTransferFrom(IERC20 token, address sender, address recipient, uint256 amount) private {
            bool sent = token.transferFrom(sender, recipient, amount*100000000000000);
            
            require(sent, "Token transfer failed");
            
            claims[recipient]+=amount;
        }
    }

    File 2 of 2: UniqueUtilityToken
    pragma solidity 0.8.3;
    
    // SPDX-License-Identifier: MIT
    
    // ----------------------------------------------------------------------------
    // Safe maths
    // ----------------------------------------------------------------------------
    
    contract SafeMath {
        function safeAdd(uint a, uint b) public pure returns (uint c) {
            c = a + b;
            require(c >= a);
        }
        function safeSub(uint a, uint b) public pure returns (uint c) {
            require(b <= a);
            c = a - b;
        }
        function safeMul(uint a, uint b) public pure returns (uint c) {
            c = a * b;
            require(a == 0 || c / a == b);
        }
        function safeDiv(uint a, uint b) public pure returns (uint c) {
            require(b > 0);
            c = a / b;
        }
    }
    
    
    // ----------------------------------------------------------------------------
    // ERC Token Standard #20 Interface
    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
    // ----------------------------------------------------------------------------
    
    interface IERC20 {
        /**
         * @dev Returns the amount of tokens in existence.
         */
        function totalSupply() external view returns (uint256);
    
        function balanceOf(address account) external view returns (uint256);
    
        function transfer(address recipient, uint256 amount) external returns (bool);
    
        function allowance(address owner, address spender) external view returns (uint256);
        
        function approve(address spender, uint256 amount) external returns (bool);
    
        function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    
        event Transfer(address indexed from, address indexed to, uint256 value);
    
        event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    
    // ----------------------------------------------------------------------------
    // Contract function to receive approval and execute function in one call
    //
    // Borrowed from MiniMeToken
    // ----------------------------------------------------------------------------
    abstract contract ApproveAndCallFallBack {
        function receiveApproval(address from, uint256 tokens, address token, bytes memory data) virtual public;
    }
    
    
    // ----------------------------------------------------------------------------
    // Owned contract
    // ----------------------------------------------------------------------------
    contract Owned {
        address public owner;
        address public newOwner;
    
        event OwnershipTransferred(address indexed _from, address indexed _to);
    
        constructor()  {
            owner = 0xC7781bf45EE2C64AA6E330Bd0e35522C1d7BA6b3;
        }
    
        modifier onlyOwner {
            require(msg.sender == owner);
            _;
        }
    
        function transferOwnership(address _newOwner) public onlyOwner {
            newOwner = _newOwner;
        }
        function acceptOwnership() public {
            require(msg.sender == newOwner);
            emit OwnershipTransferred(owner, newOwner);
            owner = newOwner;
            newOwner = address(0);
        }
    }
    
    
    // ----------------------------------------------------------------------------
    // ERC20 Token, with the addition of symbol, name and decimals and assisted
    // token transfers
    // ----------------------------------------------------------------------------
    
    contract UniqueUtilityToken is IERC20, Owned, SafeMath {
        string public symbol;
        string public  name;
        uint8 public decimals;
        uint public _totalSupply;
    
        mapping(address => uint) balances;
        mapping(address => mapping(address => uint)) allowed;
    
    
        // ------------------------------------------------------------------------
        // Constructor
        // ------------------------------------------------------------------------
        
     constructor() {
            name = "Unique Utility Token";
            symbol = "UNQT";
            decimals = 18;
            _totalSupply = 100000000e18;         // 100,000,000 UNQT
            address owner = owner;
            balances[owner] = _totalSupply;
            emit Transfer(address(0), owner, _totalSupply);
        }
    
    
        // ------------------------------------------------------------------------
        // Total supply
        // ------------------------------------------------------------------------
        function totalSupply() public view override returns (uint) {
            return _totalSupply;
        }
    
    
        // ------------------------------------------------------------------------
        // Get the token balance for account tokenOwner
        // ------------------------------------------------------------------------
        function balanceOf(address tokenOwner) public view override returns (uint balance) {
            return balances[tokenOwner];
        }
    
    
        // ------------------------------------------------------------------------
        // Transfer the balance from token owner's account to to account
        // - Owner's account must have sufficient balance to transfer
        // - 0 value transfers are allowed
        // ------------------------------------------------------------------------
        function transfer(address to, uint tokens) public override returns (bool success) {
            balances[msg.sender] = safeSub(balances[msg.sender], tokens);
            balances[to] = safeAdd(balances[to], tokens);
            Transfer(msg.sender, to, tokens);
            return true;
        }
    
    
        // ------------------------------------------------------------------------
        // Token owner can approve for spender to transferFrom(...) tokens
        // from the token owner's account
        //
        // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
        // recommends that there are no checks for the approval double-spend attack
        // as this should be implemented in user interfaces 
        // ------------------------------------------------------------------------
        function approve(address spender, uint tokens) public virtual override returns (bool success) {
            allowed[msg.sender][spender] = tokens;
            Approval(msg.sender, spender, tokens);
            return true;
        }
    
        // ------------------------------------------------------------------------
        // Transfer tokens from the from account to the to account
        // 
        // The calling account must already have sufficient tokens approve(...)-d
        // for spending from the from account and
        // - From account must have sufficient balance to transfer
        // - Spender must have sufficient allowance to transfer
        // - 0 value transfers are allowed
        // ------------------------------------------------------------------------
        function transferFrom(address from, address to, uint tokens) public virtual override returns (bool success) {
            balances[from] = safeSub(balances[from], tokens);
            allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens);
            balances[to] = safeAdd(balances[to], tokens);
            Transfer(from, to, tokens);
            return true;
        }
    
    
        // ------------------------------------------------------------------------
        // Returns the amount of tokens approved by the owner that can be
        // transferred to the spender's account
        // ------------------------------------------------------------------------
        function allowance(address tokenOwner, address spender) public view virtual override  returns (uint remaining) {
            return allowed[tokenOwner][spender];
        }
    
    
        // ------------------------------------------------------------------------
        // Token owner can approve for spender to transferFrom(...) tokens
        // from the token owner's account. The spender contract function
        // receiveApproval(...) is then executed
        // ------------------------------------------------------------------------
        function approveAndCall(address spender, uint tokens, bytes memory data) public returns (bool success) {
            allowed[msg.sender][spender] = tokens;
            Approval(msg.sender, spender, tokens);
            ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, address(this), data);
            return true;
        }
    
    
        // ------------------------------------------------------------------------
        // Don't accept ETH
        // ------------------------------------------------------------------------
        receive () external payable {
            revert();
        }
    
    
        // ------------------------------------------------------------------------
        // Owner can transfer out any accidentally sent ERC20 tokens
        // ------------------------------------------------------------------------
        function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) {
            return IERC20(tokenAddress).transfer(owner, tokens);
        }
    }