Contract 0xd7519ffbfb1f15ef320f5bf7a325aa1020e31988

 

Contract Overview

Balance:
0 MATIC

MATIC Value:
$0.00

Token:
 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xe2e6d61795765a522fb0c85c41ddebb40e21edecfe7f4d58d3ba67883261d6f9Mint Vehicle Sig...339082922022-10-04 5:43:584 hrs 46 mins ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.010048590005 30.000000015
0xf572e6fb721739b041bca7440604d4d4396a3edf704f1115877fa3889cad215aMint Vehicle Sig...338999532022-10-04 0:56:479 hrs 33 mins ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.011188247619 33.403637117
0xcae0aef4db88df4fb95370ad82c89db0ade02f5ec97330fb0d54057ce32764d8Mint Vehicle Sig...338704772022-10-03 7:55:431 day 2 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.010048800005 30.000000015
0xb21e120887e126a3881dd65a3eeebb72f5ccbf6b1f413745ca175f25441e5872Mint Vehicle Sig...338441442022-10-02 16:39:371 day 17 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.010048080005 30.000000015
0xc66d7df71b958e95e141de9f62e9a201d7dd94adefee8091ca768473c02d0b2fMint Vehicle Sig...338166192022-10-02 0:42:462 days 9 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.010297260446 30.742403999
0x59d9ee8c16f2a1f02d60cfcbfb323a2c29ff888aae50de9f8a9a91d32e325ca9Mint Vehicle Sig...338056122022-10-01 18:24:112 days 16 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.010048230004 30.000000013
0x1cc7b7ec7086431ecd4eb8686e284761266a48ea6d26b73286ef7b2f132f829cMint Vehicle Sig...337797862022-10-01 3:28:213 days 7 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.010052760003 30.000000011
0x60c0d499b12601940d937c4fbd87dc55ef845ffd9b521bf027137d2d19272654Mint Vehicle Sig...337290762022-09-29 21:57:194 days 12 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.010048080004 30.000000012
0x08989f4d96ea752452aa8769b5f67136f4cdf90ea8964929702c69f427c4f39fMint Vehicle Sig...337246452022-09-29 19:24:424 days 15 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.010047360004 30.000000013
0xb0727b4df95943a1247052f14fc1efff2d08ac01ce4763fba0408e9492eb7faeMint Vehicle Sig...335998742022-09-26 18:24:397 days 16 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.010050960004 30.000000013
0xbccf7996c962a19843112d22bcf4e7047dfc82b44d1bf6db6b04fc130ff3d9daMint Vehicle Sig...335542452022-09-25 15:44:338 days 18 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.010047870004 30.000000013
0xcd0e9c705d4e618c787c5a406373a09da6e537bc0708d2e569cf73f03c3e8523Mint Vehicle Sig...335274312022-09-25 0:11:089 days 10 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.010046430006 30.000000018
0xde392e0889cde08ad8f8835e77d8ceec2c260d0d4a5bce43ea74bb4a140ad59cMint Vehicle Sig...335208362022-09-24 20:23:569 days 14 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.010049880004 30.000000013
0xe79c1e6220fb831194615947b1f7020be3cb0b53ba45231cb5a803ba3ef726d4Mint Vehicle Sig...335116792022-09-24 15:06:529 days 19 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.009537390004 30.000000014
0x329110fe0155778d48c5eb4543e67153572f804a352e46d9b2e744bcb5a39d25Mint Vehicle Sig...334924402022-09-24 3:53:1510 days 6 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.010047000004 30.000000014
0x125c4672faf97d1ef78c3fde907366b7170e898cb8ae67a2ca8bcf35229d441fMint Vehicle Sig...334797122022-09-23 20:33:3910 days 13 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.01055454973 31.515526217
0x31627ae11dcb8d7631ad2bce28d90a49ca3f62373f2196c269ffdd39f1c34c77Mint Vehicle Sig...334052872022-09-22 1:18:1412 days 9 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.010048080004 30.000000014
0x77bea615219c67cc28171feb2b262d42f1feefed33c44826adb695f3a3946159Mint Vehicle Sig...333997282022-09-21 22:06:4912 days 12 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.01005323696 30.01324624
0x02c52f2dde0d613ab245f06c3aa6f167df563bad5f30cfffd61cce87dab0f4e6Transfer333855282022-09-21 13:52:0612 days 20 hrs ago0xd2cf45d1b19cb60c63b6716879bd059786859b21 IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.000803880053 30.000002001
0x9b7974197665daf3e80f2f4b687e0686ae894c5ea9576dca633847aa6e296938Mint Vehicle Sig...333454972022-09-20 13:46:2613 days 20 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.0100466519 30.000035535
0x72c42063daab056078dc5de732d5b91ced37309c6f589b6916f7a076bb39a214Mint Vehicle Sig...333246092022-09-20 1:28:5014 days 9 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.010048080004 30.000000013
0xe7ec6a443ad5fa013e897110db19ba8091f6c47f3d8616b22b090065e82c75cbMint Vehicle Sig...332805402022-09-19 0:09:0215 days 10 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.012185275924 36.380908367
0xd2441a2a7ab761e8d447f65f76f76637e8fd90de7c5a4357b41e07e1886f540bMint Vehicle Sig...332566662022-09-18 10:14:4716 days 15 mins ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.010047000005 30.000000015
0x3197b8db5e3bb4fefe3034ef6b977d7f331e08f227764ca72b0be019a3a36f4bMint Vehicle Sig...331502542022-09-15 20:27:3318 days 14 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.010049670025 30.000000076
0xedaa3618753ea1211d65de5c08e4a2fc97bd4d8410a3fd5f22a933625342192bMint Vehicle Sig...331447552022-09-15 17:18:2918 days 17 hrs ago0xcce4ef41a67e28c3cf3dbc51a6cd3d004f53acbd IN  0xd7519ffbfb1f15ef320f5bf7a325aa1020e319880 MATIC0.012950673487 38.666921907
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
DIMORegistryBetaV1

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion
File 1 of 26 : DIMORegistry.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.13;

import "./libraries/DIMOStorage.sol";
import "./access/AccessControlInternal.sol";
import "@solidstate/contracts/introspection/ERC165.sol";
import "@solidstate/contracts/token/ERC721/ERC721.sol";
import "@solidstate/contracts/token/ERC721/metadata/IERC721Metadata.sol";
import "@solidstate/contracts/token/ERC721/metadata/ERC721MetadataStorage.sol";

contract DIMORegistryBetaV1 is ERC721, AccessControlInternal {
    using ERC165Storage for ERC165Storage.Layout;

    event ModuleAdded(address indexed moduleAddr, bytes4[] selectors);
    event ModuleRemoved(address indexed moduleAddr, bytes4[] selectors);
    event ModuleUpdated(
        address indexed oldImplementation,
        address indexed newImplementation,
        bytes4[] oldSelectors,
        bytes4[] newSelectors
    );

    constructor(
        string memory _name,
        string memory _symbol,
        string memory __baseURI
    ) {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);

        ERC721MetadataStorage.Layout storage s = ERC721MetadataStorage.layout();
        s.name = _name;
        s.symbol = _symbol;
        s.baseURI = __baseURI;

        ERC165Storage.layout().setSupportedInterface(
            type(IERC165).interfaceId,
            true
        );
        ERC165Storage.layout().setSupportedInterface(
            type(IERC721Metadata).interfaceId,
            true
        );
    }

    /// @notice pass a call to a module
    /* solhint-disable no-complex-fallback, payable-fallback, no-inline-assembly */
    fallback() external {
        address implementation = DIMOStorage.getStorage().implementations[
            msg.sig
        ];
        assembly {
            calldatacopy(0, 0, calldatasize())
            let result := delegatecall(
                gas(),
                implementation,
                0,
                calldatasize(),
                0,
                0
            )
            returndatacopy(0, 0, returndatasize())
            switch result
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    /* solhint-enable no-complex-fallback, payable-fallback, no-inline-assembly */

    /// @notice update module
    /// @dev oldImplementation should be registered
    /// @param oldImplementation address of the module to remove
    /// @param newImplementation address of the module to register
    /// @param oldSelectors old function signatures list
    /// @param newSelectors new function signatures list
    function updateModule(
        address oldImplementation,
        address newImplementation,
        bytes4[] calldata oldSelectors,
        bytes4[] calldata newSelectors
    ) external onlyRole(DEFAULT_ADMIN_ROLE) {
        _removeModule(oldImplementation, oldSelectors);
        _addModule(newImplementation, newSelectors);
        emit ModuleUpdated(
            oldImplementation,
            newImplementation,
            oldSelectors,
            newSelectors
        );
    }

    /// @notice Adds a new module
    /// @dev function selector should not have been registered
    /// @param implementation address of the implementation
    /// @param selectors selectors of the implementation contract
    function addModule(address implementation, bytes4[] calldata selectors)
        external
        onlyRole(DEFAULT_ADMIN_ROLE)
    {
        _addModule(implementation, selectors);
        emit ModuleAdded(implementation, selectors);
    }

    /// @notice Adds a new module and supported functions
    /// @dev function selector should not exist
    /// @param implementation implementation address
    /// @param selectors function signatures
    function removeModule(address implementation, bytes4[] calldata selectors)
        external
        onlyRole(DEFAULT_ADMIN_ROLE)
    {
        _removeModule(implementation, selectors);
        emit ModuleRemoved(implementation, selectors);
    }

    /// @notice Adds a new module
    /// @dev function selector should not have been registered.
    /// @param implementation address of the implementation
    /// @param selectors selectors of the implementation contract
    function _addModule(address implementation, bytes4[] calldata selectors)
        private
    {
        DIMOStorage.Storage storage s = DIMOStorage.getStorage();
        require(
            s.selectorsHash[implementation] == 0x0,
            "Implementation already exists"
        );

        for (uint256 i = 0; i < selectors.length; i++) {
            require(
                s.implementations[selectors[i]] == address(0),
                "Selector already registered"
            );
            s.implementations[selectors[i]] = implementation;
        }
        bytes32 hash = keccak256(abi.encode(selectors));
        s.selectorsHash[implementation] = hash;
    }

    /// @notice Adds a new module and supported functions
    /// @dev function selector should not exist
    /// @param implementation implementation address
    /// @param selectors function signatures
    function _removeModule(address implementation, bytes4[] calldata selectors)
        private
    {
        DIMOStorage.Storage storage s = DIMOStorage.getStorage();
        bytes32 hash = keccak256(abi.encode(selectors));
        require(
            s.selectorsHash[implementation] == hash,
            "Invalid selector list"
        );

        for (uint256 i = 0; i < selectors.length; i++) {
            require(
                s.implementations[selectors[i]] == implementation,
                "Unregistered selector"
            );
            s.implementations[selectors[i]] = address(0);
        }
    }
}

File 2 of 26 : DIMOStorage.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.13;

library DIMOStorage {
    bytes32 internal constant DIMO_REGISTRY_STORAGE_SLOT =
        keccak256("DIMORegistry.storage");

    struct Node {
        uint256 nodeType;
        uint256 parentNode;
        mapping(string => string) info;
    }

    struct Storage {
        address admin;
        // Maps function selectors to the implementations that execute the functions
        mapping(bytes4 => address) implementations;
        // Maps the implementation to the hash of all its selectors
        // implementation => keccak256(abi.encode(selectors))
        mapping(address => bytes32) selectorsHash;
        // [Node id] => Node info
        mapping(uint256 => Node) nodes;
        uint256 currentIndex;
    }

    /* solhint-disable no-inline-assembly */
    function getStorage() internal pure returns (Storage storage s) {
        bytes32 slot = DIMO_REGISTRY_STORAGE_SLOT;
        assembly {
            s.slot := slot
        }
    }
    /* solhint-enable no-inline-assembly */
}

File 3 of 26 : AccessControlInternal.sol
// SPDX-License-Identifier: Unlicensed
pragma solidity ^0.8.13;

import {AccessControlStorage} from "./AccessControlStorage.sol";
import {IAccessControlInternal} from "./IAccessControlInternal.sol";
import {UintUtils} from "@solidstate/contracts/utils/UintUtils.sol";
import {AddressUtils} from "@solidstate/contracts/utils/AddressUtils.sol";

contract AccessControlInternal is IAccessControlInternal {
    using AccessControlStorage for AccessControlStorage.Storage;
    using AddressUtils for address;
    using UintUtils for uint256;

    bytes32 internal constant DEFAULT_ADMIN_ROLE = 0x00;

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

    /**
     * @notice query if account's has role
     * @param role role to query
     * @param account account to query
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function _hasRole(bytes32 role, address account)
        internal
        view
        virtual
        returns (bool)
    {
        return AccessControlStorage.getStorage().roles[role].members[account];
    }

    /**
     * @notice query role by msg.sender
     * @param role role to query
     * @dev Revert with a standard message if `msg.sender` is missing `role`.
     * Overriding this function changes the behavior of the {onlyRole} modifier.
     *
     * Format of the revert message is described in {_checkRole}.
     *
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, msg.sender);
    }

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

    /**
     * @notice query admin role
     * @param role role to query
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function _getRoleAdmin(bytes32 role)
        internal
        view
        virtual
        returns (bytes32)
    {
        return AccessControlStorage.getStorage().roles[role].adminRole;
    }

    /**
     * @notice set role as admin role
     * @param role role to set
     * @param adminRole admin role to set
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = _getRoleAdmin(role);
        AccessControlStorage.getStorage().roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @notice grant role to account
     * @param role role to grant
     * @param account account to grant the role
     * @dev Grants `role` to `account`.
     *
     *  * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * Internal function without access restriction.
     */
    function _grantRole(bytes32 role, address account) internal virtual {
        if (!_hasRole(role, account)) {
            AccessControlStorage.getStorage().roles[role].members[
                account
            ] = true;
            emit RoleGranted(role, account, msg.sender);
        }
    }

    /**
     * @notice revoke role from account
     * @param role role to revoke
     * @param account account to revoke the role
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * Internal function without access restriction.
     */
    function _revokeRole(bytes32 role, address account) internal virtual {
        if (_hasRole(role, account)) {
            AccessControlStorage.getStorage().roles[role].members[
                account
            ] = false;
            emit RoleRevoked(role, account, msg.sender);
        }
    }
}

File 4 of 26 : ERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC165 } from './IERC165.sol';
import { ERC165Storage } from './ERC165Storage.sol';

/**
 * @title ERC165 implementation
 */
abstract contract ERC165 is IERC165 {
    using ERC165Storage for ERC165Storage.Layout;

    /**
     * @inheritdoc IERC165
     */
    function supportsInterface(bytes4 interfaceId) public view returns (bool) {
        return ERC165Storage.layout().isSupportedInterface(interfaceId);
    }
}

File 5 of 26 : ERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { ERC721Base, ERC721BaseInternal } from './base/ERC721Base.sol';
import { ERC721Enumerable } from './enumerable/ERC721Enumerable.sol';
import { ERC721Metadata } from './metadata/ERC721Metadata.sol';
import { ERC165 } from '../../introspection/ERC165.sol';

/**
 * @title SolidState ERC721 implementation, including recommended extensions
 */
abstract contract ERC721 is
    ERC721Base,
    ERC721Enumerable,
    ERC721Metadata,
    ERC165
{
    /**
     * @notice ERC721 hook: revert if value is included in external approve function call
     * @inheritdoc ERC721BaseInternal
     */
    function _handleApproveMessageValue(
        address operator,
        uint256 tokenId,
        uint256 value
    ) internal virtual override {
        require(value == 0, 'ERC721: payable approve calls not supported');
        super._handleApproveMessageValue(operator, tokenId, value);
    }

    /**
     * @notice ERC721 hook: revert if value is included in external transfer function call
     * @inheritdoc ERC721BaseInternal
     */
    function _handleTransferMessageValue(
        address from,
        address to,
        uint256 tokenId,
        uint256 value
    ) internal virtual override {
        require(value == 0, 'ERC721: payable transfer calls not supported');
        super._handleTransferMessageValue(from, to, tokenId, value);
    }

    /**
     * @inheritdoc ERC721BaseInternal
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override(ERC721BaseInternal, ERC721Metadata) {
        super._beforeTokenTransfer(from, to, tokenId);
    }
}

File 6 of 26 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title ERC721Metadata interface
 */
interface IERC721Metadata {
    /**
     * @notice get token name
     * @return token name
     */
    function name() external view returns (string memory);

    /**
     * @notice get token symbol
     * @return token symbol
     */
    function symbol() external view returns (string memory);

    /**
     * @notice get generated URI for given token
     * @return token URI
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

File 7 of 26 : ERC721MetadataStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

library ERC721MetadataStorage {
    bytes32 internal constant STORAGE_SLOT =
        keccak256('solidstate.contracts.storage.ERC721Metadata');

    struct Layout {
        string name;
        string symbol;
        string baseURI;
        mapping(uint256 => string) tokenURIs;
    }

    function layout() internal pure returns (Layout storage l) {
        bytes32 slot = STORAGE_SLOT;
        assembly {
            l.slot := slot
        }
    }
}

File 8 of 26 : AccessControlStorage.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.13;

library AccessControlStorage {
    bytes32 internal constant ACCESS_CONTROL_STORAGE_SLOT =
        keccak256("DIMORegistry.accessControl.storage");

    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    struct Storage {
        mapping(bytes32 => RoleData) roles;
    }

    /* solhint-disable no-inline-assembly */
    function getStorage() internal pure returns (Storage storage s) {
        bytes32 slot = ACCESS_CONTROL_STORAGE_SLOT;
        assembly {
            s.slot := slot
        }
    }
    /* solhint-enable no-inline-assembly */
}

File 9 of 26 : IAccessControlInternal.sol
// SPDX-License-Identifier: Unlicensed
// From OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)

pragma solidity ^0.8.13;

/**
 * @title Partial AccessControl interface needed by internal functions
 */
interface IAccessControlInternal {
    /**
     * @notice Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     */
    event RoleAdminChanged(
        bytes32 indexed role,
        bytes32 indexed previousAdminRole,
        bytes32 indexed newAdminRole
    );

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

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

File 10 of 26 : UintUtils.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title utility functions for uint256 operations
 * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts/ (MIT license)
 */
library UintUtils {
    bytes16 private constant HEX_SYMBOLS = '0123456789abcdef';

    function toString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return '0';
        }

        uint256 temp = value;
        uint256 digits;

        while (temp != 0) {
            digits++;
            temp /= 10;
        }

        bytes memory buffer = new bytes(digits);

        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }

        return string(buffer);
    }

    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return '0x00';
        }

        uint256 length = 0;

        for (uint256 temp = value; temp != 0; temp >>= 8) {
            unchecked {
                length++;
            }
        }

        return toHexString(value, length);
    }

    function toHexString(uint256 value, uint256 length)
        internal
        pure
        returns (string memory)
    {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = '0';
        buffer[1] = 'x';

        unchecked {
            for (uint256 i = 2 * length + 1; i > 1; --i) {
                buffer[i] = HEX_SYMBOLS[value & 0xf];
                value >>= 4;
            }
        }

        require(value == 0, 'UintUtils: hex length insufficient');

        return string(buffer);
    }
}

File 11 of 26 : AddressUtils.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { UintUtils } from './UintUtils.sol';

library AddressUtils {
    using UintUtils for uint256;

    function toString(address account) internal pure returns (string memory) {
        return uint256(uint160(account)).toHexString(20);
    }

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

    function sendValue(address payable account, uint256 amount) internal {
        (bool success, ) = account.call{ value: amount }('');
        require(success, 'AddressUtils: failed to send value');
    }

    function functionCall(address target, bytes memory data)
        internal
        returns (bytes memory)
    {
        return
            functionCall(target, data, 'AddressUtils: failed low-level call');
    }

    function functionCall(
        address target,
        bytes memory data,
        string memory error
    ) internal returns (bytes memory) {
        return _functionCallWithValue(target, data, 0, error);
    }

    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return
            functionCallWithValue(
                target,
                data,
                value,
                'AddressUtils: failed low-level call with value'
            );
    }

    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory error
    ) internal returns (bytes memory) {
        require(
            address(this).balance >= value,
            'AddressUtils: insufficient balance for call'
        );
        return _functionCallWithValue(target, data, value, error);
    }

    function _functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory error
    ) private returns (bytes memory) {
        require(
            isContract(target),
            'AddressUtils: function call to non-contract'
        );

        (bool success, bytes memory returnData) = target.call{ value: value }(
            data
        );

        if (success) {
            return returnData;
        } else if (returnData.length > 0) {
            assembly {
                let returnData_size := mload(returnData)
                revert(add(32, returnData), returnData_size)
            }
        } else {
            revert(error);
        }
    }
}

File 12 of 26 : IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title ERC165 interface registration interface
 * @dev see https://eips.ethereum.org/EIPS/eip-165
 */
interface IERC165 {
    /**
     * @notice query whether contract has registered support for given interface
     * @param interfaceId interface id
     * @return bool whether interface is supported
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 13 of 26 : ERC165Storage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

library ERC165Storage {
    struct Layout {
        mapping(bytes4 => bool) supportedInterfaces;
    }

    bytes32 internal constant STORAGE_SLOT =
        keccak256('solidstate.contracts.storage.ERC165');

    function layout() internal pure returns (Layout storage l) {
        bytes32 slot = STORAGE_SLOT;
        assembly {
            l.slot := slot
        }
    }

    function isSupportedInterface(Layout storage l, bytes4 interfaceId)
        internal
        view
        returns (bool)
    {
        return l.supportedInterfaces[interfaceId];
    }

    function setSupportedInterface(
        Layout storage l,
        bytes4 interfaceId,
        bool status
    ) internal {
        require(interfaceId != 0xffffffff, 'ERC165: invalid interface id');
        l.supportedInterfaces[interfaceId] = status;
    }
}

File 14 of 26 : ERC721Base.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { AddressUtils } from '../../../utils/AddressUtils.sol';
import { EnumerableMap } from '../../../utils/EnumerableMap.sol';
import { EnumerableSet } from '../../../utils/EnumerableSet.sol';
import { IERC721 } from '../IERC721.sol';
import { IERC721Receiver } from '../IERC721Receiver.sol';
import { ERC721BaseStorage } from './ERC721BaseStorage.sol';
import { ERC721BaseInternal } from './ERC721BaseInternal.sol';

/**
 * @title Base ERC721 implementation, excluding optional extensions
 */
abstract contract ERC721Base is IERC721, ERC721BaseInternal {
    using AddressUtils for address;
    using EnumerableMap for EnumerableMap.UintToAddressMap;
    using EnumerableSet for EnumerableSet.UintSet;

    /**
     * @inheritdoc IERC721
     */
    function balanceOf(address account) public view returns (uint256) {
        return _balanceOf(account);
    }

    /**
     * @inheritdoc IERC721
     */
    function ownerOf(uint256 tokenId) public view returns (address) {
        return _ownerOf(tokenId);
    }

    /**
     * @inheritdoc IERC721
     */
    function getApproved(uint256 tokenId) public view returns (address) {
        return _getApproved(tokenId);
    }

    /**
     * @inheritdoc IERC721
     */
    function isApprovedForAll(address account, address operator)
        public
        view
        returns (bool)
    {
        return _isApprovedForAll(account, operator);
    }

    /**
     * @inheritdoc IERC721
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public payable {
        _handleTransferMessageValue(from, to, tokenId, msg.value);
        require(
            _isApprovedOrOwner(msg.sender, tokenId),
            'ERC721: transfer caller is not owner or approved'
        );
        _transfer(from, to, tokenId);
    }

    /**
     * @inheritdoc IERC721
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public payable {
        safeTransferFrom(from, to, tokenId, '');
    }

    /**
     * @inheritdoc IERC721
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) public payable {
        _handleTransferMessageValue(from, to, tokenId, msg.value);
        require(
            _isApprovedOrOwner(msg.sender, tokenId),
            'ERC721: transfer caller is not owner or approved'
        );
        _safeTransfer(from, to, tokenId, data);
    }

    /**
     * @inheritdoc IERC721
     */
    function approve(address operator, uint256 tokenId) public payable {
        _handleApproveMessageValue(operator, tokenId, msg.value);
        address owner = ownerOf(tokenId);
        require(operator != owner, 'ERC721: approval to current owner');
        require(
            msg.sender == owner || isApprovedForAll(owner, msg.sender),
            'ERC721: approve caller is not owner nor approved for all'
        );
        _approve(operator, tokenId);
    }

    /**
     * @inheritdoc IERC721
     */
    function setApprovalForAll(address operator, bool status) public {
        require(operator != msg.sender, 'ERC721: approve to caller');
        ERC721BaseStorage.layout().operatorApprovals[msg.sender][
            operator
        ] = status;
        emit ApprovalForAll(msg.sender, operator, status);
    }
}

File 15 of 26 : ERC721Enumerable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { EnumerableMap } from '../../../utils/EnumerableMap.sol';
import { EnumerableSet } from '../../../utils/EnumerableSet.sol';
import { ERC721BaseStorage } from '../base/ERC721BaseStorage.sol';
import { IERC721Enumerable } from './IERC721Enumerable.sol';
import { ERC721EnumerableInternal } from './ERC721EnumerableInternal.sol';

abstract contract ERC721Enumerable is
    IERC721Enumerable,
    ERC721EnumerableInternal
{
    using EnumerableMap for EnumerableMap.UintToAddressMap;
    using EnumerableSet for EnumerableSet.UintSet;

    /**
     * @inheritdoc IERC721Enumerable
     */
    function totalSupply() public view returns (uint256) {
        return _totalSupply();
    }

    /**
     * @inheritdoc IERC721Enumerable
     */
    function tokenOfOwnerByIndex(address owner, uint256 index)
        public
        view
        returns (uint256)
    {
        return _tokenOfOwnerByIndex(owner, index);
    }

    /**
     * @inheritdoc IERC721Enumerable
     */
    function tokenByIndex(uint256 index) public view returns (uint256) {
        return _tokenByIndex(index);
    }
}

File 16 of 26 : ERC721Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { UintUtils } from '../../../utils/UintUtils.sol';
import { ERC721BaseInternal, ERC721BaseStorage } from '../base/ERC721Base.sol';
import { ERC721MetadataStorage } from './ERC721MetadataStorage.sol';
import { ERC721MetadataInternal } from './ERC721MetadataInternal.sol';
import { IERC721Metadata } from './IERC721Metadata.sol';

/**
 * @title ERC721 metadata extensions
 */
abstract contract ERC721Metadata is IERC721Metadata, ERC721MetadataInternal {
    using ERC721BaseStorage for ERC721BaseStorage.Layout;
    using UintUtils for uint256;

    /**
     * @notice inheritdoc IERC721Metadata
     */
    function name() public view virtual returns (string memory) {
        return ERC721MetadataStorage.layout().name;
    }

    /**
     * @notice inheritdoc IERC721Metadata
     */
    function symbol() public view virtual returns (string memory) {
        return ERC721MetadataStorage.layout().symbol;
    }

    /**
     * @notice inheritdoc IERC721Metadata
     */
    function tokenURI(uint256 tokenId)
        public
        view
        virtual
        returns (string memory)
    {
        require(
            ERC721BaseStorage.layout().exists(tokenId),
            'ERC721Metadata: URI query for nonexistent token'
        );

        ERC721MetadataStorage.Layout storage l = ERC721MetadataStorage.layout();

        string memory tokenIdURI = l.tokenURIs[tokenId];
        string memory baseURI = l.baseURI;

        if (bytes(baseURI).length == 0) {
            return tokenIdURI;
        } else if (bytes(tokenIdURI).length > 0) {
            return string(abi.encodePacked(baseURI, tokenIdURI));
        } else {
            return string(abi.encodePacked(baseURI, tokenId.toString()));
        }
    }

    /**
     * @inheritdoc ERC721MetadataInternal
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, tokenId);
    }
}

File 17 of 26 : EnumerableMap.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title Map implementation with enumeration functions
 * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license)
 */
library EnumerableMap {
    struct MapEntry {
        bytes32 _key;
        bytes32 _value;
    }

    struct Map {
        MapEntry[] _entries;
        // 1-indexed to allow 0 to signify nonexistence
        mapping(bytes32 => uint256) _indexes;
    }

    struct AddressToAddressMap {
        Map _inner;
    }

    struct UintToAddressMap {
        Map _inner;
    }

    function at(AddressToAddressMap storage map, uint256 index)
        internal
        view
        returns (address, address)
    {
        (bytes32 key, bytes32 value) = _at(map._inner, index);
        address addressKey;
        assembly {
            addressKey := mload(add(key, 20))
        }
        return (addressKey, address(uint160(uint256(value))));
    }

    function at(UintToAddressMap storage map, uint256 index)
        internal
        view
        returns (uint256, address)
    {
        (bytes32 key, bytes32 value) = _at(map._inner, index);
        return (uint256(key), address(uint160(uint256(value))));
    }

    function contains(AddressToAddressMap storage map, address key)
        internal
        view
        returns (bool)
    {
        return _contains(map._inner, bytes32(uint256(uint160(key))));
    }

    function contains(UintToAddressMap storage map, uint256 key)
        internal
        view
        returns (bool)
    {
        return _contains(map._inner, bytes32(key));
    }

    function length(AddressToAddressMap storage map)
        internal
        view
        returns (uint256)
    {
        return _length(map._inner);
    }

    function length(UintToAddressMap storage map)
        internal
        view
        returns (uint256)
    {
        return _length(map._inner);
    }

    function get(AddressToAddressMap storage map, address key)
        internal
        view
        returns (address)
    {
        return
            address(
                uint160(
                    uint256(_get(map._inner, bytes32(uint256(uint160(key)))))
                )
            );
    }

    function get(UintToAddressMap storage map, uint256 key)
        internal
        view
        returns (address)
    {
        return address(uint160(uint256(_get(map._inner, bytes32(key)))));
    }

    function set(
        AddressToAddressMap storage map,
        address key,
        address value
    ) internal returns (bool) {
        return
            _set(
                map._inner,
                bytes32(uint256(uint160(key))),
                bytes32(uint256(uint160(value)))
            );
    }

    function set(
        UintToAddressMap storage map,
        uint256 key,
        address value
    ) internal returns (bool) {
        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
    }

    function remove(AddressToAddressMap storage map, address key)
        internal
        returns (bool)
    {
        return _remove(map._inner, bytes32(uint256(uint160(key))));
    }

    function remove(UintToAddressMap storage map, uint256 key)
        internal
        returns (bool)
    {
        return _remove(map._inner, bytes32(key));
    }

    function _at(Map storage map, uint256 index)
        private
        view
        returns (bytes32, bytes32)
    {
        require(
            map._entries.length > index,
            'EnumerableMap: index out of bounds'
        );

        MapEntry storage entry = map._entries[index];
        return (entry._key, entry._value);
    }

    function _contains(Map storage map, bytes32 key)
        private
        view
        returns (bool)
    {
        return map._indexes[key] != 0;
    }

    function _length(Map storage map) private view returns (uint256) {
        return map._entries.length;
    }

    function _get(Map storage map, bytes32 key) private view returns (bytes32) {
        uint256 keyIndex = map._indexes[key];
        require(keyIndex != 0, 'EnumerableMap: nonexistent key');
        unchecked {
            return map._entries[keyIndex - 1]._value;
        }
    }

    function _set(
        Map storage map,
        bytes32 key,
        bytes32 value
    ) private returns (bool) {
        uint256 keyIndex = map._indexes[key];

        if (keyIndex == 0) {
            map._entries.push(MapEntry({ _key: key, _value: value }));
            map._indexes[key] = map._entries.length;
            return true;
        } else {
            unchecked {
                map._entries[keyIndex - 1]._value = value;
            }
            return false;
        }
    }

    function _remove(Map storage map, bytes32 key) private returns (bool) {
        uint256 keyIndex = map._indexes[key];

        if (keyIndex != 0) {
            unchecked {
                MapEntry storage last = map._entries[map._entries.length - 1];

                // move last entry to now-vacant index
                map._entries[keyIndex - 1] = last;
                map._indexes[last._key] = keyIndex;
            }

            // clear last index
            map._entries.pop();
            delete map._indexes[key];

            return true;
        } else {
            return false;
        }
    }
}

File 18 of 26 : EnumerableSet.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title Set implementation with enumeration functions
 * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license)
 */
library EnumerableSet {
    struct Set {
        bytes32[] _values;
        // 1-indexed to allow 0 to signify nonexistence
        mapping(bytes32 => uint256) _indexes;
    }

    struct Bytes32Set {
        Set _inner;
    }

    struct AddressSet {
        Set _inner;
    }

    struct UintSet {
        Set _inner;
    }

    function at(Bytes32Set storage set, uint256 index)
        internal
        view
        returns (bytes32)
    {
        return _at(set._inner, index);
    }

    function at(AddressSet storage set, uint256 index)
        internal
        view
        returns (address)
    {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    function at(UintSet storage set, uint256 index)
        internal
        view
        returns (uint256)
    {
        return uint256(_at(set._inner, index));
    }

    function contains(Bytes32Set storage set, bytes32 value)
        internal
        view
        returns (bool)
    {
        return _contains(set._inner, value);
    }

    function contains(AddressSet storage set, address value)
        internal
        view
        returns (bool)
    {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    function contains(UintSet storage set, uint256 value)
        internal
        view
        returns (bool)
    {
        return _contains(set._inner, bytes32(value));
    }

    function indexOf(Bytes32Set storage set, bytes32 value)
        internal
        view
        returns (uint256)
    {
        return _indexOf(set._inner, value);
    }

    function indexOf(AddressSet storage set, address value)
        internal
        view
        returns (uint256)
    {
        return _indexOf(set._inner, bytes32(uint256(uint160(value))));
    }

    function indexOf(UintSet storage set, uint256 value)
        internal
        view
        returns (uint256)
    {
        return _indexOf(set._inner, bytes32(value));
    }

    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    function add(Bytes32Set storage set, bytes32 value)
        internal
        returns (bool)
    {
        return _add(set._inner, value);
    }

    function add(AddressSet storage set, address value)
        internal
        returns (bool)
    {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    function remove(Bytes32Set storage set, bytes32 value)
        internal
        returns (bool)
    {
        return _remove(set._inner, value);
    }

    function remove(AddressSet storage set, address value)
        internal
        returns (bool)
    {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    function remove(UintSet storage set, uint256 value)
        internal
        returns (bool)
    {
        return _remove(set._inner, bytes32(value));
    }

    function _at(Set storage set, uint256 index)
        private
        view
        returns (bytes32)
    {
        require(
            set._values.length > index,
            'EnumerableSet: index out of bounds'
        );
        return set._values[index];
    }

    function _contains(Set storage set, bytes32 value)
        private
        view
        returns (bool)
    {
        return set._indexes[value] != 0;
    }

    function _indexOf(Set storage set, bytes32 value)
        private
        view
        returns (uint256)
    {
        unchecked {
            return set._indexes[value] - 1;
        }
    }

    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    function _remove(Set storage set, bytes32 value) private returns (bool) {
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) {
            unchecked {
                bytes32 last = set._values[set._values.length - 1];

                // move last value to now-vacant index

                set._values[valueIndex - 1] = last;
                set._indexes[last] = valueIndex;
            }
            // clear last index

            set._values.pop();
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }
}

File 19 of 26 : IERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC165 } from '../../introspection/IERC165.sol';
import { IERC721Internal } from './IERC721Internal.sol';

/**
 * @title ERC721 interface
 * @dev see https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721 is IERC721Internal, IERC165 {
    /**
     * @notice query the balance of given address
     * @return balance quantity of tokens held
     */
    function balanceOf(address account) external view returns (uint256 balance);

    /**
     * @notice query the owner of given token
     * @param tokenId token to query
     * @return owner token owner
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @notice transfer token between given addresses, checking for ERC721Receiver implementation if applicable
     * @param from sender of token
     * @param to receiver of token
     * @param tokenId token id
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external payable;

    /**
     * @notice transfer token between given addresses, checking for ERC721Receiver implementation if applicable
     * @param from sender of token
     * @param to receiver of token
     * @param tokenId token id
     * @param data data payload
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external payable;

    /**
     * @notice transfer token between given addresses, without checking for ERC721Receiver implementation if applicable
     * @param from sender of token
     * @param to receiver of token
     * @param tokenId token id
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external payable;

    /**
     * @notice grant approval to given account to spend token
     * @param operator address to be approved
     * @param tokenId token to approve
     */
    function approve(address operator, uint256 tokenId) external payable;

    /**
     * @notice get approval status for given token
     * @param tokenId token to query
     * @return operator address approved to spend token
     */
    function getApproved(uint256 tokenId)
        external
        view
        returns (address operator);

    /**
     * @notice grant approval to or revoke approval from given account to spend all tokens held by sender
     * @param operator address to be approved
     * @param status approval status
     */
    function setApprovalForAll(address operator, bool status) external;

    /**
     * @notice query approval status of given operator with respect to given address
     * @param account address to query for approval granted
     * @param operator address to query for approval received
     * @return status whether operator is approved to spend tokens held by account
     */
    function isApprovedForAll(address account, address operator)
        external
        view
        returns (bool status);
}

File 20 of 26 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IERC721Receiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

File 21 of 26 : ERC721BaseStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { EnumerableMap } from '../../../utils/EnumerableMap.sol';
import { EnumerableSet } from '../../../utils/EnumerableSet.sol';

library ERC721BaseStorage {
    using EnumerableSet for EnumerableSet.UintSet;
    using EnumerableMap for EnumerableMap.UintToAddressMap;

    bytes32 internal constant STORAGE_SLOT =
        keccak256('solidstate.contracts.storage.ERC721Base');

    struct Layout {
        EnumerableMap.UintToAddressMap tokenOwners;
        mapping(address => EnumerableSet.UintSet) holderTokens;
        mapping(uint256 => address) tokenApprovals;
        mapping(address => mapping(address => bool)) operatorApprovals;
    }

    function layout() internal pure returns (Layout storage l) {
        bytes32 slot = STORAGE_SLOT;
        assembly {
            l.slot := slot
        }
    }

    function exists(Layout storage l, uint256 tokenId)
        internal
        view
        returns (bool)
    {
        return l.tokenOwners.contains(tokenId);
    }

    function totalSupply(Layout storage l) internal view returns (uint256) {
        return l.tokenOwners.length();
    }

    function tokenOfOwnerByIndex(
        Layout storage l,
        address owner,
        uint256 index
    ) internal view returns (uint256) {
        return l.holderTokens[owner].at(index);
    }

    function tokenByIndex(Layout storage l, uint256 index)
        internal
        view
        returns (uint256)
    {
        (uint256 tokenId, ) = l.tokenOwners.at(index);
        return tokenId;
    }
}

File 22 of 26 : ERC721BaseInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { AddressUtils } from '../../../utils/AddressUtils.sol';
import { EnumerableMap } from '../../../utils/EnumerableMap.sol';
import { EnumerableSet } from '../../../utils/EnumerableSet.sol';
import { IERC721Internal } from '../IERC721Internal.sol';
import { IERC721Receiver } from '../IERC721Receiver.sol';
import { ERC721BaseStorage } from './ERC721BaseStorage.sol';

/**
 * @title Base ERC721 internal functions
 */
abstract contract ERC721BaseInternal is IERC721Internal {
    using ERC721BaseStorage for ERC721BaseStorage.Layout;
    using AddressUtils for address;
    using EnumerableMap for EnumerableMap.UintToAddressMap;
    using EnumerableSet for EnumerableSet.UintSet;

    function _balanceOf(address account) internal view returns (uint256) {
        require(
            account != address(0),
            'ERC721: balance query for the zero address'
        );
        return ERC721BaseStorage.layout().holderTokens[account].length();
    }

    function _ownerOf(uint256 tokenId) internal view returns (address) {
        address owner = ERC721BaseStorage.layout().tokenOwners.get(tokenId);
        require(owner != address(0), 'ERC721: invalid owner');
        return owner;
    }

    function _getApproved(uint256 tokenId) internal view returns (address) {
        ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout();

        require(
            l.exists(tokenId),
            'ERC721: approved query for nonexistent token'
        );

        return l.tokenApprovals[tokenId];
    }

    function _isApprovedForAll(address account, address operator)
        internal
        view
        returns (bool)
    {
        return ERC721BaseStorage.layout().operatorApprovals[account][operator];
    }

    function _isApprovedOrOwner(address spender, uint256 tokenId)
        internal
        view
        returns (bool)
    {
        require(
            ERC721BaseStorage.layout().exists(tokenId),
            'ERC721: query for nonexistent token'
        );

        address owner = _ownerOf(tokenId);

        return (spender == owner ||
            _getApproved(tokenId) == spender ||
            _isApprovedForAll(owner, spender));
    }

    function _mint(address to, uint256 tokenId) internal {
        require(to != address(0), 'ERC721: mint to the zero address');

        ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout();

        require(!l.exists(tokenId), 'ERC721: token already minted');

        _beforeTokenTransfer(address(0), to, tokenId);

        l.holderTokens[to].add(tokenId);
        l.tokenOwners.set(tokenId, to);

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

    function _safeMint(address to, uint256 tokenId) internal {
        _safeMint(to, tokenId, '');
    }

    function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal {
        _mint(to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, data),
            'ERC721: transfer to non ERC721Receiver implementer'
        );
    }

    function _burn(uint256 tokenId) internal {
        address owner = _ownerOf(tokenId);

        _beforeTokenTransfer(owner, address(0), tokenId);

        _approve(address(0), tokenId);

        ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout();
        l.holderTokens[owner].remove(tokenId);
        l.tokenOwners.remove(tokenId);

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

    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal {
        require(
            _ownerOf(tokenId) == from,
            'ERC721: transfer of token that is not own'
        );
        require(to != address(0), 'ERC721: transfer to the zero address');

        _beforeTokenTransfer(from, to, tokenId);

        _approve(address(0), tokenId);

        ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout();
        l.holderTokens[from].remove(tokenId);
        l.holderTokens[to].add(tokenId);
        l.tokenOwners.set(tokenId, to);

        emit Transfer(from, to, tokenId);
    }

    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal {
        _transfer(from, to, tokenId);
        require(
            _checkOnERC721Received(from, to, tokenId, data),
            'ERC721: transfer to non ERC721Receiver implementer'
        );
    }

    function _approve(address operator, uint256 tokenId) internal {
        ERC721BaseStorage.layout().tokenApprovals[tokenId] = operator;
        emit Approval(_ownerOf(tokenId), operator, tokenId);
    }

    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal returns (bool) {
        if (!to.isContract()) {
            return true;
        }

        bytes memory returnData = to.functionCall(
            abi.encodeWithSelector(
                IERC721Receiver(to).onERC721Received.selector,
                msg.sender,
                from,
                tokenId,
                data
            ),
            'ERC721: transfer to non ERC721Receiver implementer'
        );

        bytes4 returnValue = abi.decode(returnData, (bytes4));
        return returnValue == type(IERC721Receiver).interfaceId;
    }

    /**
     * @notice ERC721 hook, called before externally called approvals for processing of included message value
     * @param operator beneficiary of approval
     * @param tokenId id of transferred token
     * @param value message value
     */
    function _handleApproveMessageValue(
        address operator,
        uint256 tokenId,
        uint256 value
    ) internal virtual {}

    /**
     * @notice ERC721 hook, called before externally called transfers for processing of included message value
     * @param from sender of token
     * @param to receiver of token
     * @param tokenId id of transferred token
     * @param value message value
     */
    function _handleTransferMessageValue(
        address from,
        address to,
        uint256 tokenId,
        uint256 value
    ) internal virtual {}

    /**
     * @notice ERC721 hook, called before all transfers including mint and burn
     * @dev function should be overridden and new implementation must call super
     * @param from sender of token
     * @param to receiver of token
     * @param tokenId id of transferred token
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}
}

File 23 of 26 : IERC721Internal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title Partial ERC721 interface needed by internal functions
 */
interface IERC721Internal {
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId
    );

    event Approval(
        address indexed owner,
        address indexed operator,
        uint256 indexed tokenId
    );

    event ApprovalForAll(
        address indexed owner,
        address indexed operator,
        bool approved
    );
}

File 24 of 26 : IERC721Enumerable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IERC721Enumerable {
    /**
     * @notice get total token supply
     * @return total supply
     */
    function totalSupply() external view returns (uint256);

    /**
     * @notice get token of given owner at given internal storage index
     * @param owner token holder to query
     * @param index position in owner's token list to query
     * @return tokenId id of retrieved token
     */
    function tokenOfOwnerByIndex(address owner, uint256 index)
        external
        view
        returns (uint256 tokenId);

    /**
     * @notice get token at given internal storage index
     * @param index position in global token list to query
     * @return tokenId id of retrieved token
     */
    function tokenByIndex(uint256 index)
        external
        view
        returns (uint256 tokenId);
}

File 25 of 26 : ERC721EnumerableInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { ERC721BaseStorage } from '../base/ERC721BaseStorage.sol';

abstract contract ERC721EnumerableInternal {
    using ERC721BaseStorage for ERC721BaseStorage.Layout;

    /**
     * @notice TODO
     */
    function _totalSupply() internal view returns (uint256) {
        return ERC721BaseStorage.layout().totalSupply();
    }

    /**
     * @notice TODO
     */
    function _tokenOfOwnerByIndex(address owner, uint256 index)
        internal
        view
        returns (uint256)
    {
        return ERC721BaseStorage.layout().tokenOfOwnerByIndex(owner, index);
    }

    /**
     * @notice TODO
     */
    function _tokenByIndex(uint256 index) internal view returns (uint256) {
        return ERC721BaseStorage.layout().tokenByIndex(index);
    }
}

File 26 of 26 : ERC721MetadataInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { ERC721BaseInternal } from '../base/ERC721Base.sol';
import { ERC721MetadataStorage } from './ERC721MetadataStorage.sol';

/**
 * @title ERC721Metadata internal functions
 */
abstract contract ERC721MetadataInternal is ERC721BaseInternal {
    /**
     * @notice ERC721 hook: clear per-token URI data on burn
     * @inheritdoc ERC721BaseInternal
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, tokenId);

        if (to == address(0)) {
            delete ERC721MetadataStorage.layout().tokenURIs[tokenId];
        }
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"string","name":"__baseURI","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","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":"address","name":"moduleAddr","type":"address"},{"indexed":false,"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"name":"ModuleAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"moduleAddr","type":"address"},{"indexed":false,"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"name":"ModuleRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldImplementation","type":"address"},{"indexed":true,"internalType":"address","name":"newImplementation","type":"address"},{"indexed":false,"internalType":"bytes4[]","name":"oldSelectors","type":"bytes4[]"},{"indexed":false,"internalType":"bytes4[]","name":"newSelectors","type":"bytes4[]"}],"name":"ModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"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"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"name":"addModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"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":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"name":"removeModule","outputs":[],"stateMutability":"nonpayable","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":"payable","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":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"status","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"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":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"oldImplementation","type":"address"},{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes4[]","name":"oldSelectors","type":"bytes4[]"},{"internalType":"bytes4[]","name":"newSelectors","type":"bytes4[]"}],"name":"updateModule","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b5060405162004ef338038062004ef383398181016040528101906200003791906200068b565b6200004c6000801b336200016260201b60201c565b6000620000636200025b60201b62000e701760201c565b9050838160000190805190602001906200007f9291906200043e565b50828160010190805190602001906200009a9291906200043e565b5081816002019080519060200190620000b59291906200043e565b50620001077f01ffc9a7000000000000000000000000000000000000000000000000000000006001620000f26200028860201b62000e9d1760201c565b620002b560201b62000eca179092919060201c565b620001587f5b5e139f000000000000000000000000000000000000000000000000000000006001620001436200028860201b62000e9d1760201c565b620002b560201b62000eca179092919060201c565b505050506200082b565b6200017482826200039060201b60201c565b62000257576001620001906200041160201b62000fa21760201c565b600001600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b6000807f99574a7094154bb123ae6ae102096f0bf9679b85a5cd1e727aaa0ae5f132e6b190508091505090565b6000807f326d0c59a7612f6a9919e2a8ee333c80ba689d8ba2634de89c85cbb04832e70590508091505090565b63ffffffff60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160362000320576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200031790620007a5565b60405180910390fd5b80836000016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff021916908315150217905550505050565b6000620003a76200041160201b62000fa21760201c565b600001600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6000807f0166504e5ccb463bc7d5bd33317cff1a2c4b9d767f1c547638f719d36741a1d090508091505090565b8280546200044c90620007f6565b90600052602060002090601f016020900481019282620004705760008555620004bc565b82601f106200048b57805160ff1916838001178555620004bc565b82800160010185558215620004bc579182015b82811115620004bb5782518255916020019190600101906200049e565b5b509050620004cb9190620004cf565b5090565b5b80821115620004ea576000816000905550600101620004d0565b5090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b62000557826200050c565b810181811067ffffffffffffffff821117156200057957620005786200051d565b5b80604052505050565b60006200058e620004ee565b90506200059c82826200054c565b919050565b600067ffffffffffffffff821115620005bf57620005be6200051d565b5b620005ca826200050c565b9050602081019050919050565b60005b83811015620005f7578082015181840152602081019050620005da565b8381111562000607576000848401525b50505050565b6000620006246200061e84620005a1565b62000582565b90508281526020810184848401111562000643576200064262000507565b5b62000650848285620005d7565b509392505050565b600082601f83011262000670576200066f62000502565b5b8151620006828482602086016200060d565b91505092915050565b600080600060608486031215620006a757620006a6620004f8565b5b600084015167ffffffffffffffff811115620006c857620006c7620004fd565b5b620006d68682870162000658565b935050602084015167ffffffffffffffff811115620006fa57620006f9620004fd565b5b620007088682870162000658565b925050604084015167ffffffffffffffff8111156200072c576200072b620004fd565b5b6200073a8682870162000658565b9150509250925092565b600082825260208201905092915050565b7f4552433136353a20696e76616c696420696e7465726661636520696400000000600082015250565b60006200078d601c8362000744565b91506200079a8262000755565b602082019050919050565b60006020820190508181036000830152620007c0816200077e565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200080f57607f821691505b602082108103620008255762000824620007c7565b5b50919050565b6146b8806200083b6000396000f3fe6080604052600436106101185760003560e01c806342842e0e116100a05780639748a762116100645780639748a76214610483578063a22cb465146104ac578063b88d4fde146104d5578063c87b56dd146104f1578063e985e9c51461052e57610119565b806342842e0e146103855780634f6ccce7146103a15780636352211e146103de57806370a082311461041b57806395d89b411461045857610119565b8063095ea7b3116100e7578063095ea7b3146102bc5780630df5b997146102d857806318160ddd1461030157806323b872dd1461032c5780632f745c591461034857610119565b806301ffc9a7146101ee57806306d1d2a11461022b57806306fdde0314610254578063081812fc1461027f57610119565b5b34801561012557600080fd5b50600061013061056b565b600101600080357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503660008037600080366000845af43d6000803e80600081146101e9573d6000f35b3d6000fd5b3480156101fa57600080fd5b5061021560048036038101906102109190612cde565b610598565b6040516102229190612d26565b60405180910390f35b34801561023757600080fd5b50610252600480360381019061024d9190612e04565b6105bb565b005b34801561026057600080fd5b50610269610652565b6040516102769190612f44565b60405180910390f35b34801561028b57600080fd5b506102a660048036038101906102a19190612f9c565b6106ed565b6040516102b39190612fd8565b60405180910390f35b6102d660048036038101906102d19190612ff3565b6106ff565b005b3480156102e457600080fd5b506102ff60048036038101906102fa9190613033565b610813565b005b34801561030d57600080fd5b50610316610881565b60405161032391906130a2565b60405180910390f35b610346600480360381019061034191906130bd565b610890565b005b34801561035457600080fd5b5061036f600480360381019061036a9190612ff3565b6108f5565b60405161037c91906130a2565b60405180910390f35b61039f600480360381019061039a91906130bd565b610909565b005b3480156103ad57600080fd5b506103c860048036038101906103c39190612f9c565b610929565b6040516103d591906130a2565b60405180910390f35b3480156103ea57600080fd5b5061040560048036038101906104009190612f9c565b61093b565b6040516104129190612fd8565b60405180910390f35b34801561042757600080fd5b50610442600480360381019061043d9190613110565b61094d565b60405161044f91906130a2565b60405180910390f35b34801561046457600080fd5b5061046d61095f565b60405161047a9190612f44565b60405180910390f35b34801561048f57600080fd5b506104aa60048036038101906104a59190613033565b6109fa565b005b3480156104b857600080fd5b506104d360048036038101906104ce9190613169565b610a68565b005b6104ef60048036038101906104ea91906132d9565b610bdc565b005b3480156104fd57600080fd5b5061051860048036038101906105139190612f9c565b610c43565b6040516105259190612f44565b60405180910390f35b34801561053a57600080fd5b506105556004803603810190610550919061335c565b610e5c565b6040516105629190612d26565b60405180910390f35b6000807f334bcdc01ad42928dc76b974b9dc2d08aef6ae80f647d452bdc48c2baf971e8890508091505090565b60006105b4826105a6610e9d565b610fcf90919063ffffffff16565b9050919050565b6000801b6105c88161103a565b6105d3878686611047565b6105de8684846112ee565b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fa062c2c046aa14dc9284b13bde77061cb034f0aa820f20057af6b164651eaa0887878787604051610641949392919061345f565b60405180910390a350505050505050565b606061065c610e70565b600001805461066a906134c9565b80601f0160208091040260200160405190810160405280929190818152602001828054610696906134c9565b80156106e35780601f106106b8576101008083540402835291602001916106e3565b820191906000526020600020905b8154815290600101906020018083116106c657829003601f168201915b5050505050905090565b60006106f8826115de565b9050919050565b61070a82823461167b565b60006107158261093b565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077c9061356c565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806107c557506107c48133610e5c565b5b610804576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107fb906135fe565b60405180910390fd5b61080e83836116ce565b505050565b6000801b6108208161103a565b61082b8484846112ee565b8373ffffffffffffffffffffffffffffffffffffffff167f02d0c334c706cd2f08faf7bc03674fc7f3970dd8921776c655069cde33b7fb29848460405161087392919061361e565b60405180910390a250505050565b600061088b611790565b905090565b61089c838383346117a7565b6108a633826117fc565b6108e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108dc906136b4565b60405180910390fd5b6108f08383836118eb565b505050565b60006109018383611b14565b905092915050565b61092483838360405180602001604052806000815250610bdc565b505050565b600061093482611b3a565b9050919050565b600061094682611b5d565b9050919050565b600061095882611bf7565b9050919050565b6060610969610e70565b6001018054610977906134c9565b80601f01602080910402602001604051908101604052809291908181526020018280546109a3906134c9565b80156109f05780601f106109c5576101008083540402835291602001916109f0565b820191906000526020600020905b8154815290600101906020018083116109d357829003601f168201915b5050505050905090565b6000801b610a078161103a565b610a12848484611047565b8373ffffffffffffffffffffffffffffffffffffffff167f7c3eb4f9083f75cbed2bd3f703e24b4bbcb77d345d3c50945f3abf3e967755cb8484604051610a5a92919061361e565b60405180910390a250505050565b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610ad6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610acd90613720565b60405180910390fd5b80610adf611cbe565b60040160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051610bd09190612d26565b60405180910390a35050565b610be8848484346117a7565b610bf233836117fc565b610c31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c28906136b4565b60405180910390fd5b610c3d84848484611ceb565b50505050565b6060610c5f82610c51611cbe565b611d4790919063ffffffff16565b610c9e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c95906137b2565b60405180910390fd5b6000610ca8610e70565b905060008160030160008581526020019081526020016000208054610ccc906134c9565b80601f0160208091040260200160405190810160405280929190818152602001828054610cf8906134c9565b8015610d455780601f10610d1a57610100808354040283529160200191610d45565b820191906000526020600020905b815481529060010190602001808311610d2857829003601f168201915b505050505090506000826002018054610d5d906134c9565b80601f0160208091040260200160405190810160405280929190818152602001828054610d89906134c9565b8015610dd65780601f10610dab57610100808354040283529160200191610dd6565b820191906000526020600020905b815481529060010190602001808311610db957829003601f168201915b505050505090506000815103610df157819350505050610e57565b600082511115610e27578082604051602001610e0e92919061380e565b6040516020818303038152906040529350505050610e57565b80610e3186611d67565b604051602001610e4292919061380e565b60405160208183030381529060405293505050505b919050565b6000610e688383611ec7565b905092915050565b6000807f99574a7094154bb123ae6ae102096f0bf9679b85a5cd1e727aaa0ae5f132e6b190508091505090565b6000807f326d0c59a7612f6a9919e2a8ee333c80ba689d8ba2634de89c85cbb04832e70590508091505090565b63ffffffff60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603610f32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f299061387e565b60405180910390fd5b80836000016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff021916908315150217905550505050565b6000807f0166504e5ccb463bc7d5bd33317cff1a2c4b9d767f1c547638f719d36741a1d090508091505090565b6000826000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff16905092915050565b6110448133611f64565b50565b600061105161056b565b90506000838360405160200161106892919061361e565b604051602081830303815290604052805190602001209050808260020160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414611103576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110fa906138ea565b60405180910390fd5b60005b848490508110156112e6578573ffffffffffffffffffffffffffffffffffffffff168360010160008787858181106111415761114061390a565b5b90506020020160208101906111569190612cde565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611219576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161121090613985565b60405180910390fd5b60008360010160008787858181106112345761123361390a565b5b90506020020160208101906112499190612cde565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080806112de906139d4565b915050611106565b505050505050565b60006112f861056b565b90506000801b8160020160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414611380576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137790613a68565b60405180910390fd5b60005b8383905081101561156357600073ffffffffffffffffffffffffffffffffffffffff168260010160008686858181106113bf576113be61390a565b5b90506020020160208101906113d49190612cde565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611497576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161148e90613ad4565b60405180910390fd5b848260010160008686858181106114b1576114b061390a565b5b90506020020160208101906114c69190612cde565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808061155b906139d4565b915050611383565b506000838360405160200161157992919061361e565b604051602081830303815290604052805190602001209050808260020160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505050505050565b6000806115e9611cbe565b90506115fe8382611d4790919063ffffffff16565b61163d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161163490613b66565b60405180910390fd5b80600301600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915050919050565b600081146116be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116b590613bf8565b60405180910390fd5b6116c9838383612008565b505050565b816116d7611cbe565b600301600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff1661174a83611b5d565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006117a261179d611cbe565b61200d565b905090565b600081146117ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117e190613c8a565b60405180910390fd5b6117f684848484612022565b50505050565b60006118188261180a611cbe565b611d4790919063ffffffff16565b611857576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161184e90613d1c565b60405180910390fd5b600061186283611b5d565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806118d157508373ffffffffffffffffffffffffffffffffffffffff166118b9846115de565b73ffffffffffffffffffffffffffffffffffffffff16145b806118e257506118e18185611ec7565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff1661190b82611b5d565b73ffffffffffffffffffffffffffffffffffffffff1614611961576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161195890613dae565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036119d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119c790613e40565b60405180910390fd5b6119db838383612028565b6119e66000826116ce565b60006119f0611cbe565b9050611a45828260020160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002061203890919063ffffffff16565b50611a99828260020160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002061205290919063ffffffff16565b50611ab282848360000161206c9092919063ffffffff16565b50818373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a450505050565b6000611b328383611b23611cbe565b6120a19092919063ffffffff16565b905092915050565b6000611b5682611b48611cbe565b6120ff90919063ffffffff16565b9050919050565b600080611b7d83611b6c611cbe565b60000161212590919063ffffffff16565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611bee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be590613eac565b60405180910390fd5b80915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611c67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c5e90613f3e565b60405180910390fd5b611cb7611c72611cbe565b60020160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612142565b9050919050565b6000807f3c7bf052874fa81625121783266a03507bd2cd48b16e571c01a04e8dd3fb07a690508091505090565b611cf68484846118eb565b611d0284848484612157565b611d41576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d3890613fd0565b60405180910390fd5b50505050565b6000611d5f82846000016122cd90919063ffffffff16565b905092915050565b606060008203611dae576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050611ec2565b600082905060005b60008214611de0578080611dc9906139d4565b915050600a82611dd9919061401f565b9150611db6565b60008167ffffffffffffffff811115611dfc57611dfb6131ae565b5b6040519080825280601f01601f191660200182016040528015611e2e5781602001600182028036833780820191505090505b5090505b60008514611ebb57600182611e479190614050565b9150600a85611e569190614084565b6030611e6291906140b5565b60f81b818381518110611e7857611e7761390a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85611eb4919061401f565b9450611e32565b8093505050505b919050565b6000611ed1611cbe565b60040160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b611f6e82826122e7565b61200457611f918173ffffffffffffffffffffffffffffffffffffffff1661235b565b611fa860208460001c61238e90919063ffffffff16565b604051602001611fb99291906141a3565b6040516020818303038152906040526040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ffb9190612f44565b60405180910390fd5b5050565b505050565b600061201b826000016125b3565b9050919050565b50505050565b6120338383836125c8565b505050565b600061204a836000018360001b6125d8565b905092915050565b6000612064836000018360001b6126c6565b905092915050565b6000612098846000018460001b8473ffffffffffffffffffffffffffffffffffffffff1660001b612736565b90509392505050565b60006120f6828560020160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002061281890919063ffffffff16565b90509392505050565b600080612118838560000161283290919063ffffffff16565b5090508091505092915050565b6000612137836000018360001b61285e565b60001c905092915050565b6000612150826000016128f0565b9050919050565b60006121788473ffffffffffffffffffffffffffffffffffffffff16612901565b61218557600190506122c5565b600061224563150b7a0260e01b338887876040516024016121a99493929190614232565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051806060016040528060328152602001614651603291398773ffffffffffffffffffffffffffffffffffffffff166129149092919063ffffffff16565b905060008180602001905181019061225d9190614293565b90507f150b7a02000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614925050505b949350505050565b60006122df836000018360001b61292c565b905092915050565b60006122f1610fa2565b600001600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b606061238760148373ffffffffffffffffffffffffffffffffffffffff1661238e90919063ffffffff16565b9050919050565b6060600060028360026123a191906142c0565b6123ab91906140b5565b67ffffffffffffffff8111156123c4576123c36131ae565b5b6040519080825280601f01601f1916602001820160405280156123f65781602001600182028036833780820191505090505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061242e5761242d61390a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106124925761249161390a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006001846002020190505b6001811115612565577f3031323334353637383961626364656600000000000000000000000000000000600f86166010811061250c5761250b61390a565b5b1a60f81b8282815181106125235761252261390a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c9450806001900390506124cd565b50600084146125a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125a09061438c565b60405180910390fd5b8091505092915050565b60006125c18260000161294f565b9050919050565b6125d3838383612960565b505050565b600080836001016000848152602001908152602001600020549050600081146126ba5760008460000160018660000180549050038154811061261d5761261c61390a565b5b90600052602060002001549050808560000160018403815481106126445761264361390a565b5b906000526020600020018190555081856001016000838152602001908152602001600020819055505083600001805480612681576126806143ac565b5b600190038181906000526020600020016000905590558360010160008481526020019081526020016000206000905560019150506126c0565b60009150505b92915050565b60006126d283836129cd565b61272b578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050612730565b600090505b92915050565b600080846001016000858152602001908152602001600020549050600081036127dc57846000016040518060400160405280868152602001858152509080600181540180825580915050600190039060005260206000209060020201600090919091909150600082015181600001556020820151816001015550508460000180549050856001016000868152602001908152602001600020819055506001915050612811565b828560000160018303815481106127f6576127f561390a565b5b90600052602060002090600202016001018190555060009150505b9392505050565b600061282783600001836129f0565b60001c905092915050565b6000806000806128458660000186612a64565b915091508160001c8160001c9350935050509250929050565b600080836001016000848152602001908152602001600020549050600081036128bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128b390614427565b60405180910390fd5b8360000160018203815481106128d5576128d461390a565b5b90600052602060002090600202016001015491505092915050565b600081600001805490509050919050565b600080823b905060008111915050919050565b60606129238484600085612aee565b90509392505050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b61296b838383612c10565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036129c8576129a7610e70565b600301600082815260200190815260200160002060006129c79190612c15565b5b505050565b600080836001016000848152602001908152602001600020541415905092915050565b600081836000018054905011612a3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a32906144b9565b60405180910390fd5b826000018281548110612a5157612a5061390a565b5b9060005260206000200154905092915050565b60008082846000018054905011612ab0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612aa79061454b565b60405180910390fd5b6000846000018481548110612ac857612ac761390a565b5b906000526020600020906002020190508060000154816001015492509250509250929050565b6060612af985612901565b612b38576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b2f906145dd565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612b619190614639565b60006040518083038185875af1925050503d8060008114612b9e576040519150601f19603f3d011682016040523d82523d6000602084013e612ba3565b606091505b50915091508115612bb8578092505050612c08565b600081511115612bcb5780518082602001fd5b836040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bff9190612f44565b60405180910390fd5b949350505050565b505050565b508054612c21906134c9565b6000825580601f10612c335750612c52565b601f016020900490600052602060002090810190612c519190612c55565b5b50565b5b80821115612c6e576000816000905550600101612c56565b5090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612cbb81612c86565b8114612cc657600080fd5b50565b600081359050612cd881612cb2565b92915050565b600060208284031215612cf457612cf3612c7c565b5b6000612d0284828501612cc9565b91505092915050565b60008115159050919050565b612d2081612d0b565b82525050565b6000602082019050612d3b6000830184612d17565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612d6c82612d41565b9050919050565b612d7c81612d61565b8114612d8757600080fd5b50565b600081359050612d9981612d73565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112612dc457612dc3612d9f565b5b8235905067ffffffffffffffff811115612de157612de0612da4565b5b602083019150836020820283011115612dfd57612dfc612da9565b5b9250929050565b60008060008060008060808789031215612e2157612e20612c7c565b5b6000612e2f89828a01612d8a565b9650506020612e4089828a01612d8a565b955050604087013567ffffffffffffffff811115612e6157612e60612c81565b5b612e6d89828a01612dae565b9450945050606087013567ffffffffffffffff811115612e9057612e8f612c81565b5b612e9c89828a01612dae565b92509250509295509295509295565b600081519050919050565b600082825260208201905092915050565b60005b83811015612ee5578082015181840152602081019050612eca565b83811115612ef4576000848401525b50505050565b6000601f19601f8301169050919050565b6000612f1682612eab565b612f208185612eb6565b9350612f30818560208601612ec7565b612f3981612efa565b840191505092915050565b60006020820190508181036000830152612f5e8184612f0b565b905092915050565b6000819050919050565b612f7981612f66565b8114612f8457600080fd5b50565b600081359050612f9681612f70565b92915050565b600060208284031215612fb257612fb1612c7c565b5b6000612fc084828501612f87565b91505092915050565b612fd281612d61565b82525050565b6000602082019050612fed6000830184612fc9565b92915050565b6000806040838503121561300a57613009612c7c565b5b600061301885828601612d8a565b925050602061302985828601612f87565b9150509250929050565b60008060006040848603121561304c5761304b612c7c565b5b600061305a86828701612d8a565b935050602084013567ffffffffffffffff81111561307b5761307a612c81565b5b61308786828701612dae565b92509250509250925092565b61309c81612f66565b82525050565b60006020820190506130b76000830184613093565b92915050565b6000806000606084860312156130d6576130d5612c7c565b5b60006130e486828701612d8a565b93505060206130f586828701612d8a565b925050604061310686828701612f87565b9150509250925092565b60006020828403121561312657613125612c7c565b5b600061313484828501612d8a565b91505092915050565b61314681612d0b565b811461315157600080fd5b50565b6000813590506131638161313d565b92915050565b600080604083850312156131805761317f612c7c565b5b600061318e85828601612d8a565b925050602061319f85828601613154565b9150509250929050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6131e682612efa565b810181811067ffffffffffffffff82111715613205576132046131ae565b5b80604052505050565b6000613218612c72565b905061322482826131dd565b919050565b600067ffffffffffffffff821115613244576132436131ae565b5b61324d82612efa565b9050602081019050919050565b82818337600083830152505050565b600061327c61327784613229565b61320e565b905082815260208101848484011115613298576132976131a9565b5b6132a384828561325a565b509392505050565b600082601f8301126132c0576132bf612d9f565b5b81356132d0848260208601613269565b91505092915050565b600080600080608085870312156132f3576132f2612c7c565b5b600061330187828801612d8a565b945050602061331287828801612d8a565b935050604061332387828801612f87565b925050606085013567ffffffffffffffff81111561334457613343612c81565b5b613350878288016132ab565b91505092959194509250565b6000806040838503121561337357613372612c7c565b5b600061338185828601612d8a565b925050602061339285828601612d8a565b9150509250929050565b600082825260208201905092915050565b6000819050919050565b6133c081612c86565b82525050565b60006133d283836133b7565b60208301905092915050565b60006133ed6020840184612cc9565b905092915050565b6000602082019050919050565b600061340e838561339c565b9350613419826133ad565b8060005b858110156134525761342f82846133de565b61343988826133c6565b9750613444836133f5565b92505060018101905061341d565b5085925050509392505050565b6000604082019050818103600083015261347a818688613402565b9050818103602083015261348f818486613402565b905095945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806134e157607f821691505b6020821081036134f4576134f361349a565b5b50919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b6000613556602183612eb6565b9150613561826134fa565b604082019050919050565b6000602082019050818103600083015261358581613549565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b60006135e8603883612eb6565b91506135f38261358c565b604082019050919050565b60006020820190508181036000830152613617816135db565b9050919050565b60006020820190508181036000830152613639818486613402565b90509392505050565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206f7220617070726f76656400000000000000000000000000000000602082015250565b600061369e603083612eb6565b91506136a982613642565b604082019050919050565b600060208201905081810360008301526136cd81613691565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b600061370a601983612eb6565b9150613715826136d4565b602082019050919050565b60006020820190508181036000830152613739816136fd565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b600061379c602f83612eb6565b91506137a782613740565b604082019050919050565b600060208201905081810360008301526137cb8161378f565b9050919050565b600081905092915050565b60006137e882612eab565b6137f281856137d2565b9350613802818560208601612ec7565b80840191505092915050565b600061381a82856137dd565b915061382682846137dd565b91508190509392505050565b7f4552433136353a20696e76616c696420696e7465726661636520696400000000600082015250565b6000613868601c83612eb6565b915061387382613832565b602082019050919050565b600060208201905081810360008301526138978161385b565b9050919050565b7f496e76616c69642073656c6563746f72206c6973740000000000000000000000600082015250565b60006138d4601583612eb6565b91506138df8261389e565b602082019050919050565b60006020820190508181036000830152613903816138c7565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f556e726567697374657265642073656c6563746f720000000000000000000000600082015250565b600061396f601583612eb6565b915061397a82613939565b602082019050919050565b6000602082019050818103600083015261399e81613962565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006139df82612f66565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613a1157613a106139a5565b5b600182019050919050565b7f496d706c656d656e746174696f6e20616c726561647920657869737473000000600082015250565b6000613a52601d83612eb6565b9150613a5d82613a1c565b602082019050919050565b60006020820190508181036000830152613a8181613a45565b9050919050565b7f53656c6563746f7220616c726561647920726567697374657265640000000000600082015250565b6000613abe601b83612eb6565b9150613ac982613a88565b602082019050919050565b60006020820190508181036000830152613aed81613ab1565b9050919050565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b6000613b50602c83612eb6565b9150613b5b82613af4565b604082019050919050565b60006020820190508181036000830152613b7f81613b43565b9050919050565b7f4552433732313a2070617961626c6520617070726f76652063616c6c73206e6f60008201527f7420737570706f72746564000000000000000000000000000000000000000000602082015250565b6000613be2602b83612eb6565b9150613bed82613b86565b604082019050919050565b60006020820190508181036000830152613c1181613bd5565b9050919050565b7f4552433732313a2070617961626c65207472616e736665722063616c6c73206e60008201527f6f7420737570706f727465640000000000000000000000000000000000000000602082015250565b6000613c74602c83612eb6565b9150613c7f82613c18565b604082019050919050565b60006020820190508181036000830152613ca381613c67565b9050919050565b7f4552433732313a20717565727920666f72206e6f6e6578697374656e7420746f60008201527f6b656e0000000000000000000000000000000000000000000000000000000000602082015250565b6000613d06602383612eb6565b9150613d1182613caa565b604082019050919050565b60006020820190508181036000830152613d3581613cf9565b9050919050565b7f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960008201527f73206e6f74206f776e0000000000000000000000000000000000000000000000602082015250565b6000613d98602983612eb6565b9150613da382613d3c565b604082019050919050565b60006020820190508181036000830152613dc781613d8b565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000613e2a602483612eb6565b9150613e3582613dce565b604082019050919050565b60006020820190508181036000830152613e5981613e1d565b9050919050565b7f4552433732313a20696e76616c6964206f776e65720000000000000000000000600082015250565b6000613e96601583612eb6565b9150613ea182613e60565b602082019050919050565b60006020820190508181036000830152613ec581613e89565b9050919050565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b6000613f28602a83612eb6565b9150613f3382613ecc565b604082019050919050565b60006020820190508181036000830152613f5781613f1b565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000613fba603283612eb6565b9150613fc582613f5e565b604082019050919050565b60006020820190508181036000830152613fe981613fad565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061402a82612f66565b915061403583612f66565b92508261404557614044613ff0565b5b828204905092915050565b600061405b82612f66565b915061406683612f66565b925082821015614079576140786139a5565b5b828203905092915050565b600061408f82612f66565b915061409a83612f66565b9250826140aa576140a9613ff0565b5b828206905092915050565b60006140c082612f66565b91506140cb83612f66565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614100576140ff6139a5565b5b828201905092915050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b60006141416017836137d2565b915061414c8261410b565b601782019050919050565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b600061418d6011836137d2565b915061419882614157565b601182019050919050565b60006141ae82614134565b91506141ba82856137dd565b91506141c582614180565b91506141d182846137dd565b91508190509392505050565b600081519050919050565b600082825260208201905092915050565b6000614204826141dd565b61420e81856141e8565b935061421e818560208601612ec7565b61422781612efa565b840191505092915050565b60006080820190506142476000830187612fc9565b6142546020830186612fc9565b6142616040830185613093565b818103606083015261427381846141f9565b905095945050505050565b60008151905061428d81612cb2565b92915050565b6000602082840312156142a9576142a8612c7c565b5b60006142b78482850161427e565b91505092915050565b60006142cb82612f66565b91506142d683612f66565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561430f5761430e6139a5565b5b828202905092915050565b7f55696e745574696c733a20686578206c656e67746820696e737566666963696560008201527f6e74000000000000000000000000000000000000000000000000000000000000602082015250565b6000614376602283612eb6565b91506143818261431a565b604082019050919050565b600060208201905081810360008301526143a581614369565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f456e756d657261626c654d61703a206e6f6e6578697374656e74206b65790000600082015250565b6000614411601e83612eb6565b915061441c826143db565b602082019050919050565b6000602082019050818103600083015261444081614404565b9050919050565b7f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008201527f6473000000000000000000000000000000000000000000000000000000000000602082015250565b60006144a3602283612eb6565b91506144ae82614447565b604082019050919050565b600060208201905081810360008301526144d281614496565b9050919050565b7f456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e60008201527f6473000000000000000000000000000000000000000000000000000000000000602082015250565b6000614535602283612eb6565b9150614540826144d9565b604082019050919050565b6000602082019050818103600083015261456481614528565b9050919050565b7f416464726573735574696c733a2066756e6374696f6e2063616c6c20746f206e60008201527f6f6e2d636f6e7472616374000000000000000000000000000000000000000000602082015250565b60006145c7602b83612eb6565b91506145d28261456b565b604082019050919050565b600060208201905081810360008301526145f6816145ba565b9050919050565b600081905092915050565b6000614613826141dd565b61461d81856145fd565b935061462d818560208601612ec7565b80840191505092915050565b60006146458284614608565b91508190509291505056fe4552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e746572a264697066735822122016b6e7043e551b384240023a250e0d348d798088b1e4a195d832c1394c20bb9264736f6c634300080d0033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000001544494d4f206964656e7469747920426574612056310000000000000000000000000000000000000000000000000000000000000000000000000000000000000a44494d4f42657461563100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002668747470733a2f2f646576696365732d6170692e64696d6f2e7a6f6e652f76312f6e6674732f0000000000000000000000000000000000000000000000000000

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000001544494d4f206964656e7469747920426574612056310000000000000000000000000000000000000000000000000000000000000000000000000000000000000a44494d4f42657461563100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002668747470733a2f2f646576696365732d6170692e64696d6f2e7a6f6e652f76312f6e6674732f0000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _name (string): DIMO identity Beta V1
Arg [1] : _symbol (string): DIMOBetaV1
Arg [2] : __baseURI (string): https://devices-api.dimo.zone/v1/nfts/

-----Encoded View---------------
10 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000015
Arg [4] : 44494d4f206964656e7469747920426574612056310000000000000000000000
Arg [5] : 000000000000000000000000000000000000000000000000000000000000000a
Arg [6] : 44494d4f42657461563100000000000000000000000000000000000000000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000026
Arg [8] : 68747470733a2f2f646576696365732d6170692e64696d6f2e7a6f6e652f7631
Arg [9] : 2f6e6674732f0000000000000000000000000000000000000000000000000000


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.