Contract 0x5b80beef957ab48d872d79ce2b764fed9c945dba

 

Contract Overview

Balance:
0 MATIC

MATIC Value:
$0.00

Token:
 
Txn Hash
Method
Block
From
To
Value [Txn Fee]
0xb3d0cbc99115b43f85e57089f1453baff47c33215258099ec1f8a65bffbd4d9bList320763882022-08-19 15:31:34215 days 1 hr ago0xa7f98142a401d3d09cbdcb4264973b89959b54b7 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba0 MATIC0.001592151641 32.855643776
0xd184f0c9fda8db2d71452de81c1c449d06feafea409d3963d5ae34865043c416Redeem To309975942022-07-22 3:17:58243 days 13 hrs ago0x0ce3033484a2d377248b768d7c3ff431f7cd4474 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba4 MATIC0.01647795 50
0x05f63e413a84e0f521394d538aa0b5981dd009c16665c2b040125200d322ced4Redeem To309975682022-07-22 3:17:06243 days 13 hrs ago0x0ce3033484a2d377248b768d7c3ff431f7cd4474 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba4 MATIC0.01647895 50
0x5e9ed4ea2529dbad4258a49094056b3580c0c83f48298e40b04ac962d95fa9b0Redeem To309940492022-07-22 0:55:46243 days 15 hrs ago0x0ce3033484a2d377248b768d7c3ff431f7cd4474 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba4 MATIC0.01647795 50
0xcb19b3f5a4b21f6475578f085bbbd9cb17a84a4ee997e02c5d3069507492c59aRedeem To309940162022-07-22 0:54:36243 days 15 hrs ago0x0ce3033484a2d377248b768d7c3ff431f7cd4474 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba4 MATIC0.01647895 50
0x9dbc277af2cc9d8e859f80d3fb079ee7848e126b0e41bd3ed183c171b6ca1b18Redeem To303250312022-07-04 10:49:43261 days 5 hrs ago0x78d262ee17922bfb29476e25df20eec17e252902 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba2 MATIC0.01633735 50
0xb732e4a20b73e045e448a0b4e5a1f73354f8a7f7d78debbe3eaad87f4371f0b6Set Project Acti...295632582022-06-14 16:07:46281 days 37 mins ago0x941250ef2ad41a35994ffd7fd7baf01d95255552 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba0 MATIC0.007585090253 238.195272387
0x17f13f91e6c95c49070e383ff04d9dd0338f107b21f33ac581969214a3da1660Redeem To294422542022-06-11 16:15:02284 days 30 mins ago0x28298ef4036f2e638986fdff26d799f2e830f3a6 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba1.5 MATIC0.01647795 50
0xbfab7ad46cfa345fcd9dfdd2774ff80835482da2a6d33972b8d2733491692393List290526702022-06-02 0:15:36293 days 16 hrs ago0x001e1826c164dd5d439b72f2aa837848a37a88db IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba0 MATIC0.00145377 30.000000013
0x6f146dd73f7d29ea507770b5682c2e8f5a88ff4a091264e45f5fcb940bb345f9List290519042022-06-01 23:49:20293 days 16 hrs ago0x001e1826c164dd5d439b72f2aa837848a37a88db IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba0 MATIC0.00145377 30.000000012
0xe6dd82d358ef03826c110963e0361adba97f91d25b6fb6ea2f11d82f46cbcdb9Redeem To282057252022-05-11 22:17:36314 days 18 hrs ago0x4cabddc93479241224d874553611d170adbf8c71 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba5 MATIC0.112719168039 342.009557767
0xc2ea5fa918840d233ba346da2a465866a8c0a2fdd2b981a6d2c5a89f9c73fba7Redeem To282054022022-05-11 22:06:30314 days 18 hrs ago0x4cabddc93479241224d874553611d170adbf8c71 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba5 MATIC0.102862338827 312.132529888
0xd4e47ff1a8b250e37bc0ba8e7d3e0f03d5463a90bf3ed804969f45a7ae176af1Redeem To282052992022-05-11 22:02:32314 days 18 hrs ago0x4cabddc93479241224d874553611d170adbf8c71 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba2 MATIC0.205545944449 623.722699492
0x72131b0d7d84c0ee056d6e2b1f9aef1b35fee32f2b2cfb1aba1283741cabc91dSet Project Acti...277624292022-04-30 16:52:44325 days 23 hrs ago0x8c51be7a16969fcd1228893ab6b83fbdeb2dfdc1 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba0 MATIC0.001218707898 38.256777327
0x0e16ea4d51b18156513f25d8825ee0cef1df8242aadafbba61a6fb37e154829aCreate Project277624142022-04-30 16:52:14325 days 23 hrs ago0x8c51be7a16969fcd1228893ab6b83fbdeb2dfdc1 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba0 MATIC0.0048543158 41.127813276
0xbe6820508c37d9dca2dccfe60d9e53a2ad6b6f9235411eea8133a0c2dea2c7f8Redeem To277179522022-04-29 13:27:22327 days 3 hrs ago0x4cabddc93479241224d874553611d170adbf8c71 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba1.3 MATIC0.01647795 50
0x443b0b4f4e39295b439db7efac41a26f26c091c456a756c7ae29efde7fbbc4d1Redeem To276144722022-04-26 22:58:04329 days 17 hrs ago0xeb9aaebd25625b0f4b2664890ea11acf4260405b IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba2 MATIC0.01733235 50
0x7399aac1516d4cf672c0a444bd1373265ff4919d6972f0a6476819bea2f46e67Redeem To276113262022-04-26 21:03:24329 days 19 hrs ago0x0b34d6dd730cc495e709c63ba27a2b9663379cf6 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba1 MATIC0.01633835 50
0x3096c5b5c1dea94ee0d383c09764704a139811546666410ecb67481411dc4acbSet Project Acti...276111972022-04-26 20:58:58329 days 19 hrs ago0x0b34d6dd730cc495e709c63ba27a2b9663379cf6 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba0 MATIC0.000890652248 30.665619342
0xf587d2bd20a0ce39d616ce4b63199aa70f5182bc49ac6c9abbf0657daa0261eaSet Project Acti...276109862022-04-26 20:51:44329 days 19 hrs ago0x0b34d6dd730cc495e709c63ba27a2b9663379cf6 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba0 MATIC0.000939309914 32.340928074
0xa8e0f39ac46e17027686d74c4c3a9a2463ce0381c0cc550a7ce365c69c46a56bSet Project Acti...276109112022-04-26 20:49:10329 days 19 hrs ago0x0b34d6dd730cc495e709c63ba27a2b9663379cf6 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba0 MATIC0.001084766376 37.349069567
0xebc7cbd0eb17dc876179bd22b46b42a9842aa04ffe06eedb2131ceb175304538Redeem To275758772022-04-25 23:30:51330 days 17 hrs ago0x28298ef4036f2e638986fdff26d799f2e830f3a6 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba0 MATIC0.01527165 50
0x5b99ff9ee858b1a7f4ba8786eb78c6879085dadd657ebbc0ab67fedc8bad5869Redeem To274896292022-04-23 18:13:20332 days 22 hrs ago0x9ef43f24f172ecf8854ab13856c93f0f3b50747d IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba4 MATIC0.01647895 50
0x88e6f938caaeb43bfece8b718e1c38aabbf6cd030039de47a8b578178baa9782Redeem To274861962022-04-23 16:00:14333 days 45 mins ago0x0ce3033484a2d377248b768d7c3ff431f7cd4474 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba4 MATIC0.01647735 50
0x8d3a013f7c0778c8e4de7c6cd5f5dd6c0801becabf2dee575c8b712e55b65fa5Redeem To274861662022-04-23 15:59:14333 days 46 mins ago0x0ce3033484a2d377248b768d7c3ff431f7cd4474 IN  0x5b80beef957ab48d872d79ce2b764fed9c945dba4 MATIC0.01647735 50
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0xd184f0c9fda8db2d71452de81c1c449d06feafea409d3963d5ae34865043c416309975942022-07-22 3:17:58243 days 13 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x28298ef4036f2e638986fdff26d799f2e830f3a63.68 MATIC
0xd184f0c9fda8db2d71452de81c1c449d06feafea409d3963d5ae34865043c416309975942022-07-22 3:17:58243 days 13 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x1734a9efb960672e22f4110bdb211ea93d7baa920.32 MATIC
0x05f63e413a84e0f521394d538aa0b5981dd009c16665c2b040125200d322ced4309975682022-07-22 3:17:06243 days 13 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x28298ef4036f2e638986fdff26d799f2e830f3a63.68 MATIC
0x05f63e413a84e0f521394d538aa0b5981dd009c16665c2b040125200d322ced4309975682022-07-22 3:17:06243 days 13 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x1734a9efb960672e22f4110bdb211ea93d7baa920.32 MATIC
0x5e9ed4ea2529dbad4258a49094056b3580c0c83f48298e40b04ac962d95fa9b0309940492022-07-22 0:55:46243 days 15 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x28298ef4036f2e638986fdff26d799f2e830f3a63.68 MATIC
0x5e9ed4ea2529dbad4258a49094056b3580c0c83f48298e40b04ac962d95fa9b0309940492022-07-22 0:55:46243 days 15 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x1734a9efb960672e22f4110bdb211ea93d7baa920.32 MATIC
0xcb19b3f5a4b21f6475578f085bbbd9cb17a84a4ee997e02c5d3069507492c59a309940162022-07-22 0:54:36243 days 15 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x28298ef4036f2e638986fdff26d799f2e830f3a63.68 MATIC
0xcb19b3f5a4b21f6475578f085bbbd9cb17a84a4ee997e02c5d3069507492c59a309940162022-07-22 0:54:36243 days 15 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x1734a9efb960672e22f4110bdb211ea93d7baa920.32 MATIC
0x9dbc277af2cc9d8e859f80d3fb079ee7848e126b0e41bd3ed183c171b6ca1b18303250312022-07-04 10:49:43261 days 5 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x003763063ee3b84ada0b978561d7319084669cb11.84 MATIC
0x9dbc277af2cc9d8e859f80d3fb079ee7848e126b0e41bd3ed183c171b6ca1b18303250312022-07-04 10:49:43261 days 5 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x1734a9efb960672e22f4110bdb211ea93d7baa920.16 MATIC
0x17f13f91e6c95c49070e383ff04d9dd0338f107b21f33ac581969214a3da1660294422542022-06-11 16:15:02284 days 30 mins ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0xa9df4e9be1eec27e8711bc07703d989da5b924611.38 MATIC
0x17f13f91e6c95c49070e383ff04d9dd0338f107b21f33ac581969214a3da1660294422542022-06-11 16:15:02284 days 30 mins ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x1734a9efb960672e22f4110bdb211ea93d7baa920.12 MATIC
0xe6dd82d358ef03826c110963e0361adba97f91d25b6fb6ea2f11d82f46cbcdb9282057252022-05-11 22:17:36314 days 18 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x941250ef2ad41a35994ffd7fd7baf01d952555524.6 MATIC
0xe6dd82d358ef03826c110963e0361adba97f91d25b6fb6ea2f11d82f46cbcdb9282057252022-05-11 22:17:36314 days 18 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x1734a9efb960672e22f4110bdb211ea93d7baa920.4 MATIC
0xc2ea5fa918840d233ba346da2a465866a8c0a2fdd2b981a6d2c5a89f9c73fba7282054022022-05-11 22:06:30314 days 18 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x941250ef2ad41a35994ffd7fd7baf01d952555524.6 MATIC
0xc2ea5fa918840d233ba346da2a465866a8c0a2fdd2b981a6d2c5a89f9c73fba7282054022022-05-11 22:06:30314 days 18 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x1734a9efb960672e22f4110bdb211ea93d7baa920.4 MATIC
0xd4e47ff1a8b250e37bc0ba8e7d3e0f03d5463a90bf3ed804969f45a7ae176af1282052992022-05-11 22:02:32314 days 18 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x0b34d6dd730cc495e709c63ba27a2b9663379cf61.84 MATIC
0xd4e47ff1a8b250e37bc0ba8e7d3e0f03d5463a90bf3ed804969f45a7ae176af1282052992022-05-11 22:02:32314 days 18 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x1734a9efb960672e22f4110bdb211ea93d7baa920.16 MATIC
0xbe6820508c37d9dca2dccfe60d9e53a2ad6b6f9235411eea8133a0c2dea2c7f8277179522022-04-29 13:27:22327 days 3 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0xb768c0bbd3f9851b4d3db40affba8172925e641a1.196 MATIC
0xbe6820508c37d9dca2dccfe60d9e53a2ad6b6f9235411eea8133a0c2dea2c7f8277179522022-04-29 13:27:22327 days 3 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x1734a9efb960672e22f4110bdb211ea93d7baa920.104 MATIC
0x443b0b4f4e39295b439db7efac41a26f26c091c456a756c7ae29efde7fbbc4d1276144722022-04-26 22:58:04329 days 17 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x0b34d6dd730cc495e709c63ba27a2b9663379cf61.84 MATIC
0x443b0b4f4e39295b439db7efac41a26f26c091c456a756c7ae29efde7fbbc4d1276144722022-04-26 22:58:04329 days 17 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x1734a9efb960672e22f4110bdb211ea93d7baa920.16 MATIC
0x7399aac1516d4cf672c0a444bd1373265ff4919d6972f0a6476819bea2f46e67276113262022-04-26 21:03:24329 days 19 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0xd00692cbf7ee044b62ae7b70a216d3c5e34fefed0.92 MATIC
0x7399aac1516d4cf672c0a444bd1373265ff4919d6972f0a6476819bea2f46e67276113262022-04-26 21:03:24329 days 19 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x1734a9efb960672e22f4110bdb211ea93d7baa920.08 MATIC
0x5b99ff9ee858b1a7f4ba8786eb78c6879085dadd657ebbc0ab67fedc8bad5869274896292022-04-23 18:13:20332 days 22 hrs ago 0x5b80beef957ab48d872d79ce2b764fed9c945dba0x28298ef4036f2e638986fdff26d799f2e830f3a63.68 MATIC
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
OneOfX

Compiler Version
v0.8.11+commit.d7f03943

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 8 : OneOfX.sol
//SPDX-License-Identifier: Unlicense
pragma solidity 0.8.11;
pragma abicoder v2; // required to accept structs as function parameters

import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol";

contract OneOfX is IERC721Metadata, IERC721Enumerable, EIP712 {
    event WithdrawnBatch(address indexed user, uint256[] tokenIds);
    event TransferWithMetadata(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId,
        string metaData
    );
    event ProjectCreated(uint256 indexed projectId);
    event ProjectComplete(uint256 indexed projectId);
    event ProjectSetActive(uint256 indexed projectId, bool active);
    event TokenListed(uint256 indexed tokenId, uint256 price);
    event TokenUnlisted(uint256 indexed tokenId);
    event TokenPurchased(uint256 indexed tokenId, uint256 price, address to);

    struct Voucher {
        uint256 projectId;
        uint256 tokenId;
        uint256 price;
        string uri;
        bytes signature;
    }

    struct Project {
        bool active;
        address payable artist;
        uint256 maxSupply;
        uint256 revSharePercent;
        uint256 royaltyPercent;
        uint256[] tokenIds;
    }

    string public override name = "1 of X";
    string public override symbol = "1/X";
    string public contractURI = "";
    uint256 public registrationPrice = 0;
    address private signerAddress;
    address payable private payoutAddress;
    string private constant SIGNING_DOMAIN = "1/X";
    string private constant SIGNATURE_VERSION = "1";
    uint256 private constant REV_SHARE_PERCENT = 8;

    string private constant ERR_NOT_AUTHORIZED = "NOT_AUTHORIZED";
    string private constant ERR_BAD_REQUEST = "BAD_REQUEST";
    string private constant ERR_BAD_SIG = "BAD_SIGNATURE";
    string private constant ERR_BAD_RECEIVER = "BAD_RECEIVER";

    // keccak256("Voucher(uint256 projectId,uint256 tokenId,uint256 price,string uri)"),
    uint256 private constant HASH_MINT =
        0xda23fdd34f87fc366001e6fa219513efc3fab1bbb5680e299134e0ecd89e6bbe;

    mapping(uint256 => Project) public projects;
    mapping(uint256 => bool) public withdrawnTokens;
    mapping(address => bool) public administrators;
    mapping(address => bool) public depositors;
    mapping(uint256 => address) private tokenApprovals;
    mapping(uint256 => address) private tokenOwners;
    mapping(uint256 => string) public override tokenURI;
    mapping(address => mapping(address => bool)) private operatorApprovals;

    mapping(address => uint256[]) public addressToTokenIds;
    mapping(uint256 => uint256) internal tokenIdToIndexInOwner;
    mapping(uint256 => uint256) internal tokenIdToIndex;

    mapping(uint256 => uint256) public listedTokens;
    uint256[] public indexToTokenId;

    mapping(uint256 => uint256) internal tokenIdToProjectId;

    constructor() EIP712(SIGNING_DOMAIN, SIGNATURE_VERSION) {
        signerAddress = _msgSender();
        payoutAddress = payable(_msgSender());
        administrators[signerAddress] = true;
    }

    modifier onlyAdmin() {
        require(administrators[_msgSender()], ERR_NOT_AUTHORIZED);
        _;
    }

    modifier onlyDepositor() {
        require(depositors[_msgSender()], ERR_NOT_AUTHORIZED);
        _;
    }

    modifier onlyArtist(uint256 id) {
        require(
            administrators[_msgSender()] || projects[id].artist == _msgSender(),
            ERR_NOT_AUTHORIZED
        );
        _;
    }

    function setPayoutAddress(address payable addr) public onlyAdmin {
        payoutAddress = addr;
    }

    function setSignerAddress(address payable addr) public onlyAdmin {
        signerAddress = addr;
    }

    function setRegistrationPrice(uint256 price) public onlyAdmin {
        registrationPrice = price;
    }

    function setAdmin(address addr, bool isAdmin) public onlyAdmin {
        administrators[addr] = isAdmin;
    }

    function setDepositor(address addr, bool isDepositor) public onlyAdmin {
        depositors[addr] = isDepositor;
    }

    function setContractURI(string memory uri) public onlyAdmin {
        contractURI = uri;
    }

    function createProject(
        uint256 id,
        uint256 maxSupply,
        uint256 royaltyPercent
    ) public payable {
        require(
            projects[id].artist == address(0) &&
                (administrators[_msgSender()] ||
                    registrationPrice == msg.value),
            ERR_BAD_REQUEST
        );

        if (msg.value > 0) payoutAddress.transfer(msg.value);

        projects[id].active = false;
        projects[id].artist = payable(_msgSender());
        projects[id].maxSupply = maxSupply;
        projects[id].revSharePercent = REV_SHARE_PERCENT;
        projects[id].royaltyPercent = royaltyPercent;
        emit ProjectCreated(id);
    }

    function updateArtist(uint256 id, address payable artist) public onlyAdmin {
        projects[id].artist = artist;
    }

    function setProjectActive(uint256 id, bool active) public onlyArtist(id) {
        projects[id].active = active;
        emit ProjectSetActive(id, active);
    }

    function setProjectRevShare(uint256 id, uint256 revSharePercent)
        public
        onlyAdmin
    {
        require(
            revSharePercent >= 0 && revSharePercent <= 100,
            ERR_BAD_REQUEST
        );
        projects[id].revSharePercent = revSharePercent;
    }

    function projectTokenIds(uint256 projectId)
        external
        view
        returns (uint256[] memory)
    {
        return projects[projectId].tokenIds;
    }

    function balanceOf(address addr) external view returns (uint256 balance) {
        return addressToTokenIds[addr].length;
    }

    function ownerOf(uint256 tokenId)
        public
        view
        override
        returns (address owner)
    {
        return tokenOwners[tokenId];
    }

    function getApproved(uint256 tokenId)
        public
        view
        override
        returns (address owner)
    {
        require(_exists(tokenId), ERR_BAD_REQUEST);
        return tokenApprovals[tokenId];
    }

    function isApprovedForAll(address owner, address operator)
        public
        view
        override
        returns (bool)
    {
        return operatorApprovals[owner][operator];
    }

    function isApprovedOrOwner(address spender, uint256 tokenId)
        internal
        view
        returns (bool)
    {
        address owner = tokenOwners[tokenId];
        require(owner != address(0), ERR_BAD_REQUEST);
        return (spender == owner ||
            getApproved(tokenId) == spender ||
            isApprovedForAll(owner, spender));
    }

    function setApprovalForAll(address operator, bool approved)
        public
        override
    {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

    function redeemTo(address redeemer, Voucher calldata voucher)
        public
        payable
    {
        verify(voucher);

        require(
            redeemer != address(0) &&
                msg.value == voucher.price &&
                projects[voucher.projectId].active &&
                projects[voucher.projectId].tokenIds.length <
                projects[voucher.projectId].maxSupply &&
                !_exists(voucher.tokenId),
            ERR_BAD_REQUEST
        );

        projects[voucher.projectId].tokenIds.push(voucher.tokenId);

        if (
            projects[voucher.projectId].tokenIds.length ==
            projects[voucher.projectId].maxSupply
        ) {
            emit ProjectComplete(voucher.projectId);
        }

        tokenURI[voucher.tokenId] = voucher.uri;
        tokenIdToProjectId[voucher.tokenId] = voucher.projectId;

        _mint(redeemer, voucher.tokenId);

        if (msg.value > 0) {
            uint256 value = msg.value;
            uint256 oneOfXAmount = (value / 100) *
                projects[voucher.projectId].revSharePercent;

            if (oneOfXAmount > 0) {
                payoutAddress.transfer(oneOfXAmount);
                value -= oneOfXAmount;
            }

            projects[voucher.projectId].artist.transfer(value);
        }

        emit TokenPurchased(voucher.tokenId, msg.value, redeemer);
    }

    function list(uint256 tokenId, uint256 price) public {
        require(ownerOf(tokenId) == _msgSender(), ERR_NOT_AUTHORIZED);
        require(price > 0, ERR_BAD_REQUEST);

        listedTokens[tokenId] = price;

        emit TokenListed(tokenId, price);
    }

    function unlist(uint256 tokenId) public {
        require(ownerOf(tokenId) == _msgSender(), ERR_NOT_AUTHORIZED);

        delete listedTokens[tokenId];

        emit TokenUnlisted(tokenId);
    }

    function purchaseTo(uint256 tokenId, address addr) public payable {
        require(msg.value > 0, ERR_BAD_REQUEST);
        require(listedTokens[tokenId] == msg.value, ERR_NOT_AUTHORIZED);

        uint256 projectId = tokenIdToProjectId[tokenId];

        uint256 value = msg.value;
        uint256 oneOfXAmount = (value / 100) *
            projects[projectId].revSharePercent;
        uint256 royaltyAmount = (value / 100) *
            projects[projectId].royaltyPercent;

        if (oneOfXAmount > 0) {
            payoutAddress.transfer(oneOfXAmount);
            value -= oneOfXAmount;
        }

        if (royaltyAmount > 0) {
            projects[projectId].artist.transfer(royaltyAmount);
            value -= royaltyAmount;
        }

        payable(ownerOf(tokenId)).transfer(value);

        _safeTransfer(ownerOf(tokenId), addr, tokenId, "");

        emit TokenPurchased(tokenId, msg.value, addr);
    }

    function verify(Voucher calldata voucher) internal view {
        require(
            signerAddress ==
                ECDSA.recover(
                    _hashTypedDataV4(
                        keccak256(
                            abi.encode(
                                HASH_MINT,
                                voucher.projectId,
                                voucher.tokenId,
                                voucher.price,
                                keccak256(bytes(voucher.uri))
                            )
                        )
                    ),
                    voucher.signature
                ),
            ERR_BAD_SIG
        );
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external override {
        _safeTransferFrom(from, to, tokenId, "");
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external override {
        _safeTransferFrom(from, to, tokenId, data);
    }

    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external override {
        require(isApprovedOrOwner(_msgSender(), tokenId), ERR_NOT_AUTHORIZED);
        _safeTransfer(from, to, tokenId, "");
    }

    function approve(address to, uint256 tokenId) external override {
        require(_exists(tokenId), ERR_BAD_REQUEST);
        address owner = ownerOf(tokenId);
        require(
            (to != owner && _msgSender() == owner) ||
                isApprovedForAll(owner, _msgSender()),
            ERR_BAD_REQUEST
        );
        _approve(to, tokenId);
    }

    function totalSupply() external view returns (uint256) {
        return indexToTokenId.length;
    }

    function tokenOfOwnerByIndex(address owner, uint256 index)
        external
        view
        returns (uint256 tokenId)
    {
        require(addressToTokenIds[owner].length > index, ERR_BAD_REQUEST);
        return addressToTokenIds[owner][index];
    }

    function tokensOfOwner(address owner)
        external
        view
        returns (uint256[] memory tokenId)
    {
        return addressToTokenIds[owner];
    }

    function tokenByIndex(uint256 index) external view returns (uint256) {
        require(indexToTokenId.length > index, ERR_BAD_REQUEST);
        return indexToTokenId[index];
    }

    function getChainID() external view returns (uint256) {
        uint256 id;

        assembly {
            id := chainid()
        }

        return id;
    }

    function supportsInterface(bytes4 interfaceId)
        public
        pure
        override
        returns (bool)
    {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            interfaceId == type(IERC721Enumerable).interfaceId ||
            interfaceId == type(IERC165).interfaceId;
    }

    function deposit(address user, uint256[] calldata tokenIds) public {
        uint256 length = tokenIds.length;
        for (uint256 i; i < length; i++) {
            deposit(user, tokenIds[i]);
        }
    }

    function deposit(address user, uint256 tokenId) public onlyDepositor {
        require(withdrawnTokens[tokenId], ERR_NOT_AUTHORIZED);
        withdrawnTokens[tokenId] = false;
        _mint(user, tokenId);
    }

    function withdraw(uint256 tokenId) public {
        require(_msgSender() == ownerOf(tokenId), ERR_NOT_AUTHORIZED);

        withdrawnTokens[tokenId] = true;

        emit TransferWithMetadata(
            ownerOf(tokenId),
            address(0),
            tokenId,
            tokenURI[tokenId]
        );

        _burn(tokenId);
    }

    function withdraw(uint256[] calldata tokenIds) external {
        uint256 length = tokenIds.length;
        require(length <= 20, ERR_BAD_REQUEST);
        for (uint256 i; i < length; i++) {
            withdraw(tokenIds[i]);
        }

        emit WithdrawnBatch(_msgSender(), tokenIds);
    }

    // private

    function _mint(address to, uint256 tokenId) internal {
        _addToAddress(tokenId, to);
        tokenIdToIndex[tokenId] = indexToTokenId.length;
        indexToTokenId.push(tokenId);

        emit Transfer(address(0), to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, ""),
            ERR_BAD_RECEIVER
        );
    }

    function _exists(uint256 tokenId) private view returns (bool) {
        return ownerOf(tokenId) != address(0) && !withdrawnTokens[tokenId];
    }

    function _isContract(address account) private view returns (bool) {
        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    function _safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) private {
        require(isApprovedOrOwner(_msgSender(), tokenId), ERR_NOT_AUTHORIZED);
        _safeTransfer(from, to, tokenId, data);
    }

    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) private {
        _transfer(from, to, tokenId);
        require(
            _checkOnERC721Received(from, to, tokenId, data),
            ERR_BAD_RECEIVER
        );
    }

    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) private {
        require(ownerOf(tokenId) == from && to != address(0), ERR_BAD_REQUEST);
        delete tokenApprovals[tokenId];
        delete listedTokens[tokenId];

        _removeFromAddress(tokenId, from);
        _addToAddress(tokenId, to);

        emit Transfer(from, to, tokenId);
    }

    function _removeFromAddress(uint256 tokenId, address from) internal {
        delete tokenOwners[tokenId];

        uint256 tokenIndex = tokenIdToIndexInOwner[tokenId];

        addressToTokenIds[from][tokenIndex] = addressToTokenIds[from][
            addressToTokenIds[from].length - 1
        ];
        addressToTokenIds[from].pop();

        delete tokenIdToIndexInOwner[tokenId];
    }

    function _addToAddress(uint256 tokenId, address to) internal {
        tokenOwners[tokenId] = to;
        tokenIdToIndexInOwner[tokenId] = addressToTokenIds[to].length;
        addressToTokenIds[to].push(tokenId);
    }

    function _approve(address to, uint256 tokenId) private {
        tokenApprovals[tokenId] = to;
        emit Approval(ownerOf(tokenId), to, tokenId);
    }

    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) private {
        require(owner != operator, ERR_BAD_REQUEST);
        operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) private returns (bool) {
        if (_isContract(to)) {
            try
                IERC721Receiver(to).onERC721Received(
                    _msgSender(),
                    from,
                    tokenId,
                    data
                )
            returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert(ERR_BAD_RECEIVER);
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    function _msgSender() internal view returns (address payable sender) {
        if (msg.sender == address(this)) {
            bytes memory array = msg.data;
            uint256 index = msg.data.length;
            assembly {
                // Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
                sender := and(
                    mload(add(array, index)),
                    0xffffffffffffffffffffffffffffffffffffffff
                )
            }
        } else {
            sender = payable(msg.sender);
        }
        return sender;
    }

    function _burn(uint256 tokenId) private {
        delete tokenApprovals[tokenId];
        delete listedTokens[tokenId];
        address owner = ownerOf(tokenId);

        _removeFromAddress(tokenId, owner);

        uint256 tokenIndex = tokenIdToIndex[tokenId];
        indexToTokenId[tokenIndex] = indexToTokenId[indexToTokenId.length - 1];
        indexToTokenId.pop();

        delete tokenIdToIndex[tokenId];

        emit Transfer(owner, address(0), tokenId);
    }
}

File 2 of 8 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

File 3 of 8 : IERC721Enumerable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}

File 4 of 8 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

File 5 of 8 : draft-EIP712.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./ECDSA.sol";

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

File 6 of 8 : IERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
}

File 7 of 8 : IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

File 8 of 8 : ECDSA.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","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":"projectId","type":"uint256"}],"name":"ProjectComplete","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"projectId","type":"uint256"}],"name":"ProjectCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"projectId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"active","type":"bool"}],"name":"ProjectSetActive","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"TokenListed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"TokenPurchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"TokenUnlisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"metaData","type":"string"}],"name":"TransferWithMetadata","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"WithdrawnBatch","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"addressToTokenIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"administrators","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"royaltyPercent","type":"uint256"}],"name":"createProject","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"depositors","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getChainID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"indexToTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"list","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"listedTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"projectId","type":"uint256"}],"name":"projectTokenIds","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"projects","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"address payable","name":"artist","type":"address"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"revSharePercent","type":"uint256"},{"internalType":"uint256","name":"royaltyPercent","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"addr","type":"address"}],"name":"purchaseTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"redeemer","type":"address"},{"components":[{"internalType":"uint256","name":"projectId","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"string","name":"uri","type":"string"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct OneOfX.Voucher","name":"voucher","type":"tuple"}],"name":"redeemTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"registrationPrice","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":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bool","name":"isAdmin","type":"bool"}],"name":"setAdmin","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":"string","name":"uri","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bool","name":"isDepositor","type":"bool"}],"name":"setDepositor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"addr","type":"address"}],"name":"setPayoutAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"}],"name":"setProjectActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"revSharePercent","type":"uint256"}],"name":"setProjectRevShare","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"name":"setRegistrationPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"addr","type":"address"}],"name":"setSignerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"tokenId","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","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":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"unlist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address payable","name":"artist","type":"address"}],"name":"updateArtist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"withdrawnTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

6101206040526040518060400160405280600681526020017f31206f66205800000000000000000000000000000000000000000000000000008152506000908051906020019062000052929190620003d4565b506040518060400160405280600381526020017f312f58000000000000000000000000000000000000000000000000000000000081525060019080519060200190620000a0929190620003d4565b506040518060200160405280600081525060029080519060200190620000c8929190620003d4565b506000600355348015620000db57600080fd5b506040518060400160405280600381526020017f312f5800000000000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525060008280519060200120905060008280519060200120905060007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f90508260c081815250508160e081815250504660a08181525050620001b0818484620002e560201b60201c565b608081815250508061010081815250505050505050620001d56200032160201b60201c565b600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620002256200032160201b60201c565b600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160086000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550620005c1565b6000838383463060405160200162000302959493929190620004ff565b6040516020818303038152906040528051906020012090509392505050565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415620003cd57600080368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509050600080369050905073ffffffffffffffffffffffffffffffffffffffff818301511692505050620003d1565b3390505b90565b828054620003e2906200058b565b90600052602060002090601f01602090048101928262000406576000855562000452565b82601f106200042157805160ff191683800117855562000452565b8280016001018555821562000452579182015b828111156200045157825182559160200191906001019062000434565b5b50905062000461919062000465565b5090565b5b808211156200048057600081600090555060010162000466565b5090565b6000819050919050565b620004998162000484565b82525050565b6000819050919050565b620004b4816200049f565b82525050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620004e782620004ba565b9050919050565b620004f981620004da565b82525050565b600060a0820190506200051660008301886200048e565b6200052560208301876200048e565b6200053460408301866200048e565b620005436060830185620004a9565b620005526080830184620004ee565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620005a457607f821691505b60208210811415620005bb57620005ba6200055c565b5b50919050565b60805160a05160c05160e05161010051615f736200060660003960006144b0015260006144f2015260006144d10152600061445d015260006144850152615f736000f3fe60806040526004361061027d5760003560e01c80635ce3877b1161014f578063a22cb465116100c1578063ce1b71ed1161007a578063ce1b71ed146109f6578063e011744114610a12578063e5f14d9d14610a3b578063e8a3d48514610a78578063e985e9c514610aa3578063eed75f6d14610ae05761027d565b8063a22cb465146108d8578063a57465e114610901578063a71604e81461093e578063b88d4fde14610967578063bf5a4dd314610990578063c87b56dd146109b95761027d565b806376be15851161011357806376be1585146107a45780637aef1164146107e15780638462151c1461081e578063938e3d7b1461085b57806395d89b4114610884578063983d95ce146108af5761027d565b80635ce3877b146106bc5780636352211e146106e55780636f860d741461072257806370a082311461074b578063740c5896146107885761027d565b80632e1a7d4d116101f357806347e7ef24116101ac57806347e7ef241461059c5780634b0bddd2146105c55780634f6ccce7146105ee57806350fd73671461062b578063564b81ef146106545780635a9d1ac31461067f5761027d565b80632e1a7d4d1461049f5780632f597db5146104c85780632f745c59146104f157806333ea51a81461052e578063385aecae1461055757806342842e0e146105735761027d565b8063095ea7b311610245578063095ea7b31461038d578063107046bd146103b657806318160ddd146103f75780632165865814610422578063217332381461044d57806323b872dd146104765761027d565b806301ffc9a714610282578063046dc166146102bf57806306fdde03146102e857806307a974fc14610313578063081812fc14610350575b600080fd5b34801561028e57600080fd5b506102a960048036038101906102a49190614ad1565b610b1d565b6040516102b69190614b19565b60405180910390f35b3480156102cb57600080fd5b506102e660048036038101906102e19190614b92565b610cbf565b005b3480156102f457600080fd5b506102fd610dcf565b60405161030a9190614c58565b60405180910390f35b34801561031f57600080fd5b5061033a60048036038101906103359190614cb0565b610e5d565b6040516103479190614b19565b60405180910390f35b34801561035c57600080fd5b5061037760048036038101906103729190614cb0565b610e7d565b6040516103849190614cfe565b60405180910390f35b34801561039957600080fd5b506103b460048036038101906103af9190614d45565b610f3b565b005b3480156103c257600080fd5b506103dd60048036038101906103d89190614cb0565b6110d6565b6040516103ee959493929190614da3565b60405180910390f35b34801561040357600080fd5b5061040c611139565b6040516104199190614df6565b60405180910390f35b34801561042e57600080fd5b50610437611146565b6040516104449190614df6565b60405180910390f35b34801561045957600080fd5b50610474600480360381019061046f9190614e11565b61114c565b005b34801561048257600080fd5b5061049d60048036038101906104989190614e51565b611271565b005b3480156104ab57600080fd5b506104c660048036038101906104c19190614cb0565b61131a565b005b3480156104d457600080fd5b506104ef60048036038101906104ea9190614ed0565b611489565b005b3480156104fd57600080fd5b5061051860048036038101906105139190614d45565b611634565b6040516105259190614df6565b60405180910390f35b34801561053a57600080fd5b5061055560048036038101906105509190614b92565b611757565b005b610571600480360381019061056c9190614f10565b611867565b005b34801561057f57600080fd5b5061059a60048036038101906105959190614e51565b611b2f565b005b3480156105a857600080fd5b506105c360048036038101906105be9190614d45565b611b4f565b005b3480156105d157600080fd5b506105ec60048036038101906105e79190614f63565b611cee565b005b3480156105fa57600080fd5b5061061560048036038101906106109190614cb0565b611e15565b6040516106229190614df6565b60405180910390f35b34801561063757600080fd5b50610652600480360381019061064d9190614fa3565b611ebd565b005b34801561066057600080fd5b50610669612043565b6040516106769190614df6565b60405180910390f35b34801561068b57600080fd5b506106a660048036038101906106a19190614cb0565b612050565b6040516106b39190614df6565b60405180910390f35b3480156106c857600080fd5b506106e360048036038101906106de9190614fa3565b612068565b005b3480156106f157600080fd5b5061070c60048036038101906107079190614cb0565b6121dd565b6040516107199190614cfe565b60405180910390f35b34801561072e57600080fd5b5061074960048036038101906107449190614f63565b61221a565b005b34801561075757600080fd5b50610772600480360381019061076d9190614fe3565b612341565b60405161077f9190614df6565b60405180910390f35b6107a2600480360381019061079d9190615010565b61238d565b005b3480156107b057600080fd5b506107cb60048036038101906107c69190614fe3565b6126e2565b6040516107d89190614b19565b60405180910390f35b3480156107ed57600080fd5b5061080860048036038101906108039190614cb0565b612702565b6040516108159190614df6565b60405180910390f35b34801561082a57600080fd5b5061084560048036038101906108409190614fe3565b612726565b604051610852919061510e565b60405180910390f35b34801561086757600080fd5b50610882600480360381019061087d9190615265565b6127bd565b005b34801561089057600080fd5b506108996128a3565b6040516108a69190614c58565b60405180910390f35b3480156108bb57600080fd5b506108d660048036038101906108d1919061530e565b612931565b005b3480156108e457600080fd5b506108ff60048036038101906108fa9190614f63565b612a53565b005b34801561090d57600080fd5b5061092860048036038101906109239190614d45565b612a69565b6040516109359190614df6565b60405180910390f35b34801561094a57600080fd5b506109656004803603810190610960919061535b565b612a9a565b005b34801561097357600080fd5b5061098e60048036038101906109899190615411565b612aea565b005b34801561099c57600080fd5b506109b760048036038101906109b29190614cb0565b612b41565b005b3480156109c557600080fd5b506109e060048036038101906109db9190614cb0565b612c3e565b6040516109ed9190614c58565b60405180910390f35b610a106004803603810190610a0b91906154bd565b612cde565b005b348015610a1e57600080fd5b50610a396004803603810190610a349190614cb0565b6130cb565b005b348015610a4757600080fd5b50610a626004803603810190610a5d9190614cb0565b6131a1565b604051610a6f919061510e565b60405180910390f35b348015610a8457600080fd5b50610a8d61320f565b604051610a9a9190614c58565b60405180910390f35b348015610aaf57600080fd5b50610aca6004803603810190610ac59190615519565b61329d565b604051610ad79190614b19565b60405180910390f35b348015610aec57600080fd5b50610b076004803603810190610b029190614fe3565b613331565b604051610b149190614b19565b60405180910390f35b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610be857507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610c5057507f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610cb857507f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60086000610ccb613351565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166040518060400160405280600e81526020017f4e4f545f415554484f52495a454400000000000000000000000000000000000081525090610d8a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d819190614c58565b60405180910390fd5b5080600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008054610ddc90615588565b80601f0160208091040260200160405190810160405280929190818152602001828054610e0890615588565b8015610e555780601f10610e2a57610100808354040283529160200191610e55565b820191906000526020600020905b815481529060010190602001808311610e3857829003601f168201915b505050505081565b60076020528060005260406000206000915054906101000a900460ff1681565b6000610e8882613402565b6040518060400160405280600b81526020017f4241445f5245515545535400000000000000000000000000000000000000000081525090610eff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef69190614c58565b60405180910390fd5b50600a600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b610f4481613402565b6040518060400160405280600b81526020017f4241445f5245515545535400000000000000000000000000000000000000000081525090610fbb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fb29190614c58565b60405180910390fd5b506000610fc7826121dd565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561103757508073ffffffffffffffffffffffffffffffffffffffff1661101f613351565b73ffffffffffffffffffffffffffffffffffffffff16145b8061104f575061104e81611049613351565b61329d565b5b6040518060400160405280600b81526020017f4241445f52455155455354000000000000000000000000000000000000000000815250906110c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110bd9190614c58565b60405180910390fd5b506110d1838361346d565b505050565b60066020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154908060020154908060030154905085565b6000601280549050905090565b60035481565b60086000611158613351565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166040518060400160405280600e81526020017f4e4f545f415554484f52495a454400000000000000000000000000000000000081525090611217576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120e9190614c58565b60405180910390fd5b50806006600084815260200190815260200160002060000160016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b61128261127c613351565b82613526565b6040518060400160405280600e81526020017f4e4f545f415554484f52495a4544000000000000000000000000000000000000815250906112f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112f09190614c58565b60405180910390fd5b506113158383836040518060200160405280600081525061368f565b505050565b611323816121dd565b73ffffffffffffffffffffffffffffffffffffffff16611341613351565b73ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600e81526020017f4e4f545f415554484f52495a4544000000000000000000000000000000000000815250906113cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113c69190614c58565b60405180910390fd5b5060016007600083815260200190815260200160002060006101000a81548160ff02191690831515021790555080600073ffffffffffffffffffffffffffffffffffffffff1661141e836121dd565b73ffffffffffffffffffffffffffffffffffffffff167ff3c6803764de9a0fc1c2acb6a71f53407c5e2b9a3e04973e6586da23d64ecaa5600c6000868152602001908152602001600020604051611475919061564f565b60405180910390a461148681613724565b50565b8160086000611496613351565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff168061155157506114ec613351565b73ffffffffffffffffffffffffffffffffffffffff166006600083815260200190815260200160002060000160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b6040518060400160405280600e81526020017f4e4f545f415554484f52495a4544000000000000000000000000000000000000815250906115c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115bf9190614c58565b60405180910390fd5b50816006600085815260200190815260200160002060000160006101000a81548160ff021916908315150217905550827f1260f84b66aba3fb08c698d24c573290a872c73c2bc6bae41012e954bd97a5ae836040516116279190614b19565b60405180910390a2505050565b600081600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050116040518060400160405280600b81526020017f4241445f52455155455354000000000000000000000000000000000000000000815250906116f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116e99190614c58565b60405180910390fd5b50600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811061174457611743615671565b5b9060005260206000200154905092915050565b60086000611763613351565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166040518060400160405280600e81526020017f4e4f545f415554484f52495a454400000000000000000000000000000000000081525090611822576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118199190614c58565b60405180910390fd5b5080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600073ffffffffffffffffffffffffffffffffffffffff166006600085815260200190815260200160002060000160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161480156119355750600860006118e0613351565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1680611934575034600354145b5b6040518060400160405280600b81526020017f4241445f52455155455354000000000000000000000000000000000000000000815250906119ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119a39190614c58565b60405180910390fd5b506000341115611a2057600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050158015611a1e573d6000803e3d6000fd5b505b60006006600085815260200190815260200160002060000160006101000a81548160ff021916908315150217905550611a57613351565b6006600085815260200190815260200160002060000160016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600660008581526020019081526020016000206001018190555060086006600085815260200190815260200160002060020181905550806006600085815260200190815260200160002060030181905550827f1ac2092e16e28eef29d1832f3dc69da1b21284a1f3159d3b26cb238b22fe4f8a60405160405180910390a2505050565b611b4a83838360405180602001604052806000815250613892565b505050565b60096000611b5b613351565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166040518060400160405280600e81526020017f4e4f545f415554484f52495a454400000000000000000000000000000000000081525090611c1a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c119190614c58565b60405180910390fd5b506007600082815260200190815260200160002060009054906101000a900460ff166040518060400160405280600e81526020017f4e4f545f415554484f52495a454400000000000000000000000000000000000081525090611cb3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611caa9190614c58565b60405180910390fd5b5060006007600083815260200190815260200160002060006101000a81548160ff021916908315150217905550611cea828261392d565b5050565b60086000611cfa613351565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166040518060400160405280600e81526020017f4e4f545f415554484f52495a454400000000000000000000000000000000000081525090611db9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611db09190614c58565b60405180910390fd5b5080600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b600081601280549050116040518060400160405280600b81526020017f4241445f5245515545535400000000000000000000000000000000000000000081525090611e96576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e8d9190614c58565b60405180910390fd5b5060128281548110611eab57611eaa615671565b5b90600052602060002001549050919050565b611ec5613351565b73ffffffffffffffffffffffffffffffffffffffff16611ee4836121dd565b73ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600e81526020017f4e4f545f415554484f52495a454400000000000000000000000000000000000081525090611f72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f699190614c58565b60405180910390fd5b50600081116040518060400160405280600b81526020017f4241445f5245515545535400000000000000000000000000000000000000000081525090611fee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fe59190614c58565b60405180910390fd5b50806011600084815260200190815260200160002081905550817f1ea85aaf6731daa0c29195039c2a36576fb04e2cd16335504fab8967dfb03f15826040516120379190614df6565b60405180910390a25050565b6000804690508091505090565b60116020528060005260406000206000915090505481565b60086000612074613351565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166040518060400160405280600e81526020017f4e4f545f415554484f52495a454400000000000000000000000000000000000081525090612133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161212a9190614c58565b60405180910390fd5b5060008110158015612146575060648111155b6040518060400160405280600b81526020017f4241445f52455155455354000000000000000000000000000000000000000000815250906121bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121b49190614c58565b60405180910390fd5b508060066000848152602001908152602001600020600201819055505050565b6000600b600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60086000612226613351565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166040518060400160405280600e81526020017f4e4f545f415554484f52495a4544000000000000000000000000000000000000815250906122e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122dc9190614c58565b60405180910390fd5b5080600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b6000600e60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b600034116040518060400160405280600b81526020017f4241445f5245515545535400000000000000000000000000000000000000000081525090612408576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123ff9190614c58565b60405180910390fd5b50346011600084815260200190815260200160002054146040518060400160405280600e81526020017f4e4f545f415554484f52495a454400000000000000000000000000000000000081525090612496576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161248d9190614c58565b60405180910390fd5b506000601360008481526020019081526020016000205490506000349050600060066000848152602001908152602001600020600201546064836124da91906156fe565b6124e4919061572f565b90506000600660008581526020019081526020016000206003015460648461250c91906156fe565b612516919061572f565b9050600082111561259957600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050158015612589573d6000803e3d6000fd5b5081836125969190615789565b92505b600081111561262e576006600085815260200190815260200160002060000160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015801561261e573d6000803e3d6000fd5b50808361262b9190615789565b92505b612637866121dd565b73ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f1935050505015801561267c573d6000803e3d6000fd5b506126a0612689876121dd565b86886040518060200160405280600081525061368f565b857fe58b9ee1e58fdb7c85bb2c81b24351f11e5a77f2c91dc346c0444da8d47fef5e34876040516126d29291906157bd565b60405180910390a2505050505050565b60086020528060005260406000206000915054906101000a900460ff1681565b6012818154811061271257600080fd5b906000526020600020016000915090505481565b6060600e60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156127b157602002820191906000526020600020905b81548152602001906001019080831161279d575b50505050509050919050565b600860006127c9613351565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166040518060400160405280600e81526020017f4e4f545f415554484f52495a454400000000000000000000000000000000000081525090612888576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161287f9190614c58565b60405180910390fd5b50806002908051906020019061289f92919061493c565b5050565b600180546128b090615588565b80601f01602080910402602001604051908101604052809291908181526020018280546128dc90615588565b80156129295780601f106128fe57610100808354040283529160200191612929565b820191906000526020600020905b81548152906001019060200180831161290c57829003601f168201915b505050505081565b600082829050905060148111156040518060400160405280600b81526020017f4241445f52455155455354000000000000000000000000000000000000000000815250906129b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129ac9190614c58565b60405180910390fd5b5060005b818110156129f6576129e38484838181106129d7576129d6615671565b5b9050602002013561131a565b80806129ee906157e6565b9150506129b9565b506129ff613351565b73ffffffffffffffffffffffffffffffffffffffff167ff871896b17e9cb7a64941c62c188a4f5c621b86800e3d15452ece01ce56073df8484604051612a46929190615890565b60405180910390a2505050565b612a65612a5e613351565b8383613a71565b5050565b600e6020528160005260406000208181548110612a8557600080fd5b90600052602060002001600091509150505481565b600082829050905060005b81811015612ae357612ad085858584818110612ac457612ac3615671565b5b90506020020135611b4f565b8080612adb906157e6565b915050612aa5565b5050505050565b612b3a85858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050613892565b5050505050565b612b49613351565b73ffffffffffffffffffffffffffffffffffffffff16612b68826121dd565b73ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600e81526020017f4e4f545f415554484f52495a454400000000000000000000000000000000000081525090612bf6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bed9190614c58565b60405180910390fd5b506011600082815260200190815260200160002060009055807fe0bba5d0bdeddbcc4ef688b9d8170c81883fb4c4a7065d8970c58b47996dd2d760405160405180910390a250565b600c6020528060005260406000206000915090508054612c5d90615588565b80601f0160208091040260200160405190810160405280929190818152602001828054612c8990615588565b8015612cd65780601f10612cab57610100808354040283529160200191612cd6565b820191906000526020600020905b815481529060010190602001808311612cb957829003601f168201915b505050505081565b612ce781613c17565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015612d275750806040013534145b8015612d575750600660008260000135815260200190815260200160002060000160009054906101000a900460ff165b8015612d995750600660008260000135815260200190815260200160002060010154600660008360000135815260200190815260200160002060040180549050105b8015612daf5750612dad8160200135613402565b155b6040518060400160405280600b81526020017f4241445f5245515545535400000000000000000000000000000000000000000081525090612e26576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e1d9190614c58565b60405180910390fd5b506006600082600001358152602001908152602001600020600401816020013590806001815401808255809150506001900390600052602060002001600090919091909150556006600082600001358152602001908152602001600020600101546006600083600001358152602001908152602001600020600401805490501415612edd5780600001357fb0a8d3d1f419d3118bddc80a81f300b86c9ff141ab958adc8d18a738d82c15ce60405160405180910390a25b808060600190612eed91906158c3565b600c6000846020013581526020019081526020016000209190612f119291906149c2565b508060000135601360008360200135815260200190815260200160002081905550612f4082826020013561392d565b60003411156130895760003490506000600660008460000135815260200190815260200160002060020154606483612f7891906156fe565b612f82919061572f565b9050600081111561300557600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015612ff5573d6000803e3d6000fd5b5080826130029190615789565b91505b600660008460000135815260200190815260200160002060000160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050158015613085573d6000803e3d6000fd5b5050505b80602001357fe58b9ee1e58fdb7c85bb2c81b24351f11e5a77f2c91dc346c0444da8d47fef5e34846040516130bf9291906157bd565b60405180910390a25050565b600860006130d7613351565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166040518060400160405280600e81526020017f4e4f545f415554484f52495a454400000000000000000000000000000000000081525090613196576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161318d9190614c58565b60405180910390fd5b508060038190555050565b60606006600083815260200190815260200160002060040180548060200260200160405190810160405280929190818152602001828054801561320357602002820191906000526020600020905b8154815260200190600101908083116131ef575b50505050509050919050565b6002805461321c90615588565b80601f016020809104026020016040519081016040528092919081815260200182805461324890615588565b80156132955780601f1061326a57610100808354040283529160200191613295565b820191906000526020600020905b81548152906001019060200180831161327857829003601f168201915b505050505081565b6000600d60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60096020528060005260406000206000915054906101000a900460ff1681565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156133fb57600080368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509050600080369050905073ffffffffffffffffffffffffffffffffffffffff8183015116925050506133ff565b3390505b90565b60008073ffffffffffffffffffffffffffffffffffffffff16613424836121dd565b73ffffffffffffffffffffffffffffffffffffffff161415801561346657506007600083815260200190815260200160002060009054906101000a900460ff16155b9050919050565b81600a600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff166134e0836121dd565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600080600b600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600b81526020017f4241445f5245515545535400000000000000000000000000000000000000000081525090613607576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135fe9190614c58565b60405180910390fd5b508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061367557508373ffffffffffffffffffffffffffffffffffffffff1661365d84610e7d565b73ffffffffffffffffffffffffffffffffffffffff16145b806136865750613685818561329d565b5b91505092915050565b61369a848484613dc5565b6136a684848484613f6e565b6040518060400160405280600c81526020017f4241445f524543454956455200000000000000000000000000000000000000008152509061371d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016137149190614c58565b60405180910390fd5b5050505050565b600a600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556011600082815260200190815260200160002060009055600061377c826121dd565b90506137888282614117565b600060106000848152602001908152602001600020549050601260016012805490506137b49190615789565b815481106137c5576137c4615671565b5b9060005260206000200154601282815481106137e4576137e3615671565b5b9060005260206000200181905550601280548061380457613803615926565b5b60019003818190600052602060002001600090559055601060008481526020019081526020016000206000905582600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6138a361389d613351565b83613526565b6040518060400160405280600e81526020017f4e4f545f415554484f52495a45440000000000000000000000000000000000008152509061391a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139119190614c58565b60405180910390fd5b506139278484848461368f565b50505050565b61393781836142ef565b60128054905060106000838152602001908152602001600020819055506012819080600181540180825580915050600190039060005260206000200160009091909190915055808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46139f56000838360405180602001604052806000815250613f6e565b6040518060400160405280600c81526020017f4241445f5245434549564552000000000000000000000000000000000000000081525090613a6c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613a639190614c58565b60405180910390fd5b505050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600b81526020017f4241445f5245515545535400000000000000000000000000000000000000000081525090613b18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613b0f9190614c58565b60405180910390fd5b5080600d60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051613c0a9190614b19565b60405180910390a3505050565b613cfa613ca27fda23fdd34f87fc366001e6fa219513efc3fab1bbb5680e299134e0ecd89e6bbe836000013584602001358560400135868060600190613c5d91906158c3565b604051613c6b929190615985565b6040518091039020604051602001613c879594939291906159b7565b60405160208183030381529060405280519060200120614405565b828060800190613cb29190615a0a565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061441f565b73ffffffffffffffffffffffffffffffffffffffff16600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600d81526020017f4241445f5349474e41545552450000000000000000000000000000000000000081525090613dc1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613db89190614c58565b60405180910390fd5b5050565b8273ffffffffffffffffffffffffffffffffffffffff16613de5826121dd565b73ffffffffffffffffffffffffffffffffffffffff16148015613e355750600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b6040518060400160405280600b81526020017f4241445f5245515545535400000000000000000000000000000000000000000081525090613eac576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613ea39190614c58565b60405180910390fd5b50600a600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556011600082815260200190815260200160002060009055613f048184614117565b613f0e81836142ef565b808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6000613f7984614446565b1561410a578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02613fa2613351565b8786866040518563ffffffff1660e01b8152600401613fc49493929190615b21565b6020604051808303816000875af192505050801561400057506040513d601f19601f82011682018060405250810190613ffd9190615b82565b60015b6140ba573d8060008114614030576040519150601f19603f3d011682016040523d82523d6000602084013e614035565b606091505b506000815114156140b2576040518060400160405280600c81526020017f4241445f524543454956455200000000000000000000000000000000000000008152506040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016140a99190614c58565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161491505061410f565b600190505b949350505050565b600b600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000600f6000848152602001908152602001600020549050600e60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490506141f39190615789565b8154811061420457614203615671565b5b9060005260206000200154600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481106142605761425f615671565b5b9060005260206000200181905550600e60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806142bd576142bc615926565b5b60019003818190600052602060002001600090559055600f600084815260200190815260200160002060009055505050565b80600b600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600e60008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050600f600084815260200190815260200160002081905550600e60008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208290806001815401808255809150506001900390600052602060002001600090919091909150555050565b6000614418614412614459565b8361451c565b9050919050565b600080600061442e858561454f565b9150915061443b816145d2565b819250505092915050565b600080823b905060008111915050919050565b60007f00000000000000000000000000000000000000000000000000000000000000004614156144ab577f00000000000000000000000000000000000000000000000000000000000000009050614519565b6145167f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006147a7565b90505b90565b60008282604051602001614531929190615c27565b60405160208183030381529060405280519060200120905092915050565b6000806041835114156145915760008060006020860151925060408601519150606086015160001a9050614585878285856147e1565b945094505050506145cb565b6040835114156145c25760008060208501519150604085015190506145b78683836148ee565b9350935050506145cb565b60006002915091505b9250929050565b600060048111156145e6576145e5615c5e565b5b8160048111156145f9576145f8615c5e565b5b1415614604576147a4565b6001600481111561461857614617615c5e565b5b81600481111561462b5761462a615c5e565b5b141561466c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161466390615cd9565b60405180910390fd5b600260048111156146805761467f615c5e565b5b81600481111561469357614692615c5e565b5b14156146d4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016146cb90615d45565b60405180910390fd5b600360048111156146e8576146e7615c5e565b5b8160048111156146fb576146fa615c5e565b5b141561473c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161473390615dd7565b60405180910390fd5b60048081111561474f5761474e615c5e565b5b81600481111561476257614761615c5e565b5b14156147a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161479a90615e69565b60405180910390fd5b5b50565b600083838346306040516020016147c2959493929190615e89565b6040516020818303038152906040528051906020012090509392505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c111561481c5760006003915091506148e5565b601b8560ff16141580156148345750601c8560ff1614155b156148465760006004915091506148e5565b60006001878787876040516000815260200160405260405161486b9493929190615ef8565b6020604051602081039080840390855afa15801561488d573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156148dc576000600192509250506148e5565b80600092509250505b94509492505050565b6000806000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85169150601b8560ff1c01905061492e878288856147e1565b935093505050935093915050565b82805461494890615588565b90600052602060002090601f01602090048101928261496a57600085556149b1565b82601f1061498357805160ff19168380011785556149b1565b828001600101855582156149b1579182015b828111156149b0578251825591602001919060010190614995565b5b5090506149be9190614a48565b5090565b8280546149ce90615588565b90600052602060002090601f0160209004810192826149f05760008555614a37565b82601f10614a0957803560ff1916838001178555614a37565b82800160010185558215614a37579182015b82811115614a36578235825591602001919060010190614a1b565b5b509050614a449190614a48565b5090565b5b80821115614a61576000816000905550600101614a49565b5090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614aae81614a79565b8114614ab957600080fd5b50565b600081359050614acb81614aa5565b92915050565b600060208284031215614ae757614ae6614a6f565b5b6000614af584828501614abc565b91505092915050565b60008115159050919050565b614b1381614afe565b82525050565b6000602082019050614b2e6000830184614b0a565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000614b5f82614b34565b9050919050565b614b6f81614b54565b8114614b7a57600080fd5b50565b600081359050614b8c81614b66565b92915050565b600060208284031215614ba857614ba7614a6f565b5b6000614bb684828501614b7d565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015614bf9578082015181840152602081019050614bde565b83811115614c08576000848401525b50505050565b6000601f19601f8301169050919050565b6000614c2a82614bbf565b614c348185614bca565b9350614c44818560208601614bdb565b614c4d81614c0e565b840191505092915050565b60006020820190508181036000830152614c728184614c1f565b905092915050565b6000819050919050565b614c8d81614c7a565b8114614c9857600080fd5b50565b600081359050614caa81614c84565b92915050565b600060208284031215614cc657614cc5614a6f565b5b6000614cd484828501614c9b565b91505092915050565b6000614ce882614b34565b9050919050565b614cf881614cdd565b82525050565b6000602082019050614d136000830184614cef565b92915050565b614d2281614cdd565b8114614d2d57600080fd5b50565b600081359050614d3f81614d19565b92915050565b60008060408385031215614d5c57614d5b614a6f565b5b6000614d6a85828601614d30565b9250506020614d7b85828601614c9b565b9150509250929050565b614d8e81614b54565b82525050565b614d9d81614c7a565b82525050565b600060a082019050614db86000830188614b0a565b614dc56020830187614d85565b614dd26040830186614d94565b614ddf6060830185614d94565b614dec6080830184614d94565b9695505050505050565b6000602082019050614e0b6000830184614d94565b92915050565b60008060408385031215614e2857614e27614a6f565b5b6000614e3685828601614c9b565b9250506020614e4785828601614b7d565b9150509250929050565b600080600060608486031215614e6a57614e69614a6f565b5b6000614e7886828701614d30565b9350506020614e8986828701614d30565b9250506040614e9a86828701614c9b565b9150509250925092565b614ead81614afe565b8114614eb857600080fd5b50565b600081359050614eca81614ea4565b92915050565b60008060408385031215614ee757614ee6614a6f565b5b6000614ef585828601614c9b565b9250506020614f0685828601614ebb565b9150509250929050565b600080600060608486031215614f2957614f28614a6f565b5b6000614f3786828701614c9b565b9350506020614f4886828701614c9b565b9250506040614f5986828701614c9b565b9150509250925092565b60008060408385031215614f7a57614f79614a6f565b5b6000614f8885828601614d30565b9250506020614f9985828601614ebb565b9150509250929050565b60008060408385031215614fba57614fb9614a6f565b5b6000614fc885828601614c9b565b9250506020614fd985828601614c9b565b9150509250929050565b600060208284031215614ff957614ff8614a6f565b5b600061500784828501614d30565b91505092915050565b6000806040838503121561502757615026614a6f565b5b600061503585828601614c9b565b925050602061504685828601614d30565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61508581614c7a565b82525050565b6000615097838361507c565b60208301905092915050565b6000602082019050919050565b60006150bb82615050565b6150c5818561505b565b93506150d08361506c565b8060005b838110156151015781516150e8888261508b565b97506150f3836150a3565b9250506001810190506150d4565b5085935050505092915050565b6000602082019050818103600083015261512881846150b0565b905092915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61517282614c0e565b810181811067ffffffffffffffff821117156151915761519061513a565b5b80604052505050565b60006151a4614a65565b90506151b08282615169565b919050565b600067ffffffffffffffff8211156151d0576151cf61513a565b5b6151d982614c0e565b9050602081019050919050565b82818337600083830152505050565b6000615208615203846151b5565b61519a565b90508281526020810184848401111561522457615223615135565b5b61522f8482856151e6565b509392505050565b600082601f83011261524c5761524b615130565b5b813561525c8482602086016151f5565b91505092915050565b60006020828403121561527b5761527a614a6f565b5b600082013567ffffffffffffffff81111561529957615298614a74565b5b6152a584828501615237565b91505092915050565b600080fd5b600080fd5b60008083601f8401126152ce576152cd615130565b5b8235905067ffffffffffffffff8111156152eb576152ea6152ae565b5b602083019150836020820283011115615307576153066152b3565b5b9250929050565b6000806020838503121561532557615324614a6f565b5b600083013567ffffffffffffffff81111561534357615342614a74565b5b61534f858286016152b8565b92509250509250929050565b60008060006040848603121561537457615373614a6f565b5b600061538286828701614d30565b935050602084013567ffffffffffffffff8111156153a3576153a2614a74565b5b6153af868287016152b8565b92509250509250925092565b60008083601f8401126153d1576153d0615130565b5b8235905067ffffffffffffffff8111156153ee576153ed6152ae565b5b60208301915083600182028301111561540a576154096152b3565b5b9250929050565b60008060008060006080868803121561542d5761542c614a6f565b5b600061543b88828901614d30565b955050602061544c88828901614d30565b945050604061545d88828901614c9b565b935050606086013567ffffffffffffffff81111561547e5761547d614a74565b5b61548a888289016153bb565b92509250509295509295909350565b600080fd5b600060a082840312156154b4576154b3615499565b5b81905092915050565b600080604083850312156154d4576154d3614a6f565b5b60006154e285828601614d30565b925050602083013567ffffffffffffffff81111561550357615502614a74565b5b61550f8582860161549e565b9150509250929050565b600080604083850312156155305761552f614a6f565b5b600061553e85828601614d30565b925050602061554f85828601614d30565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806155a057607f821691505b602082108114156155b4576155b3615559565b5b50919050565b60008190508160005260206000209050919050565b600081546155dc81615588565b6155e68186614bca565b94506001821660008114615601576001811461561357615646565b60ff1983168652602086019350615646565b61561c856155ba565b60005b8381101561563e5781548189015260018201915060208101905061561f565b808801955050505b50505092915050565b6000602082019050818103600083015261566981846155cf565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061570982614c7a565b915061571483614c7a565b925082615724576157236156a0565b5b828204905092915050565b600061573a82614c7a565b915061574583614c7a565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561577e5761577d6156cf565b5b828202905092915050565b600061579482614c7a565b915061579f83614c7a565b9250828210156157b2576157b16156cf565b5b828203905092915050565b60006040820190506157d26000830185614d94565b6157df6020830184614cef565b9392505050565b60006157f182614c7a565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415615824576158236156cf565b5b600182019050919050565b600080fd5b6000615840838561505b565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156158735761587261582f565b5b6020830292506158848385846151e6565b82840190509392505050565b600060208201905081810360008301526158ab818486615834565b90509392505050565b600080fd5b600080fd5b600080fd5b600080833560016020038436030381126158e0576158df6158b4565b5b80840192508235915067ffffffffffffffff821115615902576159016158b9565b5b60208301925060018202360383131561591e5761591d6158be565b5b509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600081905092915050565b600061596c8385615955565b93506159798385846151e6565b82840190509392505050565b6000615992828486615960565b91508190509392505050565b6000819050919050565b6159b18161599e565b82525050565b600060a0820190506159cc6000830188614d94565b6159d96020830187614d94565b6159e66040830186614d94565b6159f36060830185614d94565b615a0060808301846159a8565b9695505050505050565b60008083356001602003843603038112615a2757615a266158b4565b5b80840192508235915067ffffffffffffffff821115615a4957615a486158b9565b5b602083019250600182023603831315615a6557615a646158be565b5b509250929050565b6000819050919050565b6000615a92615a8d615a8884614b34565b615a6d565b614b34565b9050919050565b6000615aa482615a77565b9050919050565b6000615ab682615a99565b9050919050565b615ac681615aab565b82525050565b600081519050919050565b600082825260208201905092915050565b6000615af382615acc565b615afd8185615ad7565b9350615b0d818560208601614bdb565b615b1681614c0e565b840191505092915050565b6000608082019050615b366000830187615abd565b615b436020830186614cef565b615b506040830185614d94565b8181036060830152615b628184615ae8565b905095945050505050565b600081519050615b7c81614aa5565b92915050565b600060208284031215615b9857615b97614a6f565b5b6000615ba684828501615b6d565b91505092915050565b600081905092915050565b7f1901000000000000000000000000000000000000000000000000000000000000600082015250565b6000615bf0600283615baf565b9150615bfb82615bba565b600282019050919050565b6000819050919050565b615c21615c1c8261599e565b615c06565b82525050565b6000615c3282615be3565b9150615c3e8285615c10565b602082019150615c4e8284615c10565b6020820191508190509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b6000615cc3601883614bca565b9150615cce82615c8d565b602082019050919050565b60006020820190508181036000830152615cf281615cb6565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b6000615d2f601f83614bca565b9150615d3a82615cf9565b602082019050919050565b60006020820190508181036000830152615d5e81615d22565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b6000615dc1602283614bca565b9150615dcc82615d65565b604082019050919050565b60006020820190508181036000830152615df081615db4565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202776272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b6000615e53602283614bca565b9150615e5e82615df7565b604082019050919050565b60006020820190508181036000830152615e8281615e46565b9050919050565b600060a082019050615e9e60008301886159a8565b615eab60208301876159a8565b615eb860408301866159a8565b615ec56060830185614d94565b615ed26080830184614cef565b9695505050505050565b600060ff82169050919050565b615ef281615edc565b82525050565b6000608082019050615f0d60008301876159a8565b615f1a6020830186615ee9565b615f2760408301856159a8565b615f3460608301846159a8565b9594505050505056fea264697066735822122041ad50c4c1188e9de974deb052c8e7d9e421db890f696eebe4ac81991c2fd7a264736f6c634300080b0033

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.