Contract 0x383767b384df365f71fd57d8f7a44d489f03ff2d

 
 
Txn Hash
Method
Block
From
To
Value [Txn Fee]
0x1779f2546dbe02be8dbb95cce2a1562fca414357f20ba139e6faa11f8676bf9dSafe Transfer Fr...379555562023-01-11 19:47:26139 days 4 hrs ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.001595950052 40.514572826
0xb7d5bab6b4ebb76cd559cb5a42429877a3e0e19653e3a503d667a19d099adbcfSafe Transfer Fr...377605822023-01-06 23:36:36144 days 46 mins ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.00326755004 57.840933938
0x8ab066e33668452e58946a52872f7393d8c6038619b02c940783149db8d9295aSet Approval For...376751892023-01-04 20:39:30146 days 3 hrs ago0x9e9bf5db1c0931f5c3984685fad97351e7e42a2a IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.00292423953 63.392649537
0x9c3d2ca864b76fd48f5d7b8a75cf997f8860e8f196f0b26b75094d17f88bfd73Safe Transfer Fr...373472102022-12-27 17:20:10154 days 7 hrs ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.001996794036 35.346492191
0x44ea403b12f850a9622f58d5fac3dac7f2b166e2daa87d24351e8f500676c623Safe Transfer Fr...373095782022-12-26 18:52:39155 days 5 hrs ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.001893511092 33.518216602
0xb8bab3e1891fe167a064333216aa5c9e10c49b52d6f87c48ac2e9ff0f3327070Safe Transfer Fr...371496272022-12-22 19:15:07159 days 5 hrs ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.003024420052 53.537138925
0x9104bd2801dace52cb3654136675fc9f0660b0b985fbf0ac894f5d7914244110Safe Transfer Fr...371044162022-12-21 16:22:52160 days 8 hrs ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.00315136323 55.784239021
0x1f77c05fb2b368f0130269993f09731ab540c9d35de7528d9dec46bd576cf382Safe Transfer Fr...370687962022-12-20 19:24:42161 days 4 hrs ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.003016005152 53.388181556
0x6a021b1e1cb46f2a3b9813878ffb2838797fde069eeafa93cebde8940937c661Safe Transfer Fr...370359372022-12-19 23:18:49162 days 1 hr ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.007492655189 144.948061402
0xb7ecdfb5e9499179f6e9a74ba8378cb78b1263c0a26a19fbb9621ef515ef2c1bSafe Transfer Fr...369627402022-12-18 2:57:23163 days 21 hrs ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.003707471802 65.628262455
0x555dff8155fef4f2bc3c35958267548df62102f50c07102b17c2505b3bf45135Safe Transfer Fr...369556582022-12-17 22:36:19164 days 1 hr ago0x4eb972a2f3782f5d3fd96ad8d67dbc4e98529a72 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.001579183967 30.54987169
0x71e6051917b1bed67345664cbb8200d408715a522aadef5ec505d4de7213ba01Safe Transfer Fr...369518742022-12-17 20:19:47164 days 4 hrs ago0x4eb972a2f3782f5d3fd96ad8d67dbc4e98529a72 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.001056781161 30.54987169
0x4aa3a0c977fc63237fbdcfe39912c16448af5d3641173dbf91b8859ad95134abSafe Transfer Fr...369498042022-12-17 19:03:44164 days 5 hrs ago0x5a7f1c1d7d4b8a897cb660fa8f39a2383b5a046b IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.002120483865 41.021509425
0x3cd4d27503a3f0c6d9a6803603e09a077fc488880571df2163833d91d9d05329Set Approval For...369483762022-12-17 18:12:15164 days 6 hrs ago0x85a4eb68f545dc2e8686db8a1e231d9d8b7201d8 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.004762878266 103.251279389
0xe44d0fa65523a57a79557dd04b3adf16607c61b095850dbd836c122fe84ae5a2Safe Transfer Fr...369482952022-12-17 18:07:37164 days 6 hrs ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.004224551312 74.781408213
0xa44f364ba2cf63f1139f6b59d217dbd25c8324b0781937506aabd20e18f80b6dSafe Transfer Fr...369482042022-12-17 18:04:10164 days 6 hrs ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.00314068281 55.595178272
0xa6bb645b94aa1d6ea9a34795ca8f15571c4e40fb982248ca7b70999d4d0bafabSafe Transfer Fr...369480402022-12-17 17:58:15164 days 6 hrs ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.002230080552 39.476041793
0xb3df7b9ea9335c54fac95fd6d4ab65a428bd668e7a862c1cd7b3ea4f4aec79a7Safe Transfer Fr...369479622022-12-17 17:55:31164 days 6 hrs ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.002087152703 36.945987113
0x181754de02c928af38dc764caf601ed3a62cf5a2e7a6eb09fbab0df5859a516bSafe Transfer Fr...369479052022-12-17 17:53:37164 days 6 hrs ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.002026867534 35.878841861
0x81a95b97cbb4594aff247e8c1deed805d728efe33bd04c2a9b6d1d6d47b5a67bSafe Transfer Fr...369041972022-12-16 14:58:12165 days 9 hrs ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.008451447738 149.604328731
0xb0941ec880faa8f5288a6dfccc98f41adc56704e6b73cd405f999a006837f370Auto Mint368773572022-12-15 22:34:28166 days 1 hr ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.004369687514 42.858561674
0x926efb38b30f0ba06c3598e76e92e7cd826c920b09daa091cf2999b77840da46Safe Transfer Fr...368772722022-12-15 22:31:34166 days 1 hr ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.002304928219 40.800966853
0xf3c95c93513bc54a30cdd913dc089cebec83f2028521f59c6dbb62351c0e9e72Safe Transfer Fr...368701762022-12-15 18:25:13166 days 5 hrs ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.006213223263 109.984126316
0x9a9f7c9dacc7359630b27f03ac89439cdec6a36b1a6056d764401bc6cfdd7f01Set Approval For...368701042022-12-15 18:22:45166 days 6 hrs ago0x98d9df44c792eaa29826dd01b3bd205a15efb78c IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.006209957713 134.62155507
0xb0cd1559bb7770380de18ecce1d6e56d99e34307f64e2376c374754ac555b107Safe Transfer Fr...368639872022-12-15 14:52:24166 days 9 hrs ago0x0cec8578400d2fcfe831461df8853dc780ef04f2 IN  0x383767b384df365f71fd57d8f7a44d489f03ff2d0 MATIC0.012426193844 219.963779738
[ Download CSV Export 
Latest 1 internal transaction
Parent Txn Hash Block From To Value
0xd75b01ce743e29bee31f9cb0e5d302fc0022a7bde82173673245e43b63c2a6fe368221712022-12-14 13:25:26167 days 10 hrs ago 0xcc1ae35f30946a5019401fd5b9e5a988afb4a169  Contract Creation0 MATIC
[ Download CSV Export 
Loading

Similar Match Source Code
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0x214Cb1daC9370A360f2f3F0DAa99b09dE58f87D5

Contract Name:
ERC1155Ikasumi

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license
File 1 of 1 : Ikasumi.sol
// SPDX-License-Identifier: MIT

/**

MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMWWWWWWWWWWWWWWWMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMWWNXXKKKKKKKXXXXKKKKKKXXNWWMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMWNXKKKKXXNWWWWMMWWWWMWWWWNXXXKKKXNWMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMWNXKKKXNWMMMMMMMMMNOdxKWMMMMMMMMWNXKKKXNWMMMMMMMMMMMMMM
MMMMMMMMMMMMMWXKKKNWMMMMMMMMMMMMNx:;;l0WMMMMMMMMMMMWNK0KXWMMMMMMMMMMMM
MMMMMMMMMMMWXKKXWMMMMMMMMMMMMMMXd:;;;;cOWMMMMMMMMMMMMMWXKKXWMMMMMMMMMM
MMMMMMMMMWNKKXWMMMMMMMMMMMMMMWKo;;col:;:kNMMMMMMMMMMMMMMWX0KNWMMMMMMMM
MMMMMMMMWX0XWMMMMMMMMMMMMMMMWOl;;oKWXkc;:dXMMMMMMMMMMMMMMMWX0XWMMMMMMM
MMMMMMMNKKNWMMMMMMMMMMMMMMMNkc;:dXMMMWOc;;oKWMMMMMMMMMMMMMMWNKKNMMMMMM
MMMMMMNKKNMMMMMMMMMMMMMMMMNx:;:xNMMMMMW0l;;l0WMMMMMMMWMMMMMMMNKKNMMMMM
MMMMMNKKNMMMMMMMMMMMMMMMMXd:;ckNMMMMMMMMKo:;cOWMMMMXkxkXWMMMMMNKKNMMMM
MMMMWK0NMMMMMMMMMMMMMMMWKo;;l0WMMMMMMMMMMXx:;:xNMMW0lccxXMMMMMMN0KWMMM
MMMMX0XWMMMMMMWWMMMMMMWOl;;oKWMMMMMMMMMMMMNkc;:dXMMNklcoKMMMMMMMX0XMMM
MMMWKKNMMWK0OkkkkkkKWNkc;:dXMMMMMMMMMMMMMMMWOl;;oKWMXdcxNMMMMMMMNKKWMM
MMMN0XWMMWNXX0OdlccdKOc;:xNMMMWXKKXNWNNNNWWMW0o;;l0WNkdKWMMMMMMMWX0NMM
MMMX0XMMMMMMMMMN0dlcdOxoONMMMMW0xdddddodxk0KNWXd:;l0Kx0WMMMMMMMMMX0XMM
MMMX0NMMMMMMMMMMWXxlcoOXWMMMMWKkolclodkKNNNNWWMNxcxOkKWMMMMMMMMMMX0XMM
MMMX0XMMMMMMMMMMMMNklclkNMMWXklccodxdodKWMMMMMMMNKOkKWMMMMMMMMMMMX0XMM
MMMN0XWMMMMMMMMMMMMNOoclxXN0occcdKX0xlco0WMMMMMMNOOXMMMMMMMMMMMMMX0NMM
MMMWKKWMMMMMMMMMMMMMW0dccoxocccdKWMWNklclONMMMMXOONMMMMMMMMMMMMMWKKWMM
MMMMX0XMMMMMMMMMMMMMMWKdcccccco0WMMMMNOoclkNWWKk0NMMMMMMMMMMMMMMX0XWMM
MMMMWKKNMMMMMMMMMMMMMMMXxlcccckNMMMMMMW0oclxK0kKWMMMMMMMMMMMMMMNKKWMMM
MMMMMN0KWMMMMMMMMMMMMMMMNklccoKWMMMMMMMWKdlcoxKWMMMMMMMMMMMMMMWK0NMMMM
MMMMMMN0KWMMMMMMMMMMMMMMMNOod0KXWMMMMMMNK0xoxXWMMMMMMMMMMMMMMWK0NMMMMM
MMMMMMMN0KNMMMMMMMMMMMMMMMWXKkll0WMMMMXdcoOKNMMMMMMMMMMMMMMMNK0NMMMMMM
MMMMMMMMNK0XWMMMMMMMMMMMMMMMNd:;cOWMWKo:;c0WMMMMMMMMMMMMMMWX0KNMMMMMMM
MMMMMMMMMWXKKNWMMMMMMMMMMMMMMXd:;cx0kl;;l0WMMMMMMMMMMMMMWNKKXWMMMMMMMM
MMMMMMMMMMMWX0KNWMMMMMMMMMMMMMNkc;;::;:oKWMMMMMMMMMMMMWNK0XWMMMMMMMMMM
MMMMMMMMMMMMMNXKKXNWMMMMMMMMMMMWOc;;;:dXMMMMMMMMMMMWNXKKXWMMMMMMMMMMMM
MMMMMMMMMMMMMMMWNKKKXNWMMMMMMMMMW0l:ckNMMMMMMMMMWNXKKKNWMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMWNXKKKXXNWWWMMMMX0KWMMMWWWNXXKKKXNWMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMWWNXXKKKKKXXXXXXXXXXKKKKXXNWWMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMWWNNNNNNNNNNNNWWWMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM


---------------------- [ WPSmartContracts.com ] ----------------------

                       [ Blockchain Made Easy ]


    |
    |  ERC-1155 NFT Token Advanced Marketplace
    |
    |----------------------------
    |
    |  Flavors
    |
    |  >  Ikasumi v.1: Standard ERC-1155 Token with Marketplace
    |
    |                  > Token Marketplace
    |                  > Royalties
    |                  > Lazy minting
    |

*/

pragma solidity ^0.8.2;

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        } else if (error == RecoverError.InvalidSignatureV) {
            revert("ECDSA: invalid signature 'v' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        // Check the signature length
        // - case 65: r,s,v signature (standard)
        // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else if (signature.length == 64) {
            bytes32 r;
            bytes32 vs;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                vs := mload(add(signature, 0x40))
            }
            return tryRecover(hash, r, vs);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s;
        uint8 v;
        assembly {
            s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
            v := add(shr(255, vs), 27)
        }
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }
        if (v != 27 && v != 28) {
            return (address(0), RecoverError.InvalidSignatureV);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
 * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
 * they need in their contracts using a combination of `abi.encode` and `keccak256`.
 *
 * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
 * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
 * ({_hashTypedDataV4}).
 *
 * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
 * the chain id to protect against replay attacks on an eventual fork of the chain.
 *
 * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
 * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
 *
 * _Available since v3.4._
 */
abstract contract EIP712 {
    /* solhint-disable var-name-mixedcase */
    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
    // invalidate the cached domain separator if the chain id changes.
    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
    uint256 private immutable _CACHED_CHAIN_ID;

    bytes32 private immutable _HASHED_NAME;
    bytes32 private immutable _HASHED_VERSION;
    bytes32 private immutable _TYPE_HASH;

    /* solhint-enable var-name-mixedcase */

    /**
     * @dev Initializes the domain separator and parameter caches.
     *
     * The meaning of `name` and `version` is specified in
     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
     *
     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
     * - `version`: the current major version of the signing domain.
     *
     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
     * contract upgrade].
     */
    constructor(string memory name, string memory version) {
        bytes32 hashedName = keccak256(bytes(name));
        bytes32 hashedVersion = keccak256(bytes(version));
        bytes32 typeHash = keccak256(
            "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
        );
        _HASHED_NAME = hashedName;
        _HASHED_VERSION = hashedVersion;
        _CACHED_CHAIN_ID = block.chainid;
        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
        _TYPE_HASH = typeHash;
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparatorV4() internal view returns (bytes32) {
        if (block.chainid == _CACHED_CHAIN_ID) {
            return _CACHED_DOMAIN_SEPARATOR;
        } else {
            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
        }
    }

    function _buildDomainSeparator(
        bytes32 typeHash,
        bytes32 nameHash,
        bytes32 versionHash
    ) private view returns (bytes32) {
        return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
    }

    /**
     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
     * function returns the hash of the fully encoded EIP712 message for this domain.
     *
     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
     *
     * ```solidity
     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
     *     keccak256("Mail(address to,string contents)"),
     *     mailTo,
     *     keccak256(bytes(mailContents))
     * )));
     * address signer = ECDSA.recover(digest, signature);
     * ```
     */
    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
        return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
    }
}

/**
 * @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);
    }
}

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

/**
 * @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;
    }
}

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}

/**
 * @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);
}

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

/**
 * @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;
}

/**
 * @dev _Available since v3.1._
 */
interface IERC1155Receiver is IERC165 {
    /**
        @dev Handles the receipt of a single ERC1155 token type. This function is
        called at the end of a `safeTransferFrom` after the balance has been updated.
        To accept the transfer, this must return
        `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
        (i.e. 0xf23a6e61, or its own function selector).
        @param operator The address which initiated the transfer (i.e. msg.sender)
        @param from The address which previously owned the token
        @param id The ID of the token being transferred
        @param value The amount of tokens being transferred
        @param data Additional data with no specified format
        @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
    */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external returns (bytes4);

    /**
        @dev Handles the receipt of a multiple ERC1155 token types. This function
        is called at the end of a `safeBatchTransferFrom` after the balances have
        been updated. To accept the transfer(s), this must return
        `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
        (i.e. 0xbc197c81, or its own function selector).
        @param operator The address which initiated the batch transfer (i.e. msg.sender)
        @param from The address which previously owned the token
        @param ids An array containing ids of each token being transferred (order and length must match values array)
        @param values An array containing amounts of each token being transferred (order and length must match ids array)
        @param data Additional data with no specified format
        @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
    */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external returns (bytes4);
}

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     *
     * _Available since v4.1._
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role, _msgSender());
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view override returns (bool) {
        return _roles[role].members[account];
    }

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     */
    function _checkRole(bytes32 role, address account) internal view {
        if (!hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "AccessControl: account ",
                        Strings.toHexString(uint160(account), 20),
                        " is missing role ",
                        Strings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    function _grantRole(bytes32 role, address account) private {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    function _revokeRole(bytes32 role, address account) private {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

/**
 * @dev Interface of the optional ERC1155MetadataExtension interface, as defined
 * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].
 *
 * _Available since v3.1._
 */
interface IERC1155MetadataURI is IERC1155 {
    /**
     * @dev Returns the URI for token type `id`.
     *
     * If the `\{id\}` substring is present in the URI, it must be replaced by
     * clients with the actual token type ID.
     */
    function uri(uint256 id) external view returns (string memory);
}

/**
 * @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
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 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);
            }
        }
    }
}

/**
 * @dev Implementation of the basic standard multi-token.
 * See https://eips.ethereum.org/EIPS/eip-1155
 * Originally based on code by Enjin: https://github.com/enjin/erc-1155
 *
 * _Available since v3.1._
 */
contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
    using Address for address;

    // Mapping from token ID to account balances
    mapping(uint256 => mapping(address => uint256)) private _balances;

    // Mapping from account to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json
    string private _uri;

    /**
     * @dev See {_setURI}.
     */
    constructor(string memory uri_) {
        _setURI(uri_);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC1155).interfaceId ||
            interfaceId == type(IERC1155MetadataURI).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC1155MetadataURI-uri}.
     *
     * This implementation returns the same URI for *all* token types. It relies
     * on the token type ID substitution mechanism
     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
     *
     * Clients calling this function must replace the `\{id\}` substring with the
     * actual token type ID.
     */
    function uri(uint256) public view virtual override returns (string memory) {
        return _uri;
    }

    /**
     * @dev See {IERC1155-balanceOf}.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {
        require(account != address(0), "ERC1155: balance query for the zero address");
        return _balances[id][account];
    }

    /**
     * @dev See {IERC1155-balanceOfBatch}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(address[] memory accounts, uint256[] memory ids)
        public
        view
        virtual
        override
        returns (uint256[] memory)
    {
        require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch");

        uint256[] memory batchBalances = new uint256[](accounts.length);

        for (uint256 i = 0; i < accounts.length; ++i) {
            batchBalances[i] = balanceOf(accounts[i], ids[i]);
        }

        return batchBalances;
    }

    /**
     * @dev See {IERC1155-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        require(_msgSender() != operator, "ERC1155: setting approval status for self");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC1155-isApprovedForAll}.
     */
    function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[account][operator];
    }

    /**
     * @dev See {IERC1155-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) public virtual override {
        require(
            from == _msgSender() || isApprovedForAll(from, _msgSender()),
            "ERC1155: caller is not owner nor approved"
        );
        _safeTransferFrom(from, to, id, amount, data);
    }

    /**
     * @dev See {IERC1155-safeBatchTransferFrom}.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) public virtual override {
        require(
            from == _msgSender() || isApprovedForAll(from, _msgSender()),
            "ERC1155: transfer caller is not owner nor approved"
        );
        _safeBatchTransferFrom(from, to, ids, amounts, data);
    }

    /**
     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `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 memory data
    ) internal virtual {
        require(to != address(0), "ERC1155: transfer to the zero address");

        address operator = _msgSender();

        uint256 fromBalance = _balances[id][from];
        require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
        unchecked {
            _balances[id][from] = fromBalance - amount;
        }
        _balances[id][to] += amount;

        emit TransferSingle(operator, from, to, id, amount);

        _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
    }

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - 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[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual {
        require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
        require(to != address(0), "ERC1155: transfer to the zero address");

        address operator = _msgSender();

        for (uint256 i = 0; i < ids.length; ++i) {
            uint256 id = ids[i];
            uint256 amount = amounts[i];

            uint256 fromBalance = _balances[id][from];
            require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
            unchecked {
                _balances[id][from] = fromBalance - amount;
            }
            _balances[id][to] += amount;
        }

        emit TransferBatch(operator, from, to, ids, amounts);

        _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);
    }

    /**
     * @dev Sets a new URI for all token types, by relying on the token type ID
     * substitution mechanism
     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
     *
     * By this mechanism, any occurrence of the `\{id\}` substring in either the
     * URI or any of the amounts in the JSON file at said URI will be replaced by
     * clients with the token type ID.
     *
     * For example, the `https://token-cdn-domain/\{id\}.json` URI would be
     * interpreted by clients as
     * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`
     * for token type ID 0x4cce0.
     *
     * See {uri}.
     *
     * Because these URIs cannot be meaningfully represented by the {URI} event,
     * this function emits no events.
     */
    function _setURI(string memory newuri) internal virtual {
        _uri = newuri;
    }

    /**
     * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - If `account` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function _mint(
        address account,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) internal virtual {
        require(account != address(0), "ERC1155: mint to the zero address");

        address operator = _msgSender();

        _balances[id][account] += amount;
        emit TransferSingle(operator, address(0), account, id, amount);

        _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);
    }

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.
     *
     * 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 _mintBatch(
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual {
        require(to != address(0), "ERC1155: mint to the zero address");
        require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");

        address operator = _msgSender();

        for (uint256 i = 0; i < ids.length; i++) {
            _balances[ids[i]][to] += amounts[i];
        }

        emit TransferBatch(operator, address(0), to, ids, amounts);

        _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
    }

    function _doSafeTransferAcceptanceCheck(
        address operator,
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) private {
        if (to.isContract()) {
            try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {
                if (response != IERC1155Receiver.onERC1155Received.selector) {
                    revert("ERC1155: ERC1155Receiver rejected tokens");
                }
            } catch Error(string memory reason) {
                revert(reason);
            } catch {
                revert("ERC1155: transfer to non ERC1155Receiver implementer");
            }
        }
    }

    function _doSafeBatchTransferAcceptanceCheck(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) private {
        if (to.isContract()) {
            try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (
                bytes4 response
            ) {
                if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {
                    revert("ERC1155: ERC1155Receiver rejected tokens");
                }
            } catch Error(string memory reason) {
                revert(reason);
            } catch {
                revert("ERC1155: transfer to non ERC1155Receiver implementer");
            }
        }
    }

    function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {
        uint256[] memory array = new uint256[](1);
        array[0] = element;

        return array;
    }
}

/**
 * @dev Extension of ERC1155 that adds tracking of total supply per id.
 *
 * Useful for scenarios where Fungible and Non-fungible tokens have to be
 * clearly identified. Note: While a totalSupply of 1 might mean the
 * corresponding is an NFT, there is no guarantees that no other token with the
 * same id are not going to be minted.
 */
abstract contract ERC1155Supply is ERC1155 {
    mapping(uint256 => uint256) private _totalSupply;

    /**
     * @dev Total amount of tokens in with a given id.
     */
    function totalSupply(uint256 id) public view virtual returns (uint256) {
        return _totalSupply[id];
    }

    /**
     * @dev Indicates weither any token exist with a given id, or not.
     */
    function exists(uint256 id) public view virtual returns (bool) {
        return ERC1155Supply.totalSupply(id) > 0;
    }

    /**
     * @dev See {ERC1155-_mint}.
     */
    function _mint(
        address account,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) internal virtual override {
        super._mint(account, id, amount, data);
        _totalSupply[id] += amount;
    }

    /**
     * @dev See {ERC1155-_mintBatch}.
     */
    function _mintBatch(
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual override {
        super._mintBatch(to, ids, amounts, data);
        for (uint256 i = 0; i < ids.length; ++i) {
            _totalSupply[ids[i]] += amounts[i];
        }
    }

}

/**
 * @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() {
        _setOwner(_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 {
        _setOwner(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");
        _setOwner(newOwner);
    }

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

/**
 * @dev {ERC1155} token, including:
 *
 *  - a minter role that allows for token minting (creation)
 *
 * This contract uses {AccessControl} to lock permissioned functions using the
 * different roles - head to its documentation for details.
 *
 * The account that deploys the contract will be granted the minter role, as well
 * as the default admin role, which will let it grant minter role to other accounts.
 */
contract ERC1155YuzuInternal is Ownable, AccessControl, ERC1155Supply {
    
    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    uint256 internal _tokenIdCounter;
    bool public anyoneCanMint;

    /**
     * @dev Grants `DEFAULT_ADMIN_ROLE`, and `MINTER_ROLE` to the account that
     * deploys the contract. And initializes the contract by setting a `name` 
     * and a `symbol` to the token collection.
     */
    constructor(address owner, string memory uri, string memory name_, string memory symbol_, bool anyoneCanMint_) Ownable() ERC1155(uri) {
        _setupRole(DEFAULT_ADMIN_ROLE, owner);
        _setupRole(MINTER_ROLE, owner);
        transferOwnership(owner);
        _name = name_;
        _symbol = symbol_;
        anyoneCanMint = anyoneCanMint_;
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() external view virtual returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() external view virtual returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Find next available tokenId
     */
    function findNextTokenId() internal {
        do {
          _tokenIdCounter++;
        } while(exists(_tokenIdCounter));
    }

    /**
     * @dev Creates `amount` new tokens for `to`, using the next available `id`.
     *
     * - the caller must have the `MINTER_ROLE`.
     */
    function autoMint(address to, uint256 amount) public onlyMinter returns (uint256) {
        findNextTokenId();
        _mint(to, _tokenIdCounter, amount, "0x");
        return _tokenIdCounter;
    }

    /**
     * @dev Creates `amounts` new tokens for `to`, using the next available `ids`.
     *
     * - the caller must have the `MINTER_ROLE`.
     */
    function autoMintBatch(address to, uint256[] memory amounts) public onlyMinter {
        require(to != address(0), "ERC1155: mint to the zero address");
        for (uint256 i = 0; i < amounts.length; i++) {
            autoMint(to, amounts[i]);
        }
    }

    /**
     * @dev Creates `amount` new tokens for `to`, of token type `id`.
     *
     * See {ERC1155-_mint}.
     *
     * Requirements:
     *
     * - the caller must have the `MINTER_ROLE`.
     */
    function mint(
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) public virtual onlyMinter {
        _mint(to, id, amount, data);
    }

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] variant of {mint}.
     */
    function mintBatch(
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) public virtual onlyMinter {
        _mintBatch(to, ids, amounts, data);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(AccessControl, ERC1155)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }

    function addMinter(address account) external onlyMinter {
        grantRole(MINTER_ROLE, account);
    }

    function isMinter(address account) public view returns (bool) {
        return hasRole(MINTER_ROLE, account);
    }

    function canIMint() public view returns (bool) {
        return anyoneCanMint || isMinter(msg.sender);
    }

    /**
     * Open modifier to anyone can mint possibility
     */
    modifier onlyMinter() {
        string memory mensaje;
        require(
            canIMint(),
            "ERC1155Yuzu: must have minter role to mint"
        );
        _;
    }

}

/**
 * @title ERC1155Ikasumi
 * ERC-721 Marketplace with tokens and royalties support
 */
contract ERC1155Marketplace is ERC1155YuzuInternal, ReentrancyGuard {

    using Address for address;

    // admin address, the owner of the marketplace
    address public admin;

    // IERC20 token to be used for payments
    IERC20 public paymentToken;

    // commission rate is a value from 0 to 100
    uint256 public commissionRate;

    // royalties commission rate is a value from 0 to 100
    uint256 public royaltiesCommissionRate;

    // nft item creators list, used to pay royalties
    mapping(uint256 => address) public creators;
    
    // a sale object
    struct Sale {
        uint256 qty;    // qty for sale
        uint256 price;  // price 
        address user;   // seller
        address wallet; // seller wallet
    }

    // opened sales by tokenIds
    mapping(uint256 => Sale[]) public openSales;

    // length of the array
    mapping(uint256 => uint256) public openSalesLength;

    // a buy offer object
    struct Offer {
        uint256 qty;    // qty for buying
        uint256 price;  // buy price 
        address user;   // buyer
    }

    // opened offers by tokenIds
    mapping(uint256 => Offer[]) public openOffers;

    // length of the array
    mapping(uint256 => uint256) public openOffersLength;

    event Bid(        uint256 indexed tokenId, address indexed from,   uint256 qty,         uint256 price);
    event Sell(       uint256 indexed tokenId, address indexed to,     uint256 qty,         uint256 price);
    event Commission( uint256 indexed tokenId, address indexed from,   address indexed to,  uint256 value);
    event Royalty(    uint256 indexed tokenId, address indexed from,   address indexed to,  uint256 value);
    event Buy(        uint256 indexed tokenId, address indexed from,   address indexed to,  uint256 value);

    event CancelSale(uint256 indexed tokenId, uint256 index);
    event CancelBid(uint256 indexed tokenId, uint256 index);

    constructor(
        IERC20 _paymentToken, address _owner, address _admin, uint256 _commissionRate, uint256 _royaltiesCommissionRate, 
        string memory name, string memory symbol, bool _anyoneCanMint, string memory uri) 
        ERC1155YuzuInternal(_owner, uri, name, symbol, _anyoneCanMint)
    {
        require(_commissionRate + _royaltiesCommissionRate < 100, "Ikasumi: total commissions should be lower than 100");
        admin = _admin;
        commissionRate = _commissionRate;
        royaltiesCommissionRate = _royaltiesCommissionRate;
        paymentToken = _paymentToken;
    }

    /**
     * Any user can sell X items at Y price each, valid ownership and qty of the sell will be handled by the UI
     * All selling options are shown as “Listings” in the UI
     * Any user can buy W items at Y price, of one listing, they cannot combine two listings in one transaction, given that W>0 and W<=Y
     * Restrictions:
     *    Limit the sell to owned items, the user cannot sell items do not have
     */
    
    function sell(uint256 tokenId, uint256 qty, uint256 price, address wallet) external {

        // Limit the sell to owned items, the user cannot sell items do not have
        require(balanceOf(_msgSender(), tokenId) >= qty, "Ikasumi: you do not have enough tokens to sell");

        // set approval for all items of the user is not set already
        if (!isApprovedForAll(_msgSender(), address(this))) {
            setApprovalForAll(address(this), true);
        }

        // add the selling option to openSales
        Sale memory sale = Sale(qty, price, _msgSender(), wallet);

        // An owner can add only one selling listing for one item at a time, new listings for one item will replace the old ones

        openSales[tokenId].push(sale);
        openSalesLength[tokenId] = openSales[tokenId].length;
        emit Sell(tokenId, _msgSender(), qty, price);

    }

    /**
     * Buy an NTF item, specifying qty to buy and index offer
     * Funds are transferred from the caller user directly, previous approval required
     */
    
    function buy(uint256 tokenId, uint256 index, uint256 qty) external nonReentrant {

        // validate user
        require(openSales[tokenId][index].user != _msgSender() , "Ikasumi: the user cannot buy his own offer");

        // transfer ownership
        // we need to call a transferFrom from this contract, which is the one with permission to sell the NFT
        callOptionalReturn(this, abi.encodeWithSelector(this.safeTransferFrom.selector, openSales[tokenId][index].user, _msgSender(), tokenId, qty, "0x"));

        /**
         * distribute funds between owner, creator and admin
         * This function will transfer the funds from the buyer, which must have previously approve the funds to the contract, to the beneficiaries of the sale
         * The "true" parameter at the end means: do a transferFrom
         */ 
        distributeFunds(qty * openSales[tokenId][index].price, _msgSender(), openSales[tokenId][index].wallet, tokenId, true);

        // substract items sold
        openSales[tokenId][index].qty -= qty;

        // remove the offer and reorder the array
        if (openSales[tokenId][index].qty == 0) {
            openSales[tokenId][index] = openSales[tokenId][openSales[tokenId].length-1];
            openSales[tokenId].pop();
            openSalesLength[tokenId] = openSales[tokenId].length;
        }

    }

    // cancel the sale
    function cancelSale(uint256 tokenId, uint256 index) external {

        // Only the original bidder can cancel his bids
        require(openSales[tokenId][index].user == _msgSender(), "Ikasumi: only the original seller can cancel his sales");

        // remove the sale
        openSales[tokenId][index] = openSales[tokenId][openSales[tokenId].length-1];
        openSales[tokenId].pop();
        openSalesLength[tokenId] = openSales[tokenId].length;

        emit CancelSale(tokenId, index);

    }

    /**
     * Any user can make an offer of X items at Y price each
     * Funds of the offer are stored on the contract
     * All offers are shown as “Offers” in the UI
     * Restrictions
     *    A buyer cannot add an offer bigger than the total supply
     */
    
    function bid(uint256 tokenId, uint256 qty, uint256 price) external nonReentrant {

        require(qty>0, "Iksasumi: qty has to be positive");
        require(price>0, "Iksasumi: price has to be positive");
        require(qty <= totalSupply(tokenId), "Iksasumi: not enough items for sale");
        
        // transfer qty * price tokens to the contract
        uint256 total = qty * price;
        require(paymentToken.transferFrom(_msgSender(), address(this), total), "Transfer failed.");

        // record the offer
        Offer memory theBid = Offer(qty, price, _msgSender());

        openOffers[tokenId].push(theBid);
        openOffersLength[tokenId] = openOffers[tokenId].length;
        emit Bid(tokenId, _msgSender(), qty, price);

    }

    // cancel the offer and return funds
    function cancelBid(uint256 tokenId, uint256 index) external nonReentrant {

        // Only the original bidder can cancel his bids
        require(openOffers[tokenId][index].user == _msgSender(), "Ikasumi: only the original bidder can cancel his bids");

        // save the total
        uint256 total = openOffers[tokenId][index].qty * openOffers[tokenId][index].price;

        // remove the bid
        openOffers[tokenId][index] = openOffers[tokenId][openOffers[tokenId].length-1];
        openOffers[tokenId].pop();
        openOffersLength[tokenId] = openOffers[tokenId].length;

        // return the funds
        require(paymentToken.transfer(_msgSender(), total), "Transfer failed.");

        emit CancelBid(tokenId, index);

    }

    // owner accepts the bid and distribute the funds
    function acceptBid(uint256 tokenId, uint256 index, uint256 qty) external nonReentrant {

        // validate user
        require(openOffers[tokenId][index].user != _msgSender() , "Ikasumi: the user cannot accept his own bid");

        // set approval for all items of the user is not set already
        if (!isApprovedForAll(_msgSender(), address(this))) {
            setApprovalForAll(address(this), true);
        }

        // transfer item to bidder
        // we need to call a transferFrom from this contract, which is the one with permission to sell the NFT
        callOptionalReturn(this, abi.encodeWithSelector(this.safeTransferFrom.selector, _msgSender(), openOffers[tokenId][index].user, tokenId, qty, "0x"));

        /**
         * distribute funds between owner, creator and admin
         * This function will transfer the funds from the contract, which must have previously sent to the contract, to the beneficiaries of the sale
         * The "false" parameter at the end means: do a simple transfer
         */ 
        distributeFunds(qty * openOffers[tokenId][index].price, openOffers[tokenId][index].user, _msgSender(), tokenId, false);

        // substract items sold
        openOffers[tokenId][index].qty -= qty;

        // remove the offer and reorder the array
        if (openOffers[tokenId][index].qty == 0) {
            openOffers[tokenId][index] = openOffers[tokenId][openOffers[tokenId].length-1];
            openOffers[tokenId].pop();
            openOffersLength[tokenId] = openOffers[tokenId].length;
        }
    }

    /**
     * do the funds distribution between owner, creator and admin
     * @param totalPrice the total value to distribute
     * @param from if useTransferFrom is true then the "from" is the origin of the funds, if false, then the "from" is only used for logs purposes
     * @param to is the owner of the token on sale / bid
     * @param tokenId is the token being sold
     * @param useTransferFrom if true the transfer will be made from to, if not, a simple transfer will be done from the contract to the beneficiaries
     */

    function distributeFunds(uint256 totalPrice, address from, address to, uint256 tokenId, bool useTransferFrom) internal {

        // calculate amounts
        uint256 amount4admin = totalPrice * commissionRate / 100;
        uint256 amount4creator = totalPrice * royaltiesCommissionRate / 100;
        uint256 amount4owner = totalPrice - amount4admin - amount4creator;

        // to owner
        if (useTransferFrom) {
            require(paymentToken.transferFrom(from, to, amount4owner), "Transfer failed.");
        } else {
            require(paymentToken.transfer(to, amount4owner), "Transfer failed.");
        }
        emit Buy(tokenId, from, to, amount4owner);

        // to creator
        if (amount4creator>0) {
            if (useTransferFrom) {
                require(paymentToken.transferFrom(from, creators[tokenId], amount4creator), "Transfer failed.");
            } else {
                require(paymentToken.transfer(creators[tokenId], amount4creator), "Transfer failed.");
            }
            emit Royalty(tokenId, from, creators[tokenId], amount4creator);
        }

        // to admin
        if (amount4admin>0) {
            if (useTransferFrom) {
                require(paymentToken.transferFrom(from, admin, amount4admin), "Transfer failed.");
            } else {
                require(paymentToken.transfer(admin, amount4admin), "Transfer failed.");
            }
            emit Commission(tokenId, from, admin, amount4admin);
        }

    }

    /// Overrides minting function to keep track of item creators

    function _mint(address to, uint256 tokenId, uint256 amount, bytes memory data) override internal {
        creators[tokenId] = _msgSender();
        super._mint(to, tokenId, amount, data);
    }

    function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) override internal {
        super._mintBatch(to, ids, amounts, data);
        for (uint256 i = 0; i < ids.length; ++i) {
            creators[ids[i]] = _msgSender();
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function callOptionalReturn(IERC1155 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves.

        // A Solidity high level call has three parts:
        //  1. The target address is checked to verify it contains contract code
        //  2. The call itself is made, and success asserted
        //  3. The return value is decoded, which in turn checks the size of the returned data.
        // solhint-disable-next-line max-line-length
        require(address(token).isContract(), "Ikasumi: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = address(token).call(data);
        require(success, "Ikasumi: low-level call failed");

        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "Ikasumi: ERC20 operation did not succeed");
        }
    }

    // update contract fields
    function updateAdmin(address _admin, uint256 _commissionRate, uint256 _royaltiesCommissionRate, bool _anyoneCanMint, IERC20 _paymentToken) external onlyOwner() {
        require(_commissionRate + _royaltiesCommissionRate < 100, "Ikasumi: total commissions should be lower than 100");
        admin = _admin;
        commissionRate = _commissionRate;
        royaltiesCommissionRate = _royaltiesCommissionRate;
        anyoneCanMint = _anyoneCanMint;
        paymentToken = _paymentToken;
    }
    
}

/**
 * Marketplace with Lazy Minting feature
 */
contract ERC1155Ikasumi is ERC1155Marketplace, EIP712 {
    string private constant SIGNING_DOMAIN = "ERC1155Ikasumi-Voucher";
    string private constant SIGNATURE_VERSION = "1";

    constructor(IERC20 _paymentToken, address _owner, address _admin, uint256 _commissionRate, uint256 _royaltiesCommissionRate, 
        string memory name, string memory symbol, bool _anyoneCanMint, string memory uri)
        ERC1155Marketplace(_paymentToken, _owner, _admin, _commissionRate, _royaltiesCommissionRate, name, symbol, _anyoneCanMint, uri)
        EIP712(SIGNING_DOMAIN, SIGNATURE_VERSION) {}

    // minted qty for each voucher ID
    mapping(uint256 => uint256) public vouchersMintedQty;

    // minted NFT ID for each voucher ID
    mapping(uint256 => uint256) public vouchersNFTIds;

    event LazyMint(uint256 indexed tokenId, address indexed from, address indexed to, uint256 value);

    /// @notice Redeems an NFTVoucher for an actual NFT, creating it in the process.
    function redeem(
        uint256 nftId, uint256 id, uint256 nftPostId, uint256 qty, uint256 price, uint256 collectionId, uint256 chainId, address author, uint256 salt, bytes memory signature, uint256 qtyToMint
    ) external nonReentrant {

        require(chainId == getChainId(), "Ikasumi: Wrong chain");
        require(vouchersMintedQty[id] + qtyToMint <= qty, "Ikasumi: the qty exceeds the amount available for minting");
        require(nftId == 0 || exists(nftId), "Ikasumi: Wrong NFT ID");

        // make sure signature is valid and get the address of the signer
        verify(id, nftPostId, qty, price, collectionId, chainId, author, salt, address(this), signature, owner());

        // allow to mint less qty of the amounts in voucher, until all qtys are minted
        // first time minting? find the next available tokenId or use the existing NFT Id if it was passed to the function
        if (vouchersNFTIds[id]==0) { 
            if (nftId>0) {
                vouchersNFTIds[id] = nftId;
            } else {
                findNextTokenId();
                vouchersNFTIds[id] = _tokenIdCounter;
            }
        }

        // mint the items
        _mint(_msgSender(), vouchersNFTIds[id], qtyToMint, '0x');

        // manually set the creator / author for the tokenId just minted
        // the author is set by the contract owner in the signed message, and this is meant to receive royalties
        creators[vouchersNFTIds[id]] = author;

        // distribute payments
        distributeFunds(qtyToMint * price, _msgSender(), owner(), vouchersNFTIds[id], true);

        // Inform the Lazy Mint
        emit LazyMint(vouchersNFTIds[id], _msgSender(), owner(), qtyToMint * price);

        // keep track of minted qties
        vouchersMintedQty[id] += qtyToMint;

    }

    function domainSeparator() external view returns (bytes32) {
        return _domainSeparatorV4();
    }

    function verify(
        uint256 id,
        uint256 nftPostId,
        uint256 qty,
        uint256 price,
        uint256 collectionId,
        uint256 chainId,
        address author,
        uint256 salt,
        address thisContract,
        bytes memory signature,
        address signer
    ) internal view {
        bytes32 digest = _hashTypedDataV4(
            keccak256(
                abi.encode(
                    keccak256("NFTVoucher(uint256 id,uint256 nftPostId,uint256 qty,uint256 price,uint256 collectionId,uint256 chainId,address author,uint256 salt,address thisContract)"), 
                    id, nftPostId, qty, price, collectionId, chainId, author, salt, thisContract
                )
            )
        );
        address recoveredSigner = ECDSA.recover(digest, signature);
        require(recoveredSigner == signer, "Ikasumi: wrong signature");
    }

    function getChainId() public view returns (uint256) {
        return block.chainid;
    }

}

Settings
{
  "evmVersion": "istanbul",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs",
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": [],
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract IERC20","name":"_paymentToken","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_admin","type":"address"},{"internalType":"uint256","name":"_commissionRate","type":"uint256"},{"internalType":"uint256","name":"_royaltiesCommissionRate","type":"uint256"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"bool","name":"_anyoneCanMint","type":"bool"},{"internalType":"string","name":"uri","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"qty","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"Bid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Buy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"CancelBid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"CancelSale","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Commission","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"LazyMint","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":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Royalty","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"qty","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"Sell","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":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"qty","type":"uint256"}],"name":"acceptBid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"anyoneCanMint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"autoMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"autoMintBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"qty","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"bid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"qty","type":"uint256"}],"name":"buy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"canIMint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"cancelBid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"cancelSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"commissionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"creators","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"domainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"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":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"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":"mintBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"openOffers","outputs":[{"internalType":"uint256","name":"qty","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"openOffersLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"openSales","outputs":[{"internalType":"uint256","name":"qty","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"wallet","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"openSalesLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paymentToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftId","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"nftPostId","type":"uint256"},{"internalType":"uint256","name":"qty","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"collectionId","type":"uint256"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"author","type":"address"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"qtyToMint","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"royaltiesCommissionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"qty","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"wallet","type":"address"}],"name":"sell","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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"uint256","name":"_commissionRate","type":"uint256"},{"internalType":"uint256","name":"_royaltiesCommissionRate","type":"uint256"},{"internalType":"bool","name":"_anyoneCanMint","type":"bool"},{"internalType":"contract IERC20","name":"_paymentToken","type":"address"}],"name":"updateAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"vouchersMintedQty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"vouchersNFTIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

6101206040523480156200001257600080fd5b50604051620056e4380380620056e48339810160408190526200003591620005fc565b6040518060400160405280601681526020017f45524331313535496b6173756d692d566f756368657200000000000000000000815250604051806040016040528060018152602001603160f81b8152508a8a8a8a8a8a8a8a8a878185858583620000ae620000a8620002a360201b60201c565b620002a7565b620000b981620002f7565b50620000c760008662000310565b620000f37f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a68662000310565b620000fe856200031c565b82516200011390600690602086019062000475565b5081516200012990600790602085019062000475565b506009805460ff191691151591909117905550506001600a555060649050620001538688620006ea565b10620001cc5760405162461bcd60e51b815260206004820152603360248201527f496b6173756d693a20746f74616c20636f6d6d697373696f6e732073686f756c60448201527f64206265206c6f776572207468616e203130300000000000000000000000000060648201526084015b60405180910390fd5b5050600b80546001600160a01b039687166001600160a01b031991821617909155600d949094555050600e55600c80549490921693169290921790915550815160209283012081519183019190912060c082815260e08290524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818901819052818301979097526060810195909552608080860193909352308583015280518086039092018252939092019092528051930192909220909152610100525062000762975050505050505050565b3390565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516200030c90600490602084019062000475565b5050565b6200030c8282620003ed565b6000546001600160a01b03163314620003785760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620001c3565b6001600160a01b038116620003df5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620001c3565b620003ea81620002a7565b50565b60008281526001602090815260408083206001600160a01b038516845290915290205460ff166200030c5760008281526001602081815260408084206001600160a01b0386168086529252808420805460ff19169093179092559051339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b82805462000483906200070f565b90600052602060002090601f016020900481019282620004a75760008555620004f2565b82601f10620004c257805160ff1916838001178555620004f2565b82800160010185558215620004f2579182015b82811115620004f2578251825591602001919060010190620004d5565b506200050092915062000504565b5090565b5b8082111562000500576000815560010162000505565b80516001600160a01b03811681146200053357600080fd5b919050565b805180151581146200053357600080fd5b600082601f8301126200055a578081fd5b81516001600160401b03808211156200057757620005776200074c565b604051601f8301601f19908116603f01168101908282118183101715620005a257620005a26200074c565b81604052838152602092508683858801011115620005be578485fd5b8491505b83821015620005e15785820183015181830184015290820190620005c2565b83821115620005f257848385830101525b9695505050505050565b60008060008060008060008060006101208a8c0312156200061b578485fd5b620006268a6200051b565b98506200063660208b016200051b565b97506200064660408b016200051b565b60608b015160808c015160a08d015192995090975095506001600160401b038082111562000672578586fd5b620006808d838e0162000549565b955060c08c015191508082111562000696578485fd5b620006a48d838e0162000549565b9450620006b460e08d0162000538565b93506101008c0151915080821115620006cb578283fd5b50620006da8c828d0162000549565b9150509295985092959850929598565b600082198211156200070a57634e487b7160e01b81526011600452602481fd5b500190565b600181811c908216806200072457607f821691505b602082108114156200074657634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b60805160a05160c05160e05161010051614f3d620007a76000396000613581015260006135d0015260006135ab0152600061352f015260006135580152614f3d6000f3fe608060405234801561001057600080fd5b50600436106102f05760003560e01c8063801496091161019d578063ce15d87c116100e9578063e985e9c5116100a2578063f2fde38b1161007c578063f2fde38b14610770578063f698da2514610783578063f851a4401461078b578063fa184c491461079e57600080fd5b8063e985e9c514610719578063ee1b59e414610755578063f242432a1461075d57600080fd5b8063ce15d87c1461066c578063d13895121461068c578063d5391393146106ac578063d547741f146106d3578063dc234f5a146106e6578063e22b862c146106f957600080fd5b8063a217fddf11610156578063aa271e1a11610130578063aa271e1a14610603578063b13fbe9614610616578063bd85b03914610623578063cd53d08e1461064357600080fd5b8063a217fddf146105d5578063a22cb465146105dd578063a2d0d029146105f057600080fd5b806380149609146105415780638da5cb5b1461058357806391d148541461059457806395d89b41146105a7578063983b2d56146105af5780639fa6b40c146105c257600080fd5b806336568abe1161025c5780634f558e7911610215578063715018a6116101ef578063715018a6146104dc578063731133e9146104e45780637447298f146104f7578063745e96d71461052e57600080fd5b80634f558e791461049157806356bee561146104b35780635ea1d6f8146104d357600080fd5b806336568abe1461041c578063373f68d11461042f57806340993b26146104385780634b3936051461044b5780634c22ce0b1461045e5780634e1273f41461047157600080fd5b8063248a9ca3116102ae578063248a9ca31461038e5780632ac9bf09146103b25780632eb2c2d6146103c55780632f2ff15d146103d85780633013ce29146103eb5780633408e4701461041657600080fd5b8062fdd58e146102f557806301ffc9a71461031b57806306fdde031461033e57806309d0ffa8146103535780630e89341c146103685780631f7fdffa1461037b575b600080fd5b6103086103033660046144b5565b6107b1565b6040519081526020015b60405180910390f35b61032e6103293660046146ac565b61084a565b6040519015158152602001610312565b61034661085b565b6040516103129190614a59565b6103666103613660046146e4565b6108ed565b005b610346610376366004614670565b610b40565b6103666103893660046143f2565b610bd4565b61030861039c366004614670565b6000908152600160208190526040909120015490565b6103666103c0366004614705565b610c0d565b6103666103d3366004614296565b610edd565b6103666103e6366004614688565b610f6d565b600c546103fe906001600160a01b031681565b6040516001600160a01b039091168152602001610312565b46610308565b61036661042a366004614688565b610f99565b610308600e5481565b610366610446366004614705565b611017565b6103666104593660046146e4565b61143d565b61036661046c3660046143a5565b6117dd565b61048461047f366004614592565b61187f565b6040516103129190614a18565b61032e61049f366004614670565b600090815260056020526040902054151590565b6103086104c1366004614670565b60136020526000908152604090205481565b610308600d5481565b6103666119e0565b6103666104f236600461453e565b611a16565b61050a6105053660046146e4565b611a48565b6040805193845260208401929092526001600160a01b031690820152606001610312565b61030861053c3660046144b5565b611a93565b61055461054f3660046146e4565b611af6565b6040805194855260208501939093526001600160a01b0391821692840192909252166060820152608001610312565b6000546001600160a01b03166103fe565b61032e6105a2366004614688565b611b49565b610346611b74565b6103666105bd366004614242565b611b83565b6103666105d0366004614770565b611bd3565b610308600081565b6103666105eb366004614488565b611ecb565b6103666105fe366004614705565b611fa2565b61032e610611366004614242565b6123a5565b60095461032e9060ff1681565b610308610631366004614670565b60009081526005602052604090205490565b6103fe610651366004614670565b600f602052600090815260409020546001600160a01b031681565b61030861067a366004614670565b60156020526000908152604090205481565b61030861069a366004614670565b60116020526000908152604090205481565b6103087f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b6103666106e1366004614688565b6123d1565b6103666106f4366004614730565b6123f8565b610308610707366004614670565b60146020526000908152604090205481565b61032e61072736600461425e565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205460ff1690565b61032e612580565b61036661076b36600461433f565b61259d565b61036661077e366004614242565b612624565b6103086126bf565b600b546103fe906001600160a01b031681565b6103666107ac3660046144e0565b6126c9565b60006001600160a01b0383166108225760405162461bcd60e51b815260206004820152602b60248201527f455243313135353a2062616c616e636520717565727920666f7220746865207a60448201526a65726f206164647265737360a81b60648201526084015b60405180910390fd5b5060009081526002602090815260408083206001600160a01b03949094168352929052205490565b6000610855826127b5565b92915050565b60606006805461086a90614d80565b80601f016020809104026020016040519081016040528092919081815260200182805461089690614d80565b80156108e35780601f106108b8576101008083540402835291602001916108e3565b820191906000526020600020905b8154815290600101906020018083116108c657829003601f168201915b5050505050905090565b600082815260106020526040902080543391908390811061091e57634e487b7160e01b600052603260045260246000fd5b60009182526020909120600260049092020101546001600160a01b0316146109a75760405162461bcd60e51b815260206004820152603660248201527f496b6173756d693a206f6e6c7920746865206f726967696e616c2073656c6c65604482015275722063616e2063616e63656c206869732073616c657360501b6064820152608401610819565b600082815260106020526040902080546109c390600190614d26565b815481106109e157634e487b7160e01b600052603260045260246000fd5b9060005260206000209060040201601060008481526020019081526020016000208281548110610a2157634e487b7160e01b600052603260045260246000fd5b6000918252602080832084546004909302019182556001808501549083015560028085015490830180546001600160a01b03199081166001600160a01b03938416179091556003958601549590930180549093169416939093179055838152601090915260409020805480610aa657634e487b7160e01b600052603160045260246000fd5b60008281526020808220600460001990940193840201828155600181018390556002810180546001600160a01b03199081169091556003909101805490911690559190925583825260108152604080832054601190925291829020555182907f62f362ec9f7b9b102a4244ce20b4b58f82ab3e1a2c681c73637a4a7cf91cb78590610b349084815260200190565b60405180910390a25050565b606060048054610b4f90614d80565b80601f0160208091040260200160405190810160405280929190818152602001828054610b7b90614d80565b8015610bc85780601f10610b9d57610100808354040283529160200191610bc8565b820191906000526020600020905b815481529060010190602001808311610bab57829003601f168201915b50505050509050919050565b6060610bde612580565b610bfa5760405162461bcd60e51b815260040161081990614bea565b610c06858585856127f5565b5050505050565b6002600a541415610c305760405162461bcd60e51b815260040161081990614c75565b6002600a5581610c825760405162461bcd60e51b815260206004820181905260248201527f496b736173756d693a207174792068617320746f20626520706f7369746976656044820152606401610819565b60008111610cdd5760405162461bcd60e51b815260206004820152602260248201527f496b736173756d693a2070726963652068617320746f20626520706f73697469604482015261766560f01b6064820152608401610819565b600083815260056020526040902054821115610d475760405162461bcd60e51b815260206004820152602360248201527f496b736173756d693a206e6f7420656e6f756768206974656d7320666f722073604482015262616c6560e81b6064820152608401610819565b6000610d538284614d07565b600c546040516323b872dd60e01b81529192506001600160a01b0316906323b872dd90610d889033903090869060040161496c565b602060405180830381600087803b158015610da257600080fd5b505af1158015610db6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dda9190614654565b610df65760405162461bcd60e51b815260040161081990614b78565b60006040518060600160405280858152602001848152602001610e163390565b6001600160a01b0390811690915260008781526012602090815260408083208054600180820183558286528486208851600390930201918255878501519082015586830151600290910180546001600160a01b031916919096161790945589835292546013909152919020559050336001600160a01b0316857f3138d8d517460c959fb333d4e8d87ea984f1cf15d6742c02e2955dd27a622b708686604051610ec9929190918252602082015260400190565b60405180910390a350506001600a55505050565b6001600160a01b038516331480610ef95750610ef98533610727565b610f605760405162461bcd60e51b815260206004820152603260248201527f455243313135353a207472616e736665722063616c6c6572206973206e6f74206044820152711bdddb995c881b9bdc88185c1c1c9bdd995960721b6064820152608401610819565b610c06858585858561287d565b60008281526001602081905260409091200154610f8a8133612a38565b610f948383612a9c565b505050565b6001600160a01b03811633146110095760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610819565b6110138282612b07565b5050565b6002600a54141561103a5760405162461bcd60e51b815260040161081990614c75565b6002600a55600083815260106020526040902080543391908490811061107057634e487b7160e01b600052603260045260246000fd5b60009182526020909120600260049092020101546001600160a01b031614156110ee5760405162461bcd60e51b815260206004820152602a60248201527f496b6173756d693a2074686520757365722063616e6e6f7420627579206869736044820152691037bbb71037b33332b960b11b6064820152608401610819565b60008381526010602052604090208054611196913091637921219560e11b91908690811061112c57634e487b7160e01b600052603260045260246000fd5b60009182526020909120600490910201600201546001600160a01b031633878660405160240161115f94939291906149d5565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612b6e565b6000838152601060205260409020805461123a9190849081106111c957634e487b7160e01b600052603260045260246000fd5b906000526020600020906004020160010154826111e69190614d07565b33600086815260106020526040902080548690811061121557634e487b7160e01b600052603260045260246000fd5b60009182526020909120600360049092020101546001600160a01b0316866001612cec565b600083815260106020526040902080548291908490811061126b57634e487b7160e01b600052603260045260246000fd5b9060005260206000209060040201600001600082825461128b9190614d26565b909155505060008381526010602052604090208054839081106112be57634e487b7160e01b600052603260045260246000fd5b9060005260206000209060040201600001546000141561143357600083815260106020526040902080546112f490600190614d26565b8154811061131257634e487b7160e01b600052603260045260246000fd5b906000526020600020906004020160106000858152602001908152602001600020838154811061135257634e487b7160e01b600052603260045260246000fd5b6000918252602080832084546004909302019182556001808501549083015560028085015490830180546001600160a01b03199081166001600160a01b039384161790915560039586015495909301805490931694169390931790558481526010909152604090208054806113d757634e487b7160e01b600052603160045260246000fd5b60008281526020808220600460001990940193840201828155600181018390556002810180546001600160a01b031990811690915560039091018054909116905591909255848252601081526040808320546011909252909120555b50506001600a5550565b6002600a5414156114605760405162461bcd60e51b815260040161081990614c75565b6002600a55600082815260126020526040902080543391908390811061149657634e487b7160e01b600052603260045260246000fd5b60009182526020909120600260039092020101546001600160a01b03161461151e5760405162461bcd60e51b815260206004820152603560248201527f496b6173756d693a206f6e6c7920746865206f726967696e616c206269646465604482015274722063616e2063616e63656c20686973206269647360581b6064820152608401610819565b600082815260126020526040812080548390811061154c57634e487b7160e01b600052603260045260246000fd5b90600052602060002090600302016001015460126000858152602001908152602001600020838154811061159057634e487b7160e01b600052603260045260246000fd5b9060005260206000209060030201600001546115ac9190614d07565b60008481526012602052604090208054919250906115cc90600190614d26565b815481106115ea57634e487b7160e01b600052603260045260246000fd5b906000526020600020906003020160126000858152602001908152602001600020838154811061162a57634e487b7160e01b600052603260045260246000fd5b600091825260208083208454600390930201918255600180850154908301556002938401549390910180546001600160a01b0319166001600160a01b039094169390931790925584815260129091526040902080548061169a57634e487b7160e01b600052603160045260246000fd5b600082815260208082206003600019909401938402018281556001810183905560020180546001600160a01b03191690559190925584825260128152604080832054601390925290912055600c546001600160a01b031663a9059cbb6116fd3390565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401602060405180830381600087803b15801561174557600080fd5b505af1158015611759573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061177d9190614654565b6117995760405162461bcd60e51b815260040161081990614b78565b827f7277fc1cd614e04155fd1e358fe63c0576fc211585e1ec95403495e0272eeb4c836040516117cb91815260200190565b60405180910390a250506001600a5550565b60606117e7612580565b6118035760405162461bcd60e51b815260040161081990614bea565b6001600160a01b0383166118295760405162461bcd60e51b815260040161081990614c34565b60005b8251811015611879576118668484838151811061185957634e487b7160e01b600052603260045260246000fd5b6020026020010151611a93565b508061187181614de7565b91505061182c565b50505050565b606081518351146118e45760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b6064820152608401610819565b600083516001600160401b0381111561190d57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611936578160200160208202803683370190505b50905060005b84518110156119d85761199d85828151811061196857634e487b7160e01b600052603260045260246000fd5b602002602001015185838151811061199057634e487b7160e01b600052603260045260246000fd5b60200260200101516107b1565b8282815181106119bd57634e487b7160e01b600052603260045260246000fd5b60209081029190910101526119d181614de7565b905061193c565b509392505050565b6000546001600160a01b03163314611a0a5760405162461bcd60e51b815260040161081990614b43565b611a146000613257565b565b6060611a20612580565b611a3c5760405162461bcd60e51b815260040161081990614bea565b610c06858585856132a7565b60126020528160005260406000208181548110611a6457600080fd5b60009182526020909120600390910201805460018201546002909201549093509091506001600160a01b031683565b60006060611a9f612580565b611abb5760405162461bcd60e51b815260040161081990614bea565b611ac36132d1565b611aeb846008548560405180604001604052806002815260200161060f60f31b8152506132a7565b505060085492915050565b60106020528160005260406000208181548110611b1257600080fd5b6000918252602090912060049091020180546001820154600283015460039093015491945092506001600160a01b03918216911684565b60009182526001602090815260408084206001600160a01b0393909316845291905290205460ff1690565b60606007805461086a90614d80565b6060611b8d612580565b611ba95760405162461bcd60e51b815260040161081990614bea565b6110137f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a683610f6d565b6002600a541415611bf65760405162461bcd60e51b815260040161081990614c75565b6002600a55468514611c415760405162461bcd60e51b815260206004820152601460248201527324b5b0b9bab6b49d102bb937b7339031b430b4b760611b6044820152606401610819565b60008a8152601460205260409020548890611c5d908390614ccf565b1115611cd15760405162461bcd60e51b815260206004820152603960248201527f496b6173756d693a207468652071747920657863656564732074686520616d6f60448201527f756e7420617661696c61626c6520666f72206d696e74696e67000000000000006064820152608401610819565b8a1580611ceb575060008b81526005602052604090205415155b611d2f5760405162461bcd60e51b8152602060048201526015602482015274125ad85cdd5b5a4e8815dc9bdb99c8139195081251605a1b6044820152606401610819565b611d538a8a8a8a8a8a8a8a308b611d4e6000546001600160a01b031690565b6132fe565b60008a815260156020526040902054611d9d578a15611d825760008a81526015602052604090208b9055611d9d565b611d8a6132d1565b60085460008b8152601560205260409020555b611dd633601560008d8152602001908152602001600020548360405180604001604052806002815260200161060f60f31b8152506132a7565b60008a8152601560209081526040808320548352600f909152902080546001600160a01b0319166001600160a01b038616179055611e3a611e178883614d07565b336000546001600160a01b031660008e8152601560205260409020546001612cec565b600080548b825260156020526040909120546001600160a01b039091169033907ffd97862d5a5b5a3eb526cec9bc4d060e4927fa2388f7f3178f09a250dd864ab1611e858b86614d07565b60405190815260200160405180910390a460008a81526014602052604081208054839290611eb4908490614ccf565b90915550506001600a555050505050505050505050565b336001600160a01b0383161415611f365760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b6064820152608401610819565b3360008181526003602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6002600a541415611fc55760405162461bcd60e51b815260040161081990614c75565b6002600a556000838152601260205260409020805433919084908110611ffb57634e487b7160e01b600052603260045260246000fd5b60009182526020909120600260039092020101546001600160a01b0316141561207a5760405162461bcd60e51b815260206004820152602b60248201527f496b6173756d693a2074686520757365722063616e6e6f74206163636570742060448201526a1a1a5cc81bdddb88189a5960aa1b6064820152608401610819565b6120a8335b6001600160a01b0316600090815260036020908152604080832030845290915290205460ff1690565b6120b7576120b7306001611ecb565b61212430637921219560e11b3360008781526012602052604090208054879081106120f257634e487b7160e01b600052603260045260246000fd5b600091825260209091206002600390920201015460405161115f92916001600160a01b031690899088906024016149d5565b600083815260126020526040902080546121c891908490811061215757634e487b7160e01b600052603260045260246000fd5b906000526020600020906003020160010154826121749190614d07565b60008581526012602052604090208054859081106121a257634e487b7160e01b600052603260045260246000fd5b60009182526020909120600390910201600201546001600160a01b031633866000612cec565b60008381526012602052604090208054829190849081106121f957634e487b7160e01b600052603260045260246000fd5b906000526020600020906003020160000160008282546122199190614d26565b9091555050600083815260126020526040902080548390811061224c57634e487b7160e01b600052603260045260246000fd5b90600052602060002090600302016000015460001415611433576000838152601260205260409020805461228290600190614d26565b815481106122a057634e487b7160e01b600052603260045260246000fd5b90600052602060002090600302016012600085815260200190815260200160002083815481106122e057634e487b7160e01b600052603260045260246000fd5b600091825260208083208454600390930201918255600180850154908301556002938401549390910180546001600160a01b0319166001600160a01b039094169390931790925584815260129091526040902080548061235057634e487b7160e01b600052603160045260246000fd5b600082815260208082206003600019909401938402018281556001810183905560020180546001600160a01b0319169055919092558482526012815260408083205460139092529091205550506001600a5550565b60006108557f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a683611b49565b600082815260016020819052604090912001546123ee8133612a38565b610f948383612b07565b8261240333866107b1565b10156124685760405162461bcd60e51b815260206004820152602e60248201527f496b6173756d693a20796f7520646f206e6f74206861766520656e6f7567682060448201526d1d1bdad95b9cc81d1bc81cd95b1b60921b6064820152608401610819565b6124713361207f565b61248057612480306001611ecb565b600060405180608001604052808581526020018481526020016124a03390565b6001600160a01b039081168252848116602092830152600088815260108352604080822080546001818101835582855286852088516004909302019182558787015190820155828701516002820180549187166001600160a01b031992831617905560608801516003909201805492909616911617909355898252915460119093522055905061252d3390565b6001600160a01b0316857fce55bfae73b3c55d09c9fb6723466656ecb31fc2f7c5b90c296456857480c88c8686604051612571929190918252602082015260400190565b60405180910390a35050505050565b60095460009060ff16806125985750612598336123a5565b905090565b6001600160a01b0385163314806125b957506125b98533610727565b6126175760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201526808185c1c1c9bdd995960ba1b6064820152608401610819565b610c068585858585613418565b6000546001600160a01b0316331461264e5760405162461bcd60e51b815260040161081990614b43565b6001600160a01b0381166126b35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610819565b6126bc81613257565b50565b600061259861352b565b6000546001600160a01b031633146126f35760405162461bcd60e51b815260040161081990614b43565b60646126ff8486614ccf565b106127685760405162461bcd60e51b815260206004820152603360248201527f496b6173756d693a20746f74616c20636f6d6d697373696f6e732073686f756c604482015272064206265206c6f776572207468616e2031303606c1b6064820152608401610819565b600b80546001600160a01b039687166001600160a01b031991821617909155600d94909455600e929092556009805491151560ff19909216919091179055600c8054919093169116179055565b60006001600160e01b03198216636cdb3d1360e11b14806127e657506001600160e01b031982166303a24d0760e21b145b80610855575061085582613621565b61280184848484613656565b60005b8351811015610c065733600f600086848151811061283257634e487b7160e01b600052603260045260246000fd5b6020026020010151815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055508061287690614de7565b9050612804565b815183511461289e5760405162461bcd60e51b815260040161081990614ba2565b6001600160a01b0384166128c45760405162461bcd60e51b815260040161081990614ab4565b3360005b84518110156129ca5760008582815181106128f357634e487b7160e01b600052603260045260246000fd5b60200260200101519050600085838151811061291f57634e487b7160e01b600052603260045260246000fd5b60209081029190910181015160008481526002835260408082206001600160a01b038e1683529093529190912054909150818110156129705760405162461bcd60e51b815260040161081990614af9565b60008381526002602090815260408083206001600160a01b038e8116855292528083208585039055908b168252812080548492906129af908490614ccf565b92505081905550505050806129c390614de7565b90506128c8565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051612a1a929190614a2b565b60405180910390a4612a308187878787876136f5565b505050505050565b612a428282611b49565b61101357612a5a816001600160a01b03166014613860565b612a65836020613860565b604051602001612a76929190614899565b60408051601f198184030181529082905262461bcd60e51b825261081991600401614a59565b612aa68282611b49565b6110135760008281526001602081815260408084206001600160a01b0386168086529252808420805460ff19169093179092559051339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b612b118282611b49565b156110135760008281526001602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6001600160a01b0382163b612bc55760405162461bcd60e51b815260206004820152601d60248201527f496b6173756d693a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610819565b600080836001600160a01b031683604051612be0919061487d565b6000604051808303816000865af19150503d8060008114612c1d576040519150601f19603f3d011682016040523d82523d6000602084013e612c22565b606091505b509150915081612c745760405162461bcd60e51b815260206004820152601e60248201527f496b6173756d693a206c6f772d6c6576656c2063616c6c206661696c656400006044820152606401610819565b8051156118795780806020019051810190612c8f9190614654565b6118795760405162461bcd60e51b815260206004820152602860248201527f496b6173756d693a204552433230206f7065726174696f6e20646964206e6f74604482015267081cdd58d8d9595960c21b6064820152608401610819565b60006064600d5487612cfe9190614d07565b612d089190614ce7565b905060006064600e5488612d1c9190614d07565b612d269190614ce7565b9050600081612d35848a614d26565b612d3f9190614d26565b90508315612dee57600c546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90612d7b908a908a90869060040161496c565b602060405180830381600087803b158015612d9557600080fd5b505af1158015612da9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dcd9190614654565b612de95760405162461bcd60e51b815260040161081990614b78565b612e90565b600c5460405163a9059cbb60e01b81526001600160a01b038881166004830152602482018490529091169063a9059cbb90604401602060405180830381600087803b158015612e3c57600080fd5b505af1158015612e50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e749190614654565b612e905760405162461bcd60e51b815260040161081990614b78565b856001600160a01b0316876001600160a01b0316867f07f87664c10527a8207b443cccf57f3c20f25bd1165eeae416be79890a35892c84604051612ed691815260200190565b60405180910390a481156130a9578315612fa357600c546000868152600f6020526040908190205490516323b872dd60e01b81526001600160a01b03928316926323b872dd92612f30928c9290911690879060040161496c565b602060405180830381600087803b158015612f4a57600080fd5b505af1158015612f5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f829190614654565b612f9e5760405162461bcd60e51b815260040161081990614b78565b613054565b600c546000868152600f60205260409081902054905163a9059cbb60e01b81526001600160a01b0391821660048201526024810185905291169063a9059cbb90604401602060405180830381600087803b15801561300057600080fd5b505af1158015613014573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130389190614654565b6130545760405162461bcd60e51b815260040161081990614b78565b6000858152600f60209081526040918290205491518481526001600160a01b03928316928a169188917f802713d7f9cc0dcd6072902b48c61c206c34d6ca5f5288b580a6f86f9c9fe150910160405180910390a45b821561324d57831561316157600c54600b546040516323b872dd60e01b81526001600160a01b03928316926323b872dd926130ee928c9290911690889060040161496c565b602060405180830381600087803b15801561310857600080fd5b505af115801561311c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131409190614654565b61315c5760405162461bcd60e51b815260040161081990614b78565b613205565b600c54600b5460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810186905291169063a9059cbb90604401602060405180830381600087803b1580156131b157600080fd5b505af11580156131c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131e99190614654565b6132055760405162461bcd60e51b815260040161081990614b78565b600b546040518481526001600160a01b039182169189169087907f9577cd5ef459a0bf97b597490f08f1e93e995b9394e4c577932db36e71c4500c9060200160405180910390a45b5050505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000838152600f6020526040902080546001600160a01b0319163317905561187984848484613a48565b600880549060006132e183614de7565b90915550506008546000908152600560205260409020546132d157565b604080517f286c81460df074c46ce5aeb2d5be03f72c20e6c506d2bae9048ed617d90c3dba60208201529081018c9052606081018b9052608081018a905260a0810189905260c0810188905260e081018790526001600160a01b0380871661010083015261012082018690528416610140820152600090613398906101600160405160208183030381529060405280519060200120613a7d565b905060006133a68285613acb565b9050826001600160a01b0316816001600160a01b0316146134095760405162461bcd60e51b815260206004820152601860248201527f496b6173756d693a2077726f6e67207369676e617475726500000000000000006044820152606401610819565b50505050505050505050505050565b6001600160a01b03841661343e5760405162461bcd60e51b815260040161081990614ab4565b60008381526002602090815260408083206001600160a01b03891684529091529020543390838110156134835760405162461bcd60e51b815260040161081990614af9565b60008581526002602090815260408083206001600160a01b038b81168552925280832087850390559088168252812080548692906134c2908490614ccf565b909155505060408051868152602081018690526001600160a01b03808916928a821692918616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4613522828888888888613ae7565b50505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000046141561357a57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b90565b60006001600160e01b03198216637965db0b60e01b148061085557506301ffc9a760e01b6001600160e01b0319831614610855565b61366284848484613bb1565b60005b8351811015610c065782818151811061368e57634e487b7160e01b600052603260045260246000fd5b6020026020010151600560008684815181106136ba57634e487b7160e01b600052603260045260246000fd5b6020026020010151815260200190815260200160002060008282546136df9190614ccf565b909155506136ee905081614de7565b9050613665565b6001600160a01b0384163b15612a305760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190613739908990899088908890889060040161490e565b602060405180830381600087803b15801561375357600080fd5b505af1925050508015613783575060408051601f3d908101601f19168201909252613780918101906146c8565b60015b6138305761378f614e2e565b806308c379a014156137c957506137a4614e45565b806137af57506137cb565b8060405162461bcd60e51b81526004016108199190614a59565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e20455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b6064820152608401610819565b6001600160e01b0319811663bc197c8160e01b146135225760405162461bcd60e51b815260040161081990614a6c565b6060600061386f836002614d07565b61387a906002614ccf565b6001600160401b0381111561389f57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f1916602001820160405280156138c9576020820181803683370190505b509050600360fc1b816000815181106138f257634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061392f57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506000613953846002614d07565b61395e906001614ccf565b90505b60018111156139f2576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106139a057634e487b7160e01b600052603260045260246000fd5b1a60f81b8282815181106139c457634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c936139eb81614d69565b9050613961565b508315613a415760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610819565b9392505050565b613a5484848484613d19565b60008381526005602052604081208054849290613a72908490614ccf565b909155505050505050565b6000610855613a8a61352b565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000613ada8585613dd3565b915091506119d881613e43565b6001600160a01b0384163b15612a305760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190613b2b9089908990889088908890600401614990565b602060405180830381600087803b158015613b4557600080fd5b505af1925050508015613b75575060408051601f3d908101601f19168201909252613b72918101906146c8565b60015b613b815761378f614e2e565b6001600160e01b0319811663f23a6e6160e01b146135225760405162461bcd60e51b815260040161081990614a6c565b6001600160a01b038416613bd75760405162461bcd60e51b815260040161081990614c34565b8151835114613bf85760405162461bcd60e51b815260040161081990614ba2565b3360005b8451811015613cb157838181518110613c2557634e487b7160e01b600052603260045260246000fd5b602002602001015160026000878481518110613c5157634e487b7160e01b600052603260045260246000fd5b602002602001015181526020019081526020016000206000886001600160a01b03166001600160a01b031681526020019081526020016000206000828254613c999190614ccf565b90915550819050613ca981614de7565b915050613bfc565b50846001600160a01b031660006001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051613d02929190614a2b565b60405180910390a4610c06816000878787876136f5565b6001600160a01b038416613d3f5760405162461bcd60e51b815260040161081990614c34565b60008381526002602090815260408083206001600160a01b0388168452909152812080543392859291613d73908490614ccf565b909155505060408051858152602081018590526001600160a01b0380881692600092918516917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4610c0681600087878787613ae7565b600080825160411415613e0a5760208301516040840151606085015160001a613dfe87828585614044565b94509450505050613e3c565b825160401415613e345760208301516040840151613e29868383614131565b935093505050613e3c565b506000905060025b9250929050565b6000816004811115613e6557634e487b7160e01b600052602160045260246000fd5b1415613e6e5750565b6001816004811115613e9057634e487b7160e01b600052602160045260246000fd5b1415613ede5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610819565b6002816004811115613f0057634e487b7160e01b600052602160045260246000fd5b1415613f4e5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610819565b6003816004811115613f7057634e487b7160e01b600052602160045260246000fd5b1415613fc95760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610819565b6004816004811115613feb57634e487b7160e01b600052602160045260246000fd5b14156126bc5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610819565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561407b5750600090506003614128565b8460ff16601b1415801561409357508460ff16601c14155b156140a45750600090506004614128565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156140f8573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661412157600060019250925050614128565b9150600090505b94509492505050565b6000806001600160ff1b03831660ff84901c601b0161415287828885614044565b935093505050935093915050565b600082601f830112614170578081fd5b8135602061417d82614cac565b60405161418a8282614dbb565b8381528281019150858301600585901b870184018810156141a9578586fd5b855b858110156141c7578135845292840192908401906001016141ab565b5090979650505050505050565b600082601f8301126141e4578081fd5b81356001600160401b038111156141fd576141fd614e18565b604051614214601f8301601f191660200182614dbb565b818152846020838601011115614228578283fd5b816020850160208301379081016020019190915292915050565b600060208284031215614253578081fd5b8135613a4181614ece565b60008060408385031215614270578081fd5b823561427b81614ece565b9150602083013561428b81614ece565b809150509250929050565b600080600080600060a086880312156142ad578081fd5b85356142b881614ece565b945060208601356142c881614ece565b935060408601356001600160401b03808211156142e3578283fd5b6142ef89838a01614160565b94506060880135915080821115614304578283fd5b61431089838a01614160565b93506080880135915080821115614325578283fd5b50614332888289016141d4565b9150509295509295909350565b600080600080600060a08688031215614356578081fd5b853561436181614ece565b9450602086013561437181614ece565b9350604086013592506060860135915060808601356001600160401b03811115614399578182fd5b614332888289016141d4565b600080604083850312156143b7578182fd5b82356143c281614ece565b915060208301356001600160401b038111156143dc578182fd5b6143e885828601614160565b9150509250929050565b60008060008060808587031215614407578384fd5b843561441281614ece565b935060208501356001600160401b038082111561442d578485fd5b61443988838901614160565b9450604087013591508082111561444e578384fd5b61445a88838901614160565b9350606087013591508082111561446f578283fd5b5061447c878288016141d4565b91505092959194509250565b6000806040838503121561449a578182fd5b82356144a581614ece565b9150602083013561428b81614ee3565b600080604083850312156144c7578182fd5b82356144d281614ece565b946020939093013593505050565b600080600080600060a086880312156144f7578283fd5b853561450281614ece565b94506020860135935060408601359250606086013561452081614ee3565b9150608086013561453081614ece565b809150509295509295909350565b60008060008060808587031215614553578182fd5b843561455e81614ece565b9350602085013592506040850135915060608501356001600160401b03811115614586578182fd5b61447c878288016141d4565b600080604083850312156145a4578182fd5b82356001600160401b03808211156145ba578384fd5b818501915085601f8301126145cd578384fd5b813560206145da82614cac565b6040516145e78282614dbb565b8381528281019150858301600585901b870184018b1015614606578889fd5b8896505b8487101561463157803561461d81614ece565b83526001969096019591830191830161460a565b5096505086013592505080821115614647578283fd5b506143e885828601614160565b600060208284031215614665578081fd5b8151613a4181614ee3565b600060208284031215614681578081fd5b5035919050565b6000806040838503121561469a578182fd5b82359150602083013561428b81614ece565b6000602082840312156146bd578081fd5b8135613a4181614ef1565b6000602082840312156146d9578081fd5b8151613a4181614ef1565b600080604083850312156146f6578182fd5b50508035926020909101359150565b600080600060608486031215614719578081fd5b505081359360208301359350604090920135919050565b60008060008060808587031215614745578182fd5b843593506020850135925060408501359150606085013561476581614ece565b939692955090935050565b60008060008060008060008060008060006101608c8e031215614791578889fd5b8b359a5060208c0135995060408c0135985060608c0135975060808c0135965060a08c0135955060c08c0135945060e08c01356147cd81614ece565b93506101008c013592506101208c01356001600160401b038111156147f0578283fd5b6147fc8e828f016141d4565b9250506101408c013590509295989b509295989b9093969950565b6000815180845260208085019450808401835b838110156148465781518752958201959082019060010161482a565b509495945050505050565b60008151808452614869816020860160208601614d3d565b601f01601f19169290920160200192915050565b6000825161488f818460208701614d3d565b9190910192915050565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516148d1816017850160208801614d3d565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351614902816028840160208801614d3d565b01602801949350505050565b6001600160a01b0386811682528516602082015260a06040820181905260009061493a90830186614817565b828103606084015261494c8186614817565b905082810360808401526149608185614851565b98975050505050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190526000906149ca90830184614851565b979650505050505050565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260029082015261060f60f31b60c082015260e00190565b602081526000613a416020830184614817565b604081526000614a3e6040830185614817565b8281036020840152614a508185614817565b95945050505050565b602081526000613a416020830184614851565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526010908201526f2a3930b739b332b9103330b4b632b21760811b604082015260600190565b60208082526028908201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206040820152670dad2e6dac2e8c6d60c31b606082015260800190565b6020808252602a908201527f4552433131353559757a753a206d7573742068617665206d696e74657220726f6040820152691b19481d1bc81b5a5b9d60b21b606082015260800190565b60208082526021908201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736040820152607360f81b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60006001600160401b03821115614cc557614cc5614e18565b5060051b60200190565b60008219821115614ce257614ce2614e02565b500190565b600082614d0257634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615614d2157614d21614e02565b500290565b600082821015614d3857614d38614e02565b500390565b60005b83811015614d58578181015183820152602001614d40565b838111156118795750506000910152565b600081614d7857614d78614e02565b506000190190565b600181811c90821680614d9457607f821691505b60208210811415614db557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8201601f191681016001600160401b0381118282101715614de057614de0614e18565b6040525050565b6000600019821415614dfb57614dfb614e02565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d111561361e57600481823e5160e01c90565b600060443d1015614e535790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715614e8257505050505090565b8285019150815181811115614e9a5750505050505090565b843d8701016020828501011115614eb45750505050505090565b614ec360208286010187614dbb565b509095945050505050565b6001600160a01b03811681146126bc57600080fd5b80151581146126bc57600080fd5b6001600160e01b0319811681146126bc57600080fdfea26469706673582212203af130ce23b06cbe4bdd0d1862d48219bf1aa740af5cae8b5a307a8715c84b9b64736f6c63430008040033000000000000000000000000e4379a25a0db888e19ec2c14416fe68a62aca5cc000000000000000000000000e4379a25a0db888e19ec2c14416fe68a62aca5cc000000000000000000000000e4379a25a0db888e19ec2c14416fe68a62aca5cc000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000b496b6173756d69204e46540000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002494e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c68747470733a2f2f7770736d617274636f6e7472616374732e636f6d00000000

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.