ETH Price: $1,982.07 (-4.49%)

Contract

0x2950639f48eDbfc4625e0244d35987AEb4e6cB63
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

TokenTracker

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Set Approval For...241156632025-12-29 3:38:1167 days ago1766979491IN
SoundMint Vinyl: Token
0 ETH0.00009362.03318075
Set Approval For...241150732025-12-29 1:39:3567 days ago1766972375IN
SoundMint Vinyl: Token
0 ETH0.000095642.07743541
Set Approval For...240801062025-12-24 4:31:2372 days ago1766550683IN
SoundMint Vinyl: Token
0 ETH0.000093552.03159324
Set Approval For...240065732025-12-13 22:10:2383 days ago1765663823IN
SoundMint Vinyl: Token
0 ETH0.000001520.03303053
Set Approval For...239953652025-12-12 8:29:1184 days ago1765528151IN
SoundMint Vinyl: Token
0 ETH0.000004280.09311957
Set Approval For...239934502025-12-12 1:58:5984 days ago1765504739IN
SoundMint Vinyl: Token
0 ETH0.000005310.11544542
Set Approval For...239091582025-11-30 4:41:3596 days ago1764477695IN
SoundMint Vinyl: Token
0 ETH0.000093632.03379262
Set Approval For...237995202025-11-14 19:28:47112 days ago1763148527IN
SoundMint Vinyl: Token
0 ETH0.000016330.35486992
Set Approval For...237878082025-11-13 4:09:11113 days ago1763006951IN
SoundMint Vinyl: Token
0 ETH0.000006060.13162698
Set Approval For...235003462025-10-03 22:50:11154 days ago1759531811IN
SoundMint Vinyl: Token
0 ETH0.000007290.15846307
Set Approval For...234624512025-09-28 15:40:59159 days ago1759074059IN
SoundMint Vinyl: Token
0 ETH0.000029071.20484709
Set Approval For...234623062025-09-28 15:11:35159 days ago1759072295IN
SoundMint Vinyl: Token
0 ETH0.000006010.23
Set Approval For...234542312025-09-27 12:06:35160 days ago1758974795IN
SoundMint Vinyl: Token
0 ETH0.000021250.88102608
Set Approval For...233948652025-09-19 4:54:11168 days ago1758257651IN
SoundMint Vinyl: Token
0 ETH0.000054591.18571586
Set Approval For...233714162025-09-15 22:19:35172 days ago1757974775IN
SoundMint Vinyl: Token
0 ETH0.00001240.47483523
Set Approval For...233714162025-09-15 22:19:35172 days ago1757974775IN
SoundMint Vinyl: Token
0 ETH0.000011450.47483523
Set Approval For...233564942025-09-13 20:19:35174 days ago1757794775IN
SoundMint Vinyl: Token
0 ETH0.000010660.23163865
Set Approval For...233564102025-09-13 20:02:35174 days ago1757793755IN
SoundMint Vinyl: Token
0 ETH0.000006790.14760142
Set Approval For...233318372025-09-10 9:36:35177 days ago1757496995IN
SoundMint Vinyl: Token
0 ETH0.000017190.7099958
Set Approval For...233274012025-09-09 18:42:11178 days ago1757443331IN
SoundMint Vinyl: Token
0 ETH0.000016080.34947162
Set Approval For...233128292025-09-07 17:52:35180 days ago1757267555IN
SoundMint Vinyl: Token
0 ETH0.000004960.19
Set Approval For...233039872025-09-06 12:13:59181 days ago1757160839IN
SoundMint Vinyl: Token
0 ETH0.000057971.2591788
Set Approval For...233035832025-09-06 10:52:23181 days ago1757155943IN
SoundMint Vinyl: Token
0 ETH0.000008740.19
Set Approval For...232825372025-09-03 12:18:35184 days ago1756901915IN
SoundMint Vinyl: Token
0 ETH0.000061911.34470808
Set Approval For...230139662025-07-28 0:07:59222 days ago1753661279IN
SoundMint Vinyl: Token
0 ETH0.000102532.22707876
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
VINYL

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 500 runs

Other Settings:
default evmVersion
// SPDX-License-Identifier: MIT
/// @dev SOUNDMINT VINYL
///
/********************************************************************************
*                                                                               *
*                           ,%@@@&&&&&&&&&&&&&&&&@%*                            *
*                      /@@@@@@@@@&&&&&&&&&&&&&&&&&&&&&@@(                       *
*                  .@@@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&%%#%#&@*                   *
*                @@@@@@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&%%%%%%###&@.                *
*             *@&&&@@@@@@@@@@@@@@@@@&&&&&&&&&&&&&&%#%%%#%%#####(@#              *
*            @&&&&&&@@@@@@@@@@@@@@@@@@@@@@&&&&&&&%%#%###%##%#####(@%            *
*          @%&&&&&&&@@@@@@@@@@@@@@@@@@@&&&&&&&&&%%%#######%##%######&           *
*         @&&&&&&&&&&@@@@@@@@@@@@@@@@@@&&&&&&&@%%%%#%###%###%##%#####@/         *
*        &@@@@@&&&&&&&@@@@@@@@@@@@@@@@@@@@@@@%%%######%###%#####%####(@#        *
*       @@@@@@@@@@@&&&@@@@@@@@@@@/.,,,,,,,,.(@@@%##(####%##########%%%&@,       *
*      @@@@@@@@@@@@@@@@@@@@@@@/,,,,,,,,,,,,,,,.(&@%##%######%%&&&@@@@@@@@       *
*      @@@@@@@@@@@@@@@@@@@@@@.,,,,,,,,,,,,,,,,,,.@@@%%@&@&@@@@@@@@@@@@@@@(      *
*     /@@@@@@@@@@@@@@@@@@@@@.,,,,,,,,,,,,,,,,,,,,.@@@@@@@@@@@@@@@@@@@@@@@@      *
*     (@@@@@@@@@@@@@@@@@@@@&,,,,,,,,,,* ,,,,,,,,,,&@@@@@@@@@@@@@@@@@@@@@@@      *
*     /@@@@@@@@@@@@@@@@@@@@@,,,,,,,,,,,,,,,,,,,,,.@@@@@@@@@@@@@@@@@@@@@@@@      *
*      @@@@@@@@@@@@&@&&&%&&@@,,,,,,,,,,,,,,,,,,,,&@@@@@@@@@@@@@@@@@@@@@@@#      *
*      &@@@@&@&&%%##%%%%%%%&@@*,,,,,,,,,,,,,,,,,@@@@@@@@@@@@@@@@@@@@@@@@@.      *
*       @%%%#%###%%%%%%%%%&%%@@@@*.,,,,,,,,,,@@@@&&&&&&@@@@@@@@@@@@@@@@@%       *
*        @####%%%%%%%%%%%&&&@&&&@@@@@@@@@@@@@@&&&&&&&&&&&&&@@@@@@@@@@@@&        *
*         @#%%#%%#%%%%&%&&@&&@&@@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&@@@@@@@&         *
*          @&%#%%%%%%%%&&@&&&@@@@@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&&&@,          *
*            @###%%%&&&&&&&&@@@@@@@@@@@@@@@@@@@@@&&&&&&&@&&&&&&&&&@@            *
*              @#%%%%&&&&@@@@@@@@@@@@@@@@@@@@@@@@@@&&&&&&&&&&&&&@@              *
*                &@%%&&&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&&&&&&&&@&                *
*                   @@&&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&&&@@                   *
*                      *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@,                      *
*                           ,%@@@@@@@@@@@@@@@@@@@@@%,                           *
*                                                                               *
*********************************************************************************/
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/Strings.sol";

import "./subContracts/ERC1155PackedBalance.sol";

contract VINYL is ERC1155PackedBalance, Ownable {
    using Address for address;
    using Strings for uint256;

    string private baseURI;
    bytes32 public merkleRoot = 0xdb9f7b75bd7be5081adf28065e8d2dd1322f281c829a80c122d483779b958616;

    mapping (uint256 => uint256) _redeemed;

    bool public isActive = false;
    
    enum VINYLTYPE {
        MINT,
        GOLD,
        ONYX
    }
    string public name = "SoundMint Vinyl";

    /*
     * Function to mint NFTs (internal)
    */
    function mint(address to, uint mint_type) internal 
    {
        if (mint_type == 1)
	{
		_mint(to, uint(VINYLTYPE.MINT), 1, "");
        } 
        else if (mint_type == 2)
        {
        	_mint(to, uint(VINYLTYPE.MINT), 2, "");
        } 
        else
	{
            uint256[] memory Collect = new uint256[](2);
            uint256[] memory Count = new uint256[](2);
            if (mint_type == 5)
            {
                Collect[0] = uint(VINYLTYPE.GOLD);
                Collect[1] = uint(VINYLTYPE.ONYX);
                Count[0] = 10;
                Count[1] = 10;
            }
            else
	    {
                Collect[0] = uint(VINYLTYPE.MINT);
                Collect[1] = uint(VINYLTYPE.GOLD);
                if (mint_type == 3)
                {
                    Count[0] = 2;
                    Count[1] = 1;
                }
                else if(mint_type == 4)
                {
                    Count[0] = 4;
                    Count[1] = 2;
                }
            }
            _batchMint(to, Collect, Count, "");
        }
    }
    
    
    /*
     * Function to burn NFTs (public)
    */

    function burn(uint _id, uint amount) external 
    {
        require(isActive, "Contract is not active");
       _burn(msg.sender, _id, amount);
    }
    /*
     * Function toggleActive to activate/desactivate the smart contract
    */

    function toggleActive() external onlyOwner 
    {
        isActive = !isActive;
    }

    /*
     * Function to set Base URI
    */
    function setURI(string memory _URI) external onlyOwner 
    {
        require(keccak256(abi.encodePacked(baseURI)) != keccak256(abi.encodePacked(_URI)), "baseURI is already the value being set.");
        baseURI = _URI;
    }

    /*
     * Function to set the merkle root
    */

    function setMerkleRoot(bytes32 merkleRootHash) external onlyOwner 
    {
	    require(merkleRoot != merkleRootHash,"merkelRoot already being set.");
        merkleRoot = merkleRootHash;
    }

    function hasNotMinted(uint256 index) external view returns (bool)
    {
      uint256 redeemedBlock = _redeemed[index / 256];
      uint256 redeemedMask = (uint256(1) << uint256(index % 256));
      return ((redeemedBlock & redeemedMask) == 0);
    }

    /*
     * Function to mint new NFTs during presale/raffle
     */
  
    function mintNFT(uint256 index, uint256 mint_type, bytes32[] memory _proof) external
    {
        require(isActive, "Contract is not active");
      
      	// Check Allowlist
        bytes32 leaf = keccak256(abi.encodePacked(msg.sender, mint_type, index));
        require(verify(merkleRoot, _proof, leaf), "Not Allowlisted");
      
        // To prevent several mint
	uint256 redeemedBlock = _redeemed[index / 256]; 
        uint256 redeemedMask = (uint256(1) << uint256(index % 256)); 
        require((redeemedBlock & redeemedMask) == 0, "Drop already claimed");
        _redeemed[index / 256] = redeemedBlock | redeemedMask;
	
        mint(msg.sender, mint_type);
        
    }

    /*
     * Function to get token URI of given token ID
     * URI will be blank untill totalSupply reaches MAX_NFT_PUBLIC
    */

    function uri(uint256 _tokenId) external view returns (string memory) {
        return string(abi.encodePacked(baseURI, _tokenId.toString(), ".json"));
    }

    /*
     * Function to verify the Merkle Tree Proof
    */
    function verify(
        bytes32 root,
        bytes32[] memory proof,
        bytes32 leaf
    ) public pure returns (bool) 
    {
        bytes32 hash = leaf;

        for (uint i = 0; i < proof.length; i++) 
	    {
            bytes32 proofElement = proof[i];

            if (hash <= proofElement) {
                // Hash(current computed hash + current element of the proof)
                hash = keccak256(abi.encodePacked(hash, proofElement));
            } else {
                // Hash(current element of the proof + current computed hash)
                hash = keccak256(abi.encodePacked(proofElement, hash));
            }            
        }

        return hash == root;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/utils/Strings.sol";

import "../interfaces/IERC1155TokenReceiver.sol";
import "./ERC165.sol";

contract ERC1155PackedBalance is IERC1155, ERC165 {
  using SafeMath for uint256;
  using Address for address;

  /***********************************|
  |        Variables and Events       |
  |__________________________________*/

  // onReceive function signatures
  bytes4 constant internal ERC1155_RECEIVED_VALUE = 0xf23a6e61;
  bytes4 constant internal ERC1155_BATCH_RECEIVED_VALUE = 0xbc197c81;

  // Constants regarding bin sizes for balance packing
  // IDS_BITS_SIZE **MUST** be a power of 2 (e.g. 2, 4, 8, 16, 32, 64, 128)
  uint256 internal constant IDS_BITS_SIZE   = 32;                  // Max balance amount in bits per token ID
  uint256 internal constant IDS_PER_UINT256 = 256 / IDS_BITS_SIZE; // Number of ids per uint256

  // Operations for _updateIDBalance
  enum Operations { Add, Sub }

  // Token IDs balances ; balances[address][id] => balance (using array instead of mapping for efficiency)
  mapping (address => mapping(uint256 => uint256)) internal balances;

  // Operators
  mapping (address => mapping(address => bool)) internal operators;


  /***********************************|
  |     Public Transfer Functions     |
  |__________________________________*/

  /**
   * @notice Transfers amount amount of an _id from the _from address to the _to address specified
   * @param _from    Source address
   * @param _to      Target address
   * @param _id      ID of the token type
   * @param _amount  Transfered amount
   * @param _data    Additional data with no specified format, sent in call to `_to`
   */
  function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _amount, bytes memory _data)
    public override
  {
    // Requirements
    require((msg.sender == _from) || isApprovedForAll(_from, msg.sender), "ERC1155PackedBalance#safeTransferFrom: INVALID_OPERATOR");
    require(_to != address(0),"ERC1155PackedBalance#safeTransferFrom: INVALID_RECIPIENT");
    // require(_amount <= balances);  Not necessary since checked with _viewUpdateBinValue() checks

    _safeTransferFrom(_from, _to, _id, _amount);
    _callonERC1155Received(_from, _to, _id, _amount, gasleft(), _data);
  }

  /**
   * @notice Send multiple types of Tokens from the _from address to the _to address (with safety call)
   * @dev Arrays should be sorted so that all ids in a same storage slot are adjacent (more efficient)
   * @param _from     Source addresses
   * @param _to       Target addresses
   * @param _ids      IDs of each token type
   * @param _amounts  Transfer amounts per token type
   * @param _data     Additional data with no specified format, sent in call to `_to`
   */
  function safeBatchTransferFrom(address _from, address _to, uint256[] memory _ids, uint256[] memory _amounts, bytes memory _data)
    public override
  {
    // Requirements
    require((msg.sender == _from) || isApprovedForAll(_from, msg.sender), "ERC1155PackedBalance#safeBatchTransferFrom: INVALID_OPERATOR");
    require(_to != address(0),"ERC1155PackedBalance#safeBatchTransferFrom: INVALID_RECIPIENT");

    _safeBatchTransferFrom(_from, _to, _ids, _amounts);
    _callonERC1155BatchReceived(_from, _to, _ids, _amounts, gasleft(), _data);
  }


  /***********************************|
  |    Internal Transfer Functions    |
  |__________________________________*/

  /**
   * @notice Transfers amount amount of an _id from the _from address to the _to address specified
   * @param _from    Source address
   * @param _to      Target address
   * @param _id      ID of the token type
   * @param _amount  Transfered amount
   */
  function _safeTransferFrom(address _from, address _to, uint256 _id, uint256 _amount)
    internal
  {
    //Update balances
    _updateIDBalance(_from, _id, _amount, Operations.Sub); // Subtract amount from sender
    _updateIDBalance(_to,   _id, _amount, Operations.Add); // Add amount to recipient

    // Emit event
    emit TransferSingle(msg.sender, _from, _to, _id, _amount);
  }

  /**
   * @notice Verifies if receiver is contract and if so, calls (_to).onERC1155Received(...)
   */
  function _callonERC1155Received(address _from, address _to, uint256 _id, uint256 _amount, uint256 _gasLimit, bytes memory _data)
    internal
  {
    // Check if recipient is contract
    if (_to.isContract()) {
      bytes4 retval = IERC1155TokenReceiver(_to).onERC1155Received{gas:_gasLimit}(msg.sender, _from, _id, _amount, _data);
      require(retval == ERC1155_RECEIVED_VALUE, "ERC1155PackedBalance#_callonERC1155Received: INVALID_ON_RECEIVE_MESSAGE");
    }
  }

  /**
   * @notice Send multiple types of Tokens from the _from address to the _to address (with safety call)
   * @dev Arrays should be sorted so that all ids in a same storage slot are adjacent (more efficient)
   * @param _from     Source addresses
   * @param _to       Target addresses
   * @param _ids      IDs of each token type
   * @param _amounts  Transfer amounts per token type
   */
  function _safeBatchTransferFrom(address _from, address _to, uint256[] memory _ids, uint256[] memory _amounts)
    internal
  {
    uint256 nTransfer = _ids.length; // Number of transfer to execute
    require(nTransfer == _amounts.length, "ERC1155PackedBalance#_safeBatchTransferFrom: INVALID_ARRAYS_LENGTH");

    if (_from != _to && nTransfer > 0) {
      // Load first bin and index where the token ID balance exists
      (uint256 bin, uint256 index) = getIDBinIndex(_ids[0]);

      // Balance for current bin in memory (initialized with first transfer)
      uint256 balFrom = _viewUpdateBinValue(balances[_from][bin], index, _amounts[0], Operations.Sub);
      uint256 balTo = _viewUpdateBinValue(balances[_to][bin], index, _amounts[0], Operations.Add);

      // Last bin updated
      uint256 lastBin = bin;

      for (uint256 i = 1; i < nTransfer; i++) {
        (bin, index) = getIDBinIndex(_ids[i]);

        // If new bin
        if (bin != lastBin) {
          // Update storage balance of previous bin
          balances[_from][lastBin] = balFrom;
          balances[_to][lastBin] = balTo;

          balFrom = balances[_from][bin];
          balTo = balances[_to][bin];

          // Bin will be the most recent bin
          lastBin = bin;
        }

        // Update memory balance
        balFrom = _viewUpdateBinValue(balFrom, index, _amounts[i], Operations.Sub);
        balTo = _viewUpdateBinValue(balTo, index, _amounts[i], Operations.Add);
      }

      // Update storage of the last bin visited
      balances[_from][bin] = balFrom;
      balances[_to][bin] = balTo;

    // If transfer to self, just make sure all amounts are valid
    } else {
      for (uint256 i = 0; i < nTransfer; i++) {
        require(balanceOf(_from, _ids[i]) >= _amounts[i], "ERC1155PackedBalance#_safeBatchTransferFrom: UNDERFLOW");
      }
    }

    // Emit event
    emit TransferBatch(msg.sender, _from, _to, _ids, _amounts);
  }

  /**
   * @notice Verifies if receiver is contract and if so, calls (_to).onERC1155BatchReceived(...)
   */
  function _callonERC1155BatchReceived(address _from, address _to, uint256[] memory _ids, uint256[] memory _amounts, uint256 _gasLimit, bytes memory _data)
    internal
  {
    // Pass data if recipient is contract
    if (_to.isContract()) {
      bytes4 retval = IERC1155TokenReceiver(_to).onERC1155BatchReceived{gas: _gasLimit}(msg.sender, _from, _ids, _amounts, _data);
      require(retval == ERC1155_BATCH_RECEIVED_VALUE, "ERC1155PackedBalance#_callonERC1155BatchReceived: INVALID_ON_RECEIVE_MESSAGE");
    }
  }


  /***********************************|
  |         Operator Functions        |
  |__________________________________*/

  /**
   * @notice Enable or disable approval for a third party ("operator") to manage all of caller's tokens
   * @param _operator  Address to add to the set of authorized operators
   * @param _approved  True if the operator is approved, false to revoke approval
   */
  function setApprovalForAll(address _operator, bool _approved)
    external override
  {
    // Update operator status
    operators[msg.sender][_operator] = _approved;
    emit ApprovalForAll(msg.sender, _operator, _approved);
  }

  /**
   * @notice Queries the approval status of an operator for a given owner
   * @param _owner     The owner of the Tokens
   * @param _operator  Address of authorized operator
   * @return isOperator True if the operator is approved, false if not
   */
  function isApprovedForAll(address _owner, address _operator)
    public override view returns (bool isOperator)
  {
    return operators[_owner][_operator];
  }


  /***********************************|
  |     Public Balance Functions      |
  |__________________________________*/

  /**
   * @notice Get the balance of an account's Tokens
   * @param _owner  The address of the token holder
   * @param _id     ID of the Token
   * @return The _owner's balance of the Token type requested
   */
  function balanceOf(address _owner, uint256 _id)
    public override view returns (uint256)
  {
    uint256 bin;
    uint256 index;

    //Get bin and index of _id
    (bin, index) = getIDBinIndex(_id);
    return getValueInBin(balances[_owner][bin], index);
  }

  /**
   * @notice Get the balance of multiple account/token pairs
   * @param _owners The addresses of the token holders (sorted owners will lead to less gas usage)
   * @param _ids    ID of the Tokens (sorted ids will lead to less gas usage
   * @return The _owner's balance of the Token types requested (i.e. balance for each (owner, id) pair)
    */
  function balanceOfBatch(address[] memory _owners, uint256[] memory _ids)
    public override view returns (uint256[] memory)
  {
    uint256 n_owners = _owners.length;
    require(n_owners == _ids.length, "ERC1155PackedBalance#balanceOfBatch: INVALID_ARRAY_LENGTH");

    // First values
    (uint256 bin, uint256 index) = getIDBinIndex(_ids[0]);
    uint256 balance_bin = balances[_owners[0]][bin];
    uint256 last_bin = bin;

    // Initialization
    uint256[] memory batchBalances = new uint256[](n_owners);
    batchBalances[0] = getValueInBin(balance_bin, index);

    // Iterate over each owner and token ID
    for (uint256 i = 1; i < n_owners; i++) {
      (bin, index) = getIDBinIndex(_ids[i]);

      // SLOAD if bin changed for the same owner or if owner changed
      if (bin != last_bin || _owners[i-1] != _owners[i]) {
        balance_bin = balances[_owners[i]][bin];
        last_bin = bin;
      }

      batchBalances[i] = getValueInBin(balance_bin, index);
    }

    return batchBalances;
  }


  /***********************************|
  |      Packed Balance Functions     |
  |__________________________________*/

  /**
   * @notice Update the balance of a id for a given address
   * @param _address    Address to update id balance
   * @param _id         Id to update balance of
   * @param _amount     Amount to update the id balance
   * @param _operation  Which operation to conduct :
   *   Operations.Add: Add _amount to id balance
   *   Operations.Sub: Substract _amount from id balance
   */
  function _updateIDBalance(address _address, uint256 _id, uint256 _amount, Operations _operation)
    internal
  {
    uint256 bin;
    uint256 index;

    // Get bin and index of _id
    (bin, index) = getIDBinIndex(_id);

    // Update balance
    balances[_address][bin] = _viewUpdateBinValue(balances[_address][bin], index, _amount, _operation);
  }

  /**
   * @notice Update a value in _binValues
   * @param _binValues  Uint256 containing values of size IDS_BITS_SIZE (the token balances)
   * @param _index      Index of the value in the provided bin
   * @param _amount     Amount to update the id balance
   * @param _operation  Which operation to conduct :
   *   Operations.Add: Add _amount to value in _binValues at _index
   *   Operations.Sub: Substract _amount from value in _binValues at _index
   */
  function _viewUpdateBinValue(uint256 _binValues, uint256 _index, uint256 _amount, Operations _operation)
    internal pure returns (uint256 newBinValues)
  {
    uint256 shift = IDS_BITS_SIZE * _index;
    uint256 mask = (uint256(1) << IDS_BITS_SIZE) - 1;

    if (_operation == Operations.Add) {
      newBinValues = _binValues + (_amount << shift);
      require(newBinValues >= _binValues, "ERC1155PackedBalance#_viewUpdateBinValue: OVERFLOW");
      require(
        ((_binValues >> shift) & mask) + _amount < 2**IDS_BITS_SIZE, // Checks that no other id changed
        "ERC1155PackedBalance#_viewUpdateBinValue: OVERFLOW"
      );

    } else if (_operation == Operations.Sub) {
      newBinValues = _binValues - (_amount << shift);
      require(newBinValues <= _binValues, "ERC1155PackedBalance#_viewUpdateBinValue: UNDERFLOW");
      require(
        ((_binValues >> shift) & mask) >= _amount, // Checks that no other id changed
        "ERC1155PackedBalance#_viewUpdateBinValue: UNDERFLOW"
      );

    } else {
      revert("ERC1155PackedBalance#_viewUpdateBinValue: INVALID_BIN_WRITE_OPERATION"); // Bad operation
    }

    return newBinValues;
  }

  /**
  * @notice Return the bin number and index within that bin where ID is
  * @param _id  Token id
  * @return bin index (Bin number, ID"s index within that bin)
  */
  function getIDBinIndex(uint256 _id)
    public pure returns (uint256 bin, uint256 index)
  {
    bin = _id / IDS_PER_UINT256;
    index = _id % IDS_PER_UINT256;
    return (bin, index);
  }

  /**
   * @notice Return amount in _binValues at position _index
   * @param _binValues  uint256 containing the balances of IDS_PER_UINT256 ids
   * @param _index      Index at which to retrieve amount
   * @return amount at given _index in _bin
   */
  function getValueInBin(uint256 _binValues, uint256 _index)
    public pure returns (uint256)
  {
    // require(_index < IDS_PER_UINT256) is not required since getIDBinIndex ensures `_index < IDS_PER_UINT256`

    // Mask to retrieve data for a given binData
    uint256 mask = (uint256(1) << IDS_BITS_SIZE) - 1;

    // Shift amount
    uint256 rightShift = IDS_BITS_SIZE * _index;
    return (_binValues >> rightShift) & mask;
  }

    function _mint(address _to, uint256 _id, uint256 _amount, bytes memory _data)
    internal
    {
        //Add _amount
        _updateIDBalance(_to,   _id, _amount, Operations.Add); // Add amount to recipient

        // Emit event
        emit TransferSingle(msg.sender, address(0x0), _to, _id, _amount);

        // Calling onReceive method if recipient is contract
        _callonERC1155Received(address(0x0), _to, _id, _amount, gasleft(), _data);
    }

    /**
   * @notice Mint tokens for each (_ids[i], _amounts[i]) pair
   * @param _to       The address to mint tokens to
   * @param _ids      Array of ids to mint
   * @param _amounts  Array of amount of tokens to mint per id
   * @param _data    Data to pass if receiver is contract
   */
    function _batchMint(address _to, uint256[] memory _ids, uint256[] memory _amounts, bytes memory _data)
    internal
    {
        require(_ids.length == _amounts.length, "ERC1155MintBurnPackedBalance#_batchMint: INVALID_ARRAYS_LENGTH");

        if (_ids.length > 0) {
        // Load first bin and index where the token ID balance exists
        (uint256 bin, uint256 index) = getIDBinIndex(_ids[0]);

        // Balance for current bin in memory (initialized with first transfer)
        uint256 balTo = _viewUpdateBinValue(balances[_to][bin], index, _amounts[0], Operations.Add);

        // Number of transfer to execute
        uint256 nTransfer = _ids.length;

        // Last bin updated
        uint256 lastBin = bin;

        for (uint256 i = 1; i < nTransfer; i++) {
            (bin, index) = getIDBinIndex(_ids[i]);

            // If new bin
            if (bin != lastBin) {
            // Update storage balance of previous bin
            balances[_to][lastBin] = balTo;
            balTo = balances[_to][bin];

            // Bin will be the most recent bin
            lastBin = bin;
            }

            // Update memory balance
            balTo = _viewUpdateBinValue(balTo, index, _amounts[i], Operations.Add);
        }

        // Update storage of the last bin visited
        balances[_to][bin] = balTo;
        }

        // //Emit event
        emit TransferBatch(msg.sender, address(0x0), _to, _ids, _amounts);

        // Calling onReceive method if recipient is contract
        _callonERC1155BatchReceived(address(0x0), _to, _ids, _amounts, gasleft(), _data);
    }
    /****************************************|
    |            Burning Functions           |
    |_______________________________________*/

    /**
    * @notice Burn _amount of tokens of a given token id
    * @param _from    The address to burn tokens from
    * @param _id      Token id to burn
    * @param _amount  The amount to be burned
    */
    function _burn(address _from, uint256 _id, uint256 _amount)
      internal
    {
      // Substract _amount
      _updateIDBalance(_from, _id, _amount, Operations.Sub);

      // Emit event
      emit TransferSingle(msg.sender, _from, address(0x0), _id, _amount);
    }

    /**
    * @notice Burn tokens of given token id for each (_ids[i], _amounts[i]) pair
    * @dev This batchBurn method does not implement the most efficient way of updating
    *      balances to reduce the potential bug surface as this function is expected to
    *      be less common than transfers. EIP-2200 makes this method significantly
    *      more efficient already for packed balances.
    * @param _from     The address to burn tokens from
    * @param _ids      Array of token ids to burn
    * @param _amounts  Array of the amount to be burned
    */
    function _batchBurn(address _from, uint256[] memory _ids, uint256[] memory _amounts)
      internal
    {
      // Number of burning to execute
      uint256 nBurn = _ids.length;
      require(nBurn == _amounts.length, "ERC1155MintBurnPackedBalance#batchBurn: INVALID_ARRAYS_LENGTH");

      // Executing all burning
      for (uint256 i = 0; i < nBurn; i++) {
        // Update storage balance
        _updateIDBalance(_from,   _ids[i], _amounts[i], Operations.Sub); // Add amount to recipient
      }

      // Emit batch burn event
      emit TransferBatch(msg.sender, _from, address(0x0), _ids, _amounts);
    }
    /***********************************|
    |          ERC165 Functions         |
    |__________________________________*/

    /**
    * @notice Query if a contract implements an interface
    * @param _interfaceID  The interface identifier, as specified in ERC-165
    * @return `true` if the contract implements `_interfaceID` and
    */
    function supportsInterface(bytes4 _interfaceID) public override(ERC165, IERC165) virtual pure returns (bool) {
      if (_interfaceID == type(IERC1155).interfaceId) {
        return true;
      }
      return super.supportsInterface(_interfaceID);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
/**
 * @dev Implementation of Multi-Token Standard contract. This implementation of the ERC-1155 standard
 *      utilizes the fact that balances of different token ids can be concatenated within individual
 *      uint256 storage slots. This allows the contract to batch transfer tokens more efficiently at
 *      the cost of limiting the maximum token balance each address can hold. This limit is
 *      2^IDS_BITS_SIZE, which can be adjusted below. In practice, using IDS_BITS_SIZE smaller than 16
 *      did not lead to major efficiency gains.
 */
 interface IERC1155TokenReceiver {

  /**
   * @notice Handle the receipt of a single ERC1155 token type
   * @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeTransferFrom` after the balance has been updated
   * This function MAY throw to revert and reject the transfer
   * Return of other amount than the magic value MUST result in the transaction being reverted
   * Note: The token contract address is always the message sender
   * @param _operator  The address which called the `safeTransferFrom` function
   * @param _from      The address which previously owned the token
   * @param _id        The id of the token being transferred
   * @param _amount    The amount of tokens being transferred
   * @param _data      Additional data with no specified format
   * @return           `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
   */
  function onERC1155Received(address _operator, address _from, uint256 _id, uint256 _amount, bytes calldata _data) external returns(bytes4);

  /**
   * @notice Handle the receipt of multiple ERC1155 token types
   * @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeBatchTransferFrom` after the balances have been updated
   * This function MAY throw to revert and reject the transfer
   * Return of other amount than the magic value WILL result in the transaction being reverted
   * Note: The token contract address is always the message sender
   * @param _operator  The address which called the `safeBatchTransferFrom` function
   * @param _from      The address which previously owned the token
   * @param _ids       An array containing ids of each token being transferred
   * @param _amounts   An array containing amounts of each token being transferred
   * @param _data      Additional data with no specified format
   * @return           `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
   */
  function onERC1155BatchReceived(address _operator, address _from, uint256[] calldata _ids, uint256[] calldata _amounts, bytes calldata _data) external returns(bytes4);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";

abstract contract ERC165 is IERC165 {
  /**
   * @notice Query if a contract implements an interface
   * @param _interfaceID The interface identifier, as specified in ERC-165
   * @return `true` if the contract implements `_interfaceID`
   */
  function supportsInterface(bytes4 _interfaceID) virtual override public pure returns (bool) {
    return _interfaceID == this.supportsInterface.selector;
  }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC1155/IERC1155.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC1155 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1155[EIP].
 *
 * _Available since v3.1._
 */
interface IERC1155 is IERC165 {
    /**
     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
     */
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    /**
     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
     * transfers.
     */
    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] values
    );

    /**
     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `approved`.
     */
    event ApprovalForAll(address indexed account, address indexed operator, bool approved);

    /**
     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
     *
     * If an {URI} event was emitted for `id`, the standard
     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
     * returned by {IERC1155MetadataURI-uri}.
     */
    event URI(string value, uint256 indexed id);

    /**
     * @dev Returns the amount of tokens of token type `id` owned by `account`.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(address account, uint256 id) external view returns (uint256);

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
        external
        view
        returns (uint256[] memory);

    /**
     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
     *
     * Emits an {ApprovalForAll} event.
     *
     * Requirements:
     *
     * - `operator` cannot be the caller.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
     *
     * See {setApprovalForAll}.
     */
    function isApprovedForAll(address account, address operator) external view returns (bool);

    /**
     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `amount`.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) external;
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 500
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_owners","type":"address[]"},{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"getIDBinIndex","outputs":[{"internalType":"uint256","name":"bin","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_binValues","type":"uint256"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getValueInBin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"hasNotMinted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"isOperator","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"mint_type","type":"uint256"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"mintNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256[]","name":"_ids","type":"uint256[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"merkleRootHash","type":"bytes32"}],"name":"setMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_URI","type":"string"}],"name":"setURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"toggleActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"root","type":"bytes32"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"bytes32","name":"leaf","type":"bytes32"}],"name":"verify","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}]

7fdb9f7b75bd7be5081adf28065e8d2dd1322f281c829a80c122d483779b9586166004556006805460ff1916905560c0604052600f60808190526e14dbdd5b99135a5b9d08159a5b9e5b608a1b60a0908152620000609160079190620000d2565b503480156200006e57600080fd5b506200007a3362000080565b620001b5565b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b828054620000e09062000178565b90600052602060002090601f0160209004810192826200010457600085556200014f565b82601f106200011f57805160ff19168380011785556200014f565b828001600101855582156200014f579182015b828111156200014f57825182559160200191906001019062000132565b506200015d92915062000161565b5090565b5b808211156200015d576000815560010162000162565b600181811c908216806200018d57607f821691505b60208210811415620001af57634e487b7160e01b600052602260045260246000fd5b50919050565b612bff80620001c56000396000f3fe608060405234801561001057600080fd5b506004361061017c5760003560e01c806365aad4fd116100e3578063db90e83c1161008c578063eaec5f8111610066578063eaec5f8114610351578063f242432a14610364578063f2fde38b1461037757600080fd5b8063db90e83c146102da578063ddc5ba1b14610302578063e985e9c51461031557600080fd5b80638da5cb5b116100bd5780638da5cb5b14610299578063a22cb465146102b4578063b390c0ab146102c757600080fd5b806365aad4fd1461026b578063715018a61461027e5780637cb647591461028657600080fd5b80630e89341c116101455780632eb2c2d61161011f5780632eb2c2d61461022f5780632eb4a7ab146102425780634e1273f41461024b57600080fd5b80630e89341c1461020757806322f3e2d41461021a57806329c68dc11461022757600080fd5b8062fdd58e1461018157806301ffc9a7146101a757806302fe5305146101ca57806306fdde03146101df5780630a02831c146101f4575b600080fd5b61019461018f36600461246b565b61038a565b6040519081526020015b60405180910390f35b6101ba6101b53660046125c5565b6103d4565b604051901515815260200161019e565b6101dd6101d83660046125ff565b610410565b005b6101e7610533565b60405161019e91906128fa565b6101ba610202366004612575565b6105c1565b6101e761021536600461255c565b610670565b6006546101ba9060ff1681565b6101dd6106a4565b6101dd61023d366004612320565b610712565b61019460045481565b61025e610259366004612495565b61085b565b60405161019e91906128b9565b6101dd61027936600461266a565b610aed565b6101dd610c9d565b6101dd61029436600461255c565b610d03565b6002546040516001600160a01b03909116815260200161019e565b6101dd6102c236600461242f565b610db4565b6101dd6102d5366004612648565b610e20565b6102ed6102e836600461255c565b610e7d565b6040805192835260208301919091520161019e565b6101ba61031036600461255c565b610eb7565b6101ba6103233660046122ed565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205460ff1690565b61019461035f366004612648565b610efa565b6101dd6103723660046123ca565b610f28565b6101dd6103853660046122d2565b61106a565b600080600061039884610e7d565b6001600160a01b03871660009081526020818152604080832085845290915290205491935091506103c99082610efa565b925050505b92915050565b60006001600160e01b03198216636cdb3d1360e11b14156103f757506001919050565b6301ffc9a760e01b6001600160e01b03198316146103ce565b6002546001600160a01b0316331461046f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b8060405160200161048091906127bb565b6040516020818303038152906040528051906020012060036040516020016104a891906127d7565b60405160208183030381529060405280519060200120141561051c5760405162461bcd60e51b815260206004820152602760248201527f6261736555524920697320616c7265616479207468652076616c75652062656960448201526637339039b2ba1760c91b6064820152608401610466565b805161052f90600390602084019061212c565b5050565b6007805461054090612adb565b80601f016020809104026020016040519081016040528092919081815260200182805461056c90612adb565b80156105b95780601f1061058e576101008083540402835291602001916105b9565b820191906000526020600020905b81548152906001019060200180831161059c57829003601f168201915b505050505081565b600081815b84518110156106655760008582815181106105e3576105e3612b87565b60200260200101519050808311610625576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250610652565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b508061065d81612b16565b9150506105c6565b509093149392505050565b6060600361067d83611135565b60405160200161068e9291906127e3565b6040516020818303038152906040529050919050565b6002546001600160a01b031633146106fe5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610466565b6006805460ff19811660ff90911615179055565b336001600160a01b038616148061074c57506001600160a01b038516600090815260016020908152604080832033845290915290205460ff165b6107be5760405162461bcd60e51b815260206004820152603c60248201527f455243313135355061636b656442616c616e636523736166654261746368547260448201527f616e7366657246726f6d3a20494e56414c49445f4f50455241544f52000000006064820152608401610466565b6001600160a01b03841661083a5760405162461bcd60e51b815260206004820152603d60248201527f455243313135355061636b656442616c616e636523736166654261746368547260448201527f616e7366657246726f6d3a20494e56414c49445f524543495049454e540000006064820152608401610466565b61084685858585611253565b610854858585855a866115f2565b5050505050565b815181516060919081146108d75760405162461bcd60e51b815260206004820152603960248201527f455243313135355061636b656442616c616e63652362616c616e63654f66426160448201527f7463683a20494e56414c49445f41525241595f4c454e475448000000000000006064820152608401610466565b6000806108fd856000815181106108f0576108f0612b87565b6020026020010151610e7d565b9150915060008060008860008151811061091957610919612b87565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000848152602001908152602001600020549050600083905060008567ffffffffffffffff81111561097557610975612b9d565b60405190808252806020026020018201604052801561099e578160200160208202803683370190505b5090506109ab8385610efa565b816000815181106109be576109be612b87565b602090810291909101015260015b86811015610ae0576109e98982815181106108f0576108f0612b87565b90965094508286141580610a4d5750898181518110610a0a57610a0a612b87565b60200260200101516001600160a01b03168a600183610a299190612a98565b81518110610a3957610a39612b87565b60200260200101516001600160a01b031614155b15610aa7576000808b8381518110610a6757610a67612b87565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000205493508592505b610ab18486610efa565b828281518110610ac357610ac3612b87565b602090810291909101015280610ad881612b16565b9150506109cc565b5098975050505050505050565b60065460ff16610b3f5760405162461bcd60e51b815260206004820152601660248201527f436f6e7472616374206973206e6f7420616374697665000000000000000000006044820152606401610466565b6040516bffffffffffffffffffffffff193360601b1660208201526034810183905260548101849052600090607401604051602081830303815290604052805190602001209050610b9360045483836105c1565b610bdf5760405162461bcd60e51b815260206004820152600f60248201527f4e6f7420416c6c6f776c697374656400000000000000000000000000000000006044820152606401610466565b6000600581610bf06101008861297a565b8152602001908152602001600020549050600061010086610c119190612b31565b6001901b905081811615610c675760405162461bcd60e51b815260206004820152601460248201527f44726f7020616c726561647920636c61696d65640000000000000000000000006044820152606401610466565b81811760056000610c7a6101008a61297a565b8152602081019190915260400160002055610c953386611732565b505050505050565b6002546001600160a01b03163314610cf75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610466565b610d016000611941565b565b6002546001600160a01b03163314610d5d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610466565b806004541415610daf5760405162461bcd60e51b815260206004820152601d60248201527f6d65726b656c526f6f7420616c7265616479206265696e67207365742e0000006044820152606401610466565b600455565b3360008181526001602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff16610e725760405162461bcd60e51b815260206004820152601660248201527f436f6e7472616374206973206e6f7420616374697665000000000000000000006044820152606401610466565b61052f3383836119a0565b600080610e8d602061010061297a565b610e97908461297a565b9150610ea6602061010061297a565b610eb09084612b31565b9050915091565b600080600581610ec96101008661297a565b8152602001908152602001600020549050600061010084610eea9190612b31565b6001901b91909116159392505050565b600080610f0d6001640100000000612a98565b90506000610f1c846020612a79565b9490941c169392505050565b336001600160a01b0386161480610f6257506001600160a01b038516600090815260016020908152604080832033845290915290205460ff165b610fd45760405162461bcd60e51b815260206004820152603760248201527f455243313135355061636b656442616c616e636523736166655472616e73666560448201527f7246726f6d3a20494e56414c49445f4f50455241544f520000000000000000006064820152608401610466565b6001600160a01b0384166110505760405162461bcd60e51b815260206004820152603860248201527f455243313135355061636b656442616c616e636523736166655472616e73666560448201527f7246726f6d3a20494e56414c49445f524543495049454e5400000000000000006064820152608401610466565b61105c858585856119fb565b610854858585855a86611a66565b6002546001600160a01b031633146110c45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610466565b6001600160a01b0381166111295760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610466565b61113281611941565b50565b6060816111595750506040805180820190915260018152600360fc1b602082015290565b8160005b8115611183578061116d81612b16565b915061117c9050600a8361297a565b915061115d565b60008167ffffffffffffffff81111561119e5761119e612b9d565b6040519080825280601f01601f1916602001820160405280156111c8576020820181803683370190505b5090505b841561124b576111dd600183612a98565b91506111ea600a86612b31565b6111f5906030612962565b60f81b81838151811061120a5761120a612b87565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611244600a8661297a565b94506111cc565b949350505050565b8151815181146112d65760405162461bcd60e51b815260206004820152604260248201527f455243313135355061636b656442616c616e6365235f7361666542617463685460448201527f72616e7366657246726f6d3a20494e56414c49445f4152524159535f4c454e476064820152610a8960f31b608482015260a401610466565b836001600160a01b0316856001600160a01b0316141580156112f85750600081115b156114c457600080611316856000815181106108f0576108f0612b87565b6001600160a01b038916600090815260208181526040808320858452909152812054875193955091935091611367919084908890859061135857611358612b87565b60200260200101516001611b98565b6001600160a01b038816600090815260208181526040808320878452909152812054875192935090916113b691908590899085906113a7576113a7612b87565b60200260200101516000611b98565b90508360015b8681101561147f576113d98982815181106108f0576108f0612b87565b909650945081861461143b576001600160a01b038b811660009081526020818152604080832086845280835281842098909855928d16825281815282822094825284815282822095909555878152948452808520549290935291909220549084905b61145284868a848151811061135857611358612b87565b935061146b83868a84815181106113a7576113a7612b87565b92508061147781612b16565b9150506113bc565b50506001600160a01b03808a16600090815260208181526040808320888452825280832095909555918a16815280825283812095815294905292209190915550611594565b60005b81811015611592578281815181106114e1576114e1612b87565b602002602001015161150c878684815181106114ff576114ff612b87565b602002602001015161038a565b10156115805760405162461bcd60e51b815260206004820152603660248201527f455243313135355061636b656442616c616e6365235f7361666542617463685460448201527f72616e7366657246726f6d3a20554e444552464c4f57000000000000000000006064820152608401610466565b8061158a81612b16565b9150506114c7565b505b836001600160a01b0316856001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb86866040516115e39291906128cc565b60405180910390a45050505050565b6001600160a01b0385163b15610c95576000856001600160a01b031663bc197c8184338a8989886040518763ffffffff1660e01b8152600401611639959493929190612818565b602060405180830381600088803b15801561165357600080fd5b5087f1158015611667573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061168c91906125e2565b90506001600160e01b0319811663bc197c8160e01b146117295760405162461bcd60e51b815260206004820152604c60248201527f455243313135355061636b656442616c616e6365235f63616c6c6f6e4552433160448201527f313535426174636852656365697665643a20494e56414c49445f4f4e5f52454360648201526b454956455f4d45535341474560a01b608482015260a401610466565b50505050505050565b80600114156117585761052f826000600160405180602001604052806000815250611e61565b806002141561177e5761052f826000600260405180602001604052806000815250611e61565b6040805160028082526060820183526000926020830190803683375050604080516002808252606082018352939450600093909250906020830190803683370190505090508260051415611854576001826000815181106117e1576117e1612b87565b602090810291909101015260028260018151811061180157611801612b87565b602002602001018181525050600a8160008151811061182257611822612b87565b602002602001018181525050600a8160018151811061184357611843612b87565b602002602001018181525050611920565b60008260008151811061186957611869612b87565b602090810291909101015260018260018151811061188957611889612b87565b60200260200101818152505082600314156118d4576002816000815181106118b3576118b3612b87565b60200260200101818152505060018160018151811061184357611843612b87565b8260041415611920576004816000815181106118f2576118f2612b87565b60200260200101818152505060028160018151811061191357611913612b87565b6020026020010181815250505b61193b84838360405180602001604052806000815250611ec6565b50505050565b600280546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6119ad83838360016120bf565b60408051838152602081018390526000916001600160a01b0386169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4505050565b611a0884838360016120bf565b611a1583838360006120bf565b60408051838152602081018390526001600160a01b03808616929087169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a450505050565b6001600160a01b0385163b15610c95576000856001600160a01b031663f23a6e6184338a8989886040518763ffffffff1660e01b8152600401611aad959493929190612876565b602060405180830381600088803b158015611ac757600080fd5b5087f1158015611adb573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611b0091906125e2565b90506001600160e01b0319811663f23a6e6160e01b146117295760405162461bcd60e51b815260206004820152604760248201527f455243313135355061636b656442616c616e6365235f63616c6c6f6e4552433160448201527f31353552656365697665643a20494e56414c49445f4f4e5f524543454956455f6064820152664d45535341474560c81b608482015260a401610466565b600080611ba6856020612a79565b90506000611bba6001640100000000612a98565b90506000846001811115611bd057611bd0612b71565b1415611cd657611be285831b88612962565b925086831015611c4f5760405162461bcd60e51b815260206004820152603260248201527f455243313135355061636b656442616c616e6365235f7669657755706461746560448201527142696e56616c75653a204f564552464c4f5760701b6064820152608401610466565b611c5b602060026129d1565b611c698689851c8416612962565b10611cd15760405162461bcd60e51b815260206004820152603260248201527f455243313135355061636b656442616c616e6365235f7669657755706461746560448201527142696e56616c75653a204f564552464c4f5760701b6064820152608401610466565b611e57565b6001846001811115611cea57611cea612b71565b1415611ddb57611cfc85831b88612a98565b925086831115611d6a5760405162461bcd60e51b815260206004820152603360248201527f455243313135355061636b656442616c616e6365235f7669657755706461746560448201527242696e56616c75653a20554e444552464c4f5760681b6064820152608401610466565b84818389901c161015611cd15760405162461bcd60e51b815260206004820152603360248201527f455243313135355061636b656442616c616e6365235f7669657755706461746560448201527242696e56616c75653a20554e444552464c4f5760681b6064820152608401610466565b60405162461bcd60e51b815260206004820152604560248201527f455243313135355061636b656442616c616e6365235f7669657755706461746560448201527f42696e56616c75653a20494e56414c49445f42494e5f57524954455f4f50455260648201526420aa24a7a760d91b608482015260a401610466565b5050949350505050565b611e6e84848460006120bf565b60408051848152602081018490526001600160a01b0386169160009133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461193b60008585855a86611a66565b8151835114611f3d5760405162461bcd60e51b815260206004820152603e60248201527f455243313135354d696e744275726e5061636b656442616c616e6365235f626160448201527f7463684d696e743a20494e56414c49445f4152524159535f4c454e47544800006064820152608401610466565b82511561205857600080611f5d856000815181106108f0576108f0612b87565b6001600160a01b038816600090815260208181526040808320858452909152812054875193955091935091611f9f91908490889085906113a7576113a7612b87565b86519091508360015b8281101561202c57611fc58982815181106108f0576108f0612b87565b9096509450818614612001576001600160a01b038a16600090815260208181526040808320948352939052828120949094558584529220549184905b61201884868a84815181106113a7576113a7612b87565b93508061202481612b16565b915050611fa8565b5050506001600160a01b0387166000908152602081815260408083209583529490529290922091909155505b836001600160a01b031660006001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb86866040516120a89291906128cc565b60405180910390a461193b60008585855a866115f2565b6000806120cb85610e7d565b6001600160a01b03881660009081526020818152604080832085845290915290205491935091506120fe90828686611b98565b6001600160a01b03909616600090815260208181526040808320948352939052919091209490945550505050565b82805461213890612adb565b90600052602060002090601f01602090048101928261215a57600085556121a0565b82601f1061217357805160ff19168380011785556121a0565b828001600101855582156121a0579182015b828111156121a0578251825591602001919060010190612185565b506121ac9291506121b0565b5090565b5b808211156121ac57600081556001016121b1565b600067ffffffffffffffff8311156121df576121df612b9d565b6121f2601f8401601f191660200161290d565b905082815283838301111561220657600080fd5b828260208301376000602084830101529392505050565b80356001600160a01b038116811461223457600080fd5b919050565b600082601f83011261224a57600080fd5b8135602061225f61225a8361293e565b61290d565b80838252828201915082860187848660051b890101111561227f57600080fd5b60005b8581101561229e57813584529284019290840190600101612282565b5090979650505050505050565b600082601f8301126122bc57600080fd5b6122cb838335602085016121c5565b9392505050565b6000602082840312156122e457600080fd5b6122cb8261221d565b6000806040838503121561230057600080fd5b6123098361221d565b91506123176020840161221d565b90509250929050565b600080600080600060a0868803121561233857600080fd5b6123418661221d565b945061234f6020870161221d565b9350604086013567ffffffffffffffff8082111561236c57600080fd5b61237889838a01612239565b9450606088013591508082111561238e57600080fd5b61239a89838a01612239565b935060808801359150808211156123b057600080fd5b506123bd888289016122ab565b9150509295509295909350565b600080600080600060a086880312156123e257600080fd5b6123eb8661221d565b94506123f96020870161221d565b93506040860135925060608601359150608086013567ffffffffffffffff81111561242357600080fd5b6123bd888289016122ab565b6000806040838503121561244257600080fd5b61244b8361221d565b91506020830135801515811461246057600080fd5b809150509250929050565b6000806040838503121561247e57600080fd5b6124878361221d565b946020939093013593505050565b600080604083850312156124a857600080fd5b823567ffffffffffffffff808211156124c057600080fd5b818501915085601f8301126124d457600080fd5b813560206124e461225a8361293e565b8083825282820191508286018a848660051b890101111561250457600080fd5b600096505b8487101561252e5761251a8161221d565b835260019690960195918301918301612509565b509650508601359250508082111561254557600080fd5b5061255285828601612239565b9150509250929050565b60006020828403121561256e57600080fd5b5035919050565b60008060006060848603121561258a57600080fd5b83359250602084013567ffffffffffffffff8111156125a857600080fd5b6125b486828701612239565b925050604084013590509250925092565b6000602082840312156125d757600080fd5b81356122cb81612bb3565b6000602082840312156125f457600080fd5b81516122cb81612bb3565b60006020828403121561261157600080fd5b813567ffffffffffffffff81111561262857600080fd5b8201601f8101841361263957600080fd5b61124b848235602084016121c5565b6000806040838503121561265b57600080fd5b50508035926020909101359150565b60008060006060848603121561267f57600080fd5b8335925060208401359150604084013567ffffffffffffffff8111156126a457600080fd5b6126b086828701612239565b9150509250925092565b600081518084526020808501945080840160005b838110156126ea578151875295820195908201906001016126ce565b509495945050505050565b6000815180845261270d816020860160208601612aaf565b601f01601f19169290920160200192915050565b8054600090600181811c908083168061273b57607f831692505b602080841082141561275d57634e487b7160e01b600052602260045260246000fd5b8180156127715760018114612782576127af565b60ff198616895284890196506127af565b60008881526020902060005b868110156127a75781548b82015290850190830161278e565b505084890196505b50505050505092915050565b600082516127cd818460208701612aaf565b9190910192915050565b60006122cb8284612721565b60006127ef8285612721565b83516127ff818360208801612aaf565b64173539b7b760d91b9101908152600501949350505050565b60006001600160a01b03808816835280871660208401525060a0604083015261284460a08301866126ba565b828103606084015261285681866126ba565b9050828103608084015261286a81856126f5565b98975050505050505050565b60006001600160a01b03808816835280871660208401525084604083015283606083015260a060808301526128ae60a08301846126f5565b979650505050505050565b6020815260006122cb60208301846126ba565b6040815260006128df60408301856126ba565b82810360208401526128f181856126ba565b95945050505050565b6020815260006122cb60208301846126f5565b604051601f8201601f1916810167ffffffffffffffff8111828210171561293657612936612b9d565b604052919050565b600067ffffffffffffffff82111561295857612958612b9d565b5060051b60200190565b6000821982111561297557612975612b45565b500190565b60008261298957612989612b5b565b500490565b600181815b808511156129c95781600019048211156129af576129af612b45565b808516156129bc57918102915b93841c9390800290612993565b509250929050565b60006122cb83836000826129e7575060016103ce565b816129f4575060006103ce565b8160018114612a0a5760028114612a1457612a30565b60019150506103ce565b60ff841115612a2557612a25612b45565b50506001821b6103ce565b5060208310610133831016604e8410600b8410161715612a53575081810a6103ce565b612a5d838361298e565b8060001904821115612a7157612a71612b45565b029392505050565b6000816000190483118215151615612a9357612a93612b45565b500290565b600082821015612aaa57612aaa612b45565b500390565b60005b83811015612aca578181015183820152602001612ab2565b8381111561193b5750506000910152565b600181811c90821680612aef57607f821691505b60208210811415612b1057634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415612b2a57612b2a612b45565b5060010190565b600082612b4057612b40612b5b565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b03198116811461113257600080fdfea26469706673582212207d36b5ea4d758aa3f6ae660136764486e68fa3aa8944f4595bdc3444dd70472764736f6c63430008070033

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061017c5760003560e01c806365aad4fd116100e3578063db90e83c1161008c578063eaec5f8111610066578063eaec5f8114610351578063f242432a14610364578063f2fde38b1461037757600080fd5b8063db90e83c146102da578063ddc5ba1b14610302578063e985e9c51461031557600080fd5b80638da5cb5b116100bd5780638da5cb5b14610299578063a22cb465146102b4578063b390c0ab146102c757600080fd5b806365aad4fd1461026b578063715018a61461027e5780637cb647591461028657600080fd5b80630e89341c116101455780632eb2c2d61161011f5780632eb2c2d61461022f5780632eb4a7ab146102425780634e1273f41461024b57600080fd5b80630e89341c1461020757806322f3e2d41461021a57806329c68dc11461022757600080fd5b8062fdd58e1461018157806301ffc9a7146101a757806302fe5305146101ca57806306fdde03146101df5780630a02831c146101f4575b600080fd5b61019461018f36600461246b565b61038a565b6040519081526020015b60405180910390f35b6101ba6101b53660046125c5565b6103d4565b604051901515815260200161019e565b6101dd6101d83660046125ff565b610410565b005b6101e7610533565b60405161019e91906128fa565b6101ba610202366004612575565b6105c1565b6101e761021536600461255c565b610670565b6006546101ba9060ff1681565b6101dd6106a4565b6101dd61023d366004612320565b610712565b61019460045481565b61025e610259366004612495565b61085b565b60405161019e91906128b9565b6101dd61027936600461266a565b610aed565b6101dd610c9d565b6101dd61029436600461255c565b610d03565b6002546040516001600160a01b03909116815260200161019e565b6101dd6102c236600461242f565b610db4565b6101dd6102d5366004612648565b610e20565b6102ed6102e836600461255c565b610e7d565b6040805192835260208301919091520161019e565b6101ba61031036600461255c565b610eb7565b6101ba6103233660046122ed565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205460ff1690565b61019461035f366004612648565b610efa565b6101dd6103723660046123ca565b610f28565b6101dd6103853660046122d2565b61106a565b600080600061039884610e7d565b6001600160a01b03871660009081526020818152604080832085845290915290205491935091506103c99082610efa565b925050505b92915050565b60006001600160e01b03198216636cdb3d1360e11b14156103f757506001919050565b6301ffc9a760e01b6001600160e01b03198316146103ce565b6002546001600160a01b0316331461046f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b8060405160200161048091906127bb565b6040516020818303038152906040528051906020012060036040516020016104a891906127d7565b60405160208183030381529060405280519060200120141561051c5760405162461bcd60e51b815260206004820152602760248201527f6261736555524920697320616c7265616479207468652076616c75652062656960448201526637339039b2ba1760c91b6064820152608401610466565b805161052f90600390602084019061212c565b5050565b6007805461054090612adb565b80601f016020809104026020016040519081016040528092919081815260200182805461056c90612adb565b80156105b95780601f1061058e576101008083540402835291602001916105b9565b820191906000526020600020905b81548152906001019060200180831161059c57829003601f168201915b505050505081565b600081815b84518110156106655760008582815181106105e3576105e3612b87565b60200260200101519050808311610625576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250610652565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b508061065d81612b16565b9150506105c6565b509093149392505050565b6060600361067d83611135565b60405160200161068e9291906127e3565b6040516020818303038152906040529050919050565b6002546001600160a01b031633146106fe5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610466565b6006805460ff19811660ff90911615179055565b336001600160a01b038616148061074c57506001600160a01b038516600090815260016020908152604080832033845290915290205460ff165b6107be5760405162461bcd60e51b815260206004820152603c60248201527f455243313135355061636b656442616c616e636523736166654261746368547260448201527f616e7366657246726f6d3a20494e56414c49445f4f50455241544f52000000006064820152608401610466565b6001600160a01b03841661083a5760405162461bcd60e51b815260206004820152603d60248201527f455243313135355061636b656442616c616e636523736166654261746368547260448201527f616e7366657246726f6d3a20494e56414c49445f524543495049454e540000006064820152608401610466565b61084685858585611253565b610854858585855a866115f2565b5050505050565b815181516060919081146108d75760405162461bcd60e51b815260206004820152603960248201527f455243313135355061636b656442616c616e63652362616c616e63654f66426160448201527f7463683a20494e56414c49445f41525241595f4c454e475448000000000000006064820152608401610466565b6000806108fd856000815181106108f0576108f0612b87565b6020026020010151610e7d565b9150915060008060008860008151811061091957610919612b87565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000848152602001908152602001600020549050600083905060008567ffffffffffffffff81111561097557610975612b9d565b60405190808252806020026020018201604052801561099e578160200160208202803683370190505b5090506109ab8385610efa565b816000815181106109be576109be612b87565b602090810291909101015260015b86811015610ae0576109e98982815181106108f0576108f0612b87565b90965094508286141580610a4d5750898181518110610a0a57610a0a612b87565b60200260200101516001600160a01b03168a600183610a299190612a98565b81518110610a3957610a39612b87565b60200260200101516001600160a01b031614155b15610aa7576000808b8381518110610a6757610a67612b87565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008781526020019081526020016000205493508592505b610ab18486610efa565b828281518110610ac357610ac3612b87565b602090810291909101015280610ad881612b16565b9150506109cc565b5098975050505050505050565b60065460ff16610b3f5760405162461bcd60e51b815260206004820152601660248201527f436f6e7472616374206973206e6f7420616374697665000000000000000000006044820152606401610466565b6040516bffffffffffffffffffffffff193360601b1660208201526034810183905260548101849052600090607401604051602081830303815290604052805190602001209050610b9360045483836105c1565b610bdf5760405162461bcd60e51b815260206004820152600f60248201527f4e6f7420416c6c6f776c697374656400000000000000000000000000000000006044820152606401610466565b6000600581610bf06101008861297a565b8152602001908152602001600020549050600061010086610c119190612b31565b6001901b905081811615610c675760405162461bcd60e51b815260206004820152601460248201527f44726f7020616c726561647920636c61696d65640000000000000000000000006044820152606401610466565b81811760056000610c7a6101008a61297a565b8152602081019190915260400160002055610c953386611732565b505050505050565b6002546001600160a01b03163314610cf75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610466565b610d016000611941565b565b6002546001600160a01b03163314610d5d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610466565b806004541415610daf5760405162461bcd60e51b815260206004820152601d60248201527f6d65726b656c526f6f7420616c7265616479206265696e67207365742e0000006044820152606401610466565b600455565b3360008181526001602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60065460ff16610e725760405162461bcd60e51b815260206004820152601660248201527f436f6e7472616374206973206e6f7420616374697665000000000000000000006044820152606401610466565b61052f3383836119a0565b600080610e8d602061010061297a565b610e97908461297a565b9150610ea6602061010061297a565b610eb09084612b31565b9050915091565b600080600581610ec96101008661297a565b8152602001908152602001600020549050600061010084610eea9190612b31565b6001901b91909116159392505050565b600080610f0d6001640100000000612a98565b90506000610f1c846020612a79565b9490941c169392505050565b336001600160a01b0386161480610f6257506001600160a01b038516600090815260016020908152604080832033845290915290205460ff165b610fd45760405162461bcd60e51b815260206004820152603760248201527f455243313135355061636b656442616c616e636523736166655472616e73666560448201527f7246726f6d3a20494e56414c49445f4f50455241544f520000000000000000006064820152608401610466565b6001600160a01b0384166110505760405162461bcd60e51b815260206004820152603860248201527f455243313135355061636b656442616c616e636523736166655472616e73666560448201527f7246726f6d3a20494e56414c49445f524543495049454e5400000000000000006064820152608401610466565b61105c858585856119fb565b610854858585855a86611a66565b6002546001600160a01b031633146110c45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610466565b6001600160a01b0381166111295760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610466565b61113281611941565b50565b6060816111595750506040805180820190915260018152600360fc1b602082015290565b8160005b8115611183578061116d81612b16565b915061117c9050600a8361297a565b915061115d565b60008167ffffffffffffffff81111561119e5761119e612b9d565b6040519080825280601f01601f1916602001820160405280156111c8576020820181803683370190505b5090505b841561124b576111dd600183612a98565b91506111ea600a86612b31565b6111f5906030612962565b60f81b81838151811061120a5761120a612b87565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611244600a8661297a565b94506111cc565b949350505050565b8151815181146112d65760405162461bcd60e51b815260206004820152604260248201527f455243313135355061636b656442616c616e6365235f7361666542617463685460448201527f72616e7366657246726f6d3a20494e56414c49445f4152524159535f4c454e476064820152610a8960f31b608482015260a401610466565b836001600160a01b0316856001600160a01b0316141580156112f85750600081115b156114c457600080611316856000815181106108f0576108f0612b87565b6001600160a01b038916600090815260208181526040808320858452909152812054875193955091935091611367919084908890859061135857611358612b87565b60200260200101516001611b98565b6001600160a01b038816600090815260208181526040808320878452909152812054875192935090916113b691908590899085906113a7576113a7612b87565b60200260200101516000611b98565b90508360015b8681101561147f576113d98982815181106108f0576108f0612b87565b909650945081861461143b576001600160a01b038b811660009081526020818152604080832086845280835281842098909855928d16825281815282822094825284815282822095909555878152948452808520549290935291909220549084905b61145284868a848151811061135857611358612b87565b935061146b83868a84815181106113a7576113a7612b87565b92508061147781612b16565b9150506113bc565b50506001600160a01b03808a16600090815260208181526040808320888452825280832095909555918a16815280825283812095815294905292209190915550611594565b60005b81811015611592578281815181106114e1576114e1612b87565b602002602001015161150c878684815181106114ff576114ff612b87565b602002602001015161038a565b10156115805760405162461bcd60e51b815260206004820152603660248201527f455243313135355061636b656442616c616e6365235f7361666542617463685460448201527f72616e7366657246726f6d3a20554e444552464c4f57000000000000000000006064820152608401610466565b8061158a81612b16565b9150506114c7565b505b836001600160a01b0316856001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb86866040516115e39291906128cc565b60405180910390a45050505050565b6001600160a01b0385163b15610c95576000856001600160a01b031663bc197c8184338a8989886040518763ffffffff1660e01b8152600401611639959493929190612818565b602060405180830381600088803b15801561165357600080fd5b5087f1158015611667573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061168c91906125e2565b90506001600160e01b0319811663bc197c8160e01b146117295760405162461bcd60e51b815260206004820152604c60248201527f455243313135355061636b656442616c616e6365235f63616c6c6f6e4552433160448201527f313535426174636852656365697665643a20494e56414c49445f4f4e5f52454360648201526b454956455f4d45535341474560a01b608482015260a401610466565b50505050505050565b80600114156117585761052f826000600160405180602001604052806000815250611e61565b806002141561177e5761052f826000600260405180602001604052806000815250611e61565b6040805160028082526060820183526000926020830190803683375050604080516002808252606082018352939450600093909250906020830190803683370190505090508260051415611854576001826000815181106117e1576117e1612b87565b602090810291909101015260028260018151811061180157611801612b87565b602002602001018181525050600a8160008151811061182257611822612b87565b602002602001018181525050600a8160018151811061184357611843612b87565b602002602001018181525050611920565b60008260008151811061186957611869612b87565b602090810291909101015260018260018151811061188957611889612b87565b60200260200101818152505082600314156118d4576002816000815181106118b3576118b3612b87565b60200260200101818152505060018160018151811061184357611843612b87565b8260041415611920576004816000815181106118f2576118f2612b87565b60200260200101818152505060028160018151811061191357611913612b87565b6020026020010181815250505b61193b84838360405180602001604052806000815250611ec6565b50505050565b600280546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6119ad83838360016120bf565b60408051838152602081018390526000916001600160a01b0386169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4505050565b611a0884838360016120bf565b611a1583838360006120bf565b60408051838152602081018390526001600160a01b03808616929087169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a450505050565b6001600160a01b0385163b15610c95576000856001600160a01b031663f23a6e6184338a8989886040518763ffffffff1660e01b8152600401611aad959493929190612876565b602060405180830381600088803b158015611ac757600080fd5b5087f1158015611adb573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611b0091906125e2565b90506001600160e01b0319811663f23a6e6160e01b146117295760405162461bcd60e51b815260206004820152604760248201527f455243313135355061636b656442616c616e6365235f63616c6c6f6e4552433160448201527f31353552656365697665643a20494e56414c49445f4f4e5f524543454956455f6064820152664d45535341474560c81b608482015260a401610466565b600080611ba6856020612a79565b90506000611bba6001640100000000612a98565b90506000846001811115611bd057611bd0612b71565b1415611cd657611be285831b88612962565b925086831015611c4f5760405162461bcd60e51b815260206004820152603260248201527f455243313135355061636b656442616c616e6365235f7669657755706461746560448201527142696e56616c75653a204f564552464c4f5760701b6064820152608401610466565b611c5b602060026129d1565b611c698689851c8416612962565b10611cd15760405162461bcd60e51b815260206004820152603260248201527f455243313135355061636b656442616c616e6365235f7669657755706461746560448201527142696e56616c75653a204f564552464c4f5760701b6064820152608401610466565b611e57565b6001846001811115611cea57611cea612b71565b1415611ddb57611cfc85831b88612a98565b925086831115611d6a5760405162461bcd60e51b815260206004820152603360248201527f455243313135355061636b656442616c616e6365235f7669657755706461746560448201527242696e56616c75653a20554e444552464c4f5760681b6064820152608401610466565b84818389901c161015611cd15760405162461bcd60e51b815260206004820152603360248201527f455243313135355061636b656442616c616e6365235f7669657755706461746560448201527242696e56616c75653a20554e444552464c4f5760681b6064820152608401610466565b60405162461bcd60e51b815260206004820152604560248201527f455243313135355061636b656442616c616e6365235f7669657755706461746560448201527f42696e56616c75653a20494e56414c49445f42494e5f57524954455f4f50455260648201526420aa24a7a760d91b608482015260a401610466565b5050949350505050565b611e6e84848460006120bf565b60408051848152602081018490526001600160a01b0386169160009133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461193b60008585855a86611a66565b8151835114611f3d5760405162461bcd60e51b815260206004820152603e60248201527f455243313135354d696e744275726e5061636b656442616c616e6365235f626160448201527f7463684d696e743a20494e56414c49445f4152524159535f4c454e47544800006064820152608401610466565b82511561205857600080611f5d856000815181106108f0576108f0612b87565b6001600160a01b038816600090815260208181526040808320858452909152812054875193955091935091611f9f91908490889085906113a7576113a7612b87565b86519091508360015b8281101561202c57611fc58982815181106108f0576108f0612b87565b9096509450818614612001576001600160a01b038a16600090815260208181526040808320948352939052828120949094558584529220549184905b61201884868a84815181106113a7576113a7612b87565b93508061202481612b16565b915050611fa8565b5050506001600160a01b0387166000908152602081815260408083209583529490529290922091909155505b836001600160a01b031660006001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb86866040516120a89291906128cc565b60405180910390a461193b60008585855a866115f2565b6000806120cb85610e7d565b6001600160a01b03881660009081526020818152604080832085845290915290205491935091506120fe90828686611b98565b6001600160a01b03909616600090815260208181526040808320948352939052919091209490945550505050565b82805461213890612adb565b90600052602060002090601f01602090048101928261215a57600085556121a0565b82601f1061217357805160ff19168380011785556121a0565b828001600101855582156121a0579182015b828111156121a0578251825591602001919060010190612185565b506121ac9291506121b0565b5090565b5b808211156121ac57600081556001016121b1565b600067ffffffffffffffff8311156121df576121df612b9d565b6121f2601f8401601f191660200161290d565b905082815283838301111561220657600080fd5b828260208301376000602084830101529392505050565b80356001600160a01b038116811461223457600080fd5b919050565b600082601f83011261224a57600080fd5b8135602061225f61225a8361293e565b61290d565b80838252828201915082860187848660051b890101111561227f57600080fd5b60005b8581101561229e57813584529284019290840190600101612282565b5090979650505050505050565b600082601f8301126122bc57600080fd5b6122cb838335602085016121c5565b9392505050565b6000602082840312156122e457600080fd5b6122cb8261221d565b6000806040838503121561230057600080fd5b6123098361221d565b91506123176020840161221d565b90509250929050565b600080600080600060a0868803121561233857600080fd5b6123418661221d565b945061234f6020870161221d565b9350604086013567ffffffffffffffff8082111561236c57600080fd5b61237889838a01612239565b9450606088013591508082111561238e57600080fd5b61239a89838a01612239565b935060808801359150808211156123b057600080fd5b506123bd888289016122ab565b9150509295509295909350565b600080600080600060a086880312156123e257600080fd5b6123eb8661221d565b94506123f96020870161221d565b93506040860135925060608601359150608086013567ffffffffffffffff81111561242357600080fd5b6123bd888289016122ab565b6000806040838503121561244257600080fd5b61244b8361221d565b91506020830135801515811461246057600080fd5b809150509250929050565b6000806040838503121561247e57600080fd5b6124878361221d565b946020939093013593505050565b600080604083850312156124a857600080fd5b823567ffffffffffffffff808211156124c057600080fd5b818501915085601f8301126124d457600080fd5b813560206124e461225a8361293e565b8083825282820191508286018a848660051b890101111561250457600080fd5b600096505b8487101561252e5761251a8161221d565b835260019690960195918301918301612509565b509650508601359250508082111561254557600080fd5b5061255285828601612239565b9150509250929050565b60006020828403121561256e57600080fd5b5035919050565b60008060006060848603121561258a57600080fd5b83359250602084013567ffffffffffffffff8111156125a857600080fd5b6125b486828701612239565b925050604084013590509250925092565b6000602082840312156125d757600080fd5b81356122cb81612bb3565b6000602082840312156125f457600080fd5b81516122cb81612bb3565b60006020828403121561261157600080fd5b813567ffffffffffffffff81111561262857600080fd5b8201601f8101841361263957600080fd5b61124b848235602084016121c5565b6000806040838503121561265b57600080fd5b50508035926020909101359150565b60008060006060848603121561267f57600080fd5b8335925060208401359150604084013567ffffffffffffffff8111156126a457600080fd5b6126b086828701612239565b9150509250925092565b600081518084526020808501945080840160005b838110156126ea578151875295820195908201906001016126ce565b509495945050505050565b6000815180845261270d816020860160208601612aaf565b601f01601f19169290920160200192915050565b8054600090600181811c908083168061273b57607f831692505b602080841082141561275d57634e487b7160e01b600052602260045260246000fd5b8180156127715760018114612782576127af565b60ff198616895284890196506127af565b60008881526020902060005b868110156127a75781548b82015290850190830161278e565b505084890196505b50505050505092915050565b600082516127cd818460208701612aaf565b9190910192915050565b60006122cb8284612721565b60006127ef8285612721565b83516127ff818360208801612aaf565b64173539b7b760d91b9101908152600501949350505050565b60006001600160a01b03808816835280871660208401525060a0604083015261284460a08301866126ba565b828103606084015261285681866126ba565b9050828103608084015261286a81856126f5565b98975050505050505050565b60006001600160a01b03808816835280871660208401525084604083015283606083015260a060808301526128ae60a08301846126f5565b979650505050505050565b6020815260006122cb60208301846126ba565b6040815260006128df60408301856126ba565b82810360208401526128f181856126ba565b95945050505050565b6020815260006122cb60208301846126f5565b604051601f8201601f1916810167ffffffffffffffff8111828210171561293657612936612b9d565b604052919050565b600067ffffffffffffffff82111561295857612958612b9d565b5060051b60200190565b6000821982111561297557612975612b45565b500190565b60008261298957612989612b5b565b500490565b600181815b808511156129c95781600019048211156129af576129af612b45565b808516156129bc57918102915b93841c9390800290612993565b509250929050565b60006122cb83836000826129e7575060016103ce565b816129f4575060006103ce565b8160018114612a0a5760028114612a1457612a30565b60019150506103ce565b60ff841115612a2557612a25612b45565b50506001821b6103ce565b5060208310610133831016604e8410600b8410161715612a53575081810a6103ce565b612a5d838361298e565b8060001904821115612a7157612a71612b45565b029392505050565b6000816000190483118215151615612a9357612a93612b45565b500290565b600082821015612aaa57612aaa612b45565b500390565b60005b83811015612aca578181015183820152602001612ab2565b8381111561193b5750506000910152565b600181811c90821680612aef57607f821691505b60208210811415612b1057634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415612b2a57612b2a612b45565b5060010190565b600082612b4057612b40612b5b565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b03198116811461113257600080fdfea26469706673582212207d36b5ea4d758aa3f6ae660136764486e68fa3aa8944f4595bdc3444dd70472764736f6c63430008070033

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

OVERVIEW

SoundMint Vinyl. Your all-access pass to SoundMint. Rewarded to holders of SoundMint's Genesis collection 'WE ARE KLOUD'.

Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.