POL Price: $0.30081 (-5.10%)
 

Overview

Max Total Supply

0 W3D

Holders

336

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Balance
1 W3D
0xd5893989b9952c6568a99F854795AcC5Ae480D56
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information

Contract Source Code Verified (Exact Match)

Contract Name:
W3DBootcamp

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion
File 1 of 16 : BootcampNFTContract.sol
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import '@openzeppelin/contracts/utils/Strings.sol';
import '@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol';
import '@openzeppelin/contracts/utils/Counters.sol';
import '@openzeppelin/contracts/access/AccessControl.sol';
import 'hardhat/console.sol';

// We need to import the helper functions from the contract that we copy/pasted.
import {Base64} from './Base64.sol';

contract W3DBootcamp is ERC721URIStorage, AccessControl {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    bytes32 public constant AUTH_MINT = keccak256('AUTHORIZED_MINTER');

    mapping(string => address[]) private student_courses;
    mapping(bytes4 => uint8) private registry;

    mapping(bytes32 => mapping(bytes32 => uint256)) private cohortCounter;
    mapping(bytes32 => string) private courseDescriptions;
    mapping(bytes32 => string) private courseNames;
    mapping(bytes32 => string) private cohortNames;

    mapping(uint256 => bytes32) private tokenIdCohorts;
    mapping(uint256 => bytes32) private tokenIdCourses;
    mapping(uint256 => uint256) private tokenIdNumbers;

    event StudentOnCourse(
        address indexed studentAddress,
        string indexed course_name,
        string indexed cohort_name
    );

    string baseSvg =
        "<svg xmlns='http://www.w3.org/2000/svg' preserveAspectRatio='xMinYMin meet' viewBox='0 0 350 350'><style>.base { fill: white; font-family: serif;font-size: 24px;}</style><rect width='100%' height='100%' fill='black' /><text x='50%' y='50%' class='base' dominant-baseline='middle' text-anchor='middle'>";

    string baseSVG =
        "<?xml version='1.0' encoding='utf-8'?><svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 850.39 850.39' style='enable-background:new 0 0 850.39 850.39;' xml:space='preserve'> <defs> <style> @font-face { font-family: 'Minecraftia-Regular'; src: url(data:application/font-woff2;charset=utf-8;base64,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) format('woff2') } </style> </defs> <style type='text/css'> .st0{stroke:#FFFFFF;stroke-miterlimit:10;} .st1{fill:#A0E546;} .st2{font-family:'Minecraftia-Regular';} .st3{font-size:20px;} .st4{fill:#FFFFFF;} .st5{fill:#2ECE29;} .st6{fill:#775CE1;} .st7{fill:#EDB015;} .st8{letter-spacing:22;} .st9{fill:#FFFFFF;stroke:#FFFFFF;stroke-miterlimit:10;} .st10{fill:#4C98E2;} .st11{fill:none;} .st12{font-size:55px;} .st13{display:none;} .st14{font-size:60px;} .st15{fill:#CE3028;} .st16{fill:#EAB52F;} .st17{display:none;fill:#720909;} .st18{font-size:39.2318px;} .st19{font-size:43.1707px;} </style> <g id='linhacodigo'> <path class='st0' d='M849.55,850.39H0.84c-0.46,0-0.84-0.38-0.84-0.84V0.84C0,0.38,0.38,0,0.84,0h848.71 c0.46,0,0.84,0.38,0.84,0.84v848.71C850.39,850.02,850.02,850.39,849.55,850.39z'/><text transform='matrix(1 0 0 1 49.0367 325.8286)'><tspan x='0' y='0' class='st1 st2 st3'>pragma  solidity</tspan><tspan x='199.5' y='0' class='st4 st2 st3'>  0.8.1 ;</tspan><tspan x='0' y='90' class='st1 st2 st3'>contract</tspan><tspan x='120' y='90' class='st4 st2 st3'>web3dev  {</tspan><tspan x='32.92' y='135' class='st4 st2 st3'>function  </tspan><tspan x='145.42' y='135' class='st10 st2 st3'>bootcamp</tspan><tspan x='265.42' y='135' class='st4 st2 st3'>() </tspan><tspan x='300.42' y='135' class='st1 st2 st3'>public view returns</tspan><tspan x='547' y='135' class='st4 st2 st3'>(</tspan><tspan x='570.42' y='135' class='st10 st2 st3'>string memory)</tspan><tspan x='755.42' y='135' class='st4 st2 st3'>{</tspan><tspan x='111.67' y='180' class='st4 st2 st3'>return </tspan><tspan x='216.67' y='180' class='st6 st2 st3'>";
    string svgPart2 =
        ";</tspan><tspan x='32.92' y='225' class='st4 st2 st3'>}</tspan><tspan x='0' y='270' class='st4 st2 st3'>}</tspan></text></g><g><text transform='matrix(1 0 0 1 650.213 781.2156)' class='st4 st2 st12'>#";

    string svgPart3 =
        "</text></g><g><rect x='48.13' y='192.85' class='st11' width='497.66' height='96.99'/> <text transform='matrix(1 0 0 1 48.1271 282.8495)' class='st4 st2 st14'>";

    string svgPart4 =
        "</text><rect x='38.13' y='32.02' class='st15' width='55.77' height='48.46'/><rect x='119.2' y='32.02' class='st16' width='55.77' height='48.46'/><rect x='201.18' y='32.02' class='st5' width='55.77' height='48.46'/><text transform='matrix(1.2764 0 0 1 138.4717 101.3228)' class='st13 st2 st18'>-</text><text transform='matrix(1.1781 0 0 1 227.6772 105.4309)' class='st13 st2 st19'>+</text></g></svg>";

    constructor() ERC721('WEB3DEV Bootcamp', 'W3D') {
        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(ERC721, AccessControl)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }

    function addCourse(string memory newCourse, string memory description)
        external
        onlyAdmin
    {
        bytes32 new_course = keccak256(abi.encodePacked(newCourse));
        require(
            bytes(courseDescriptions[new_course]).length == 0,
            'Course already registered'
        );
        courseDescriptions[new_course] = description;
        courseNames[new_course] = newCourse;
    }

    function mintCertificate(
        string memory cohort,
        string memory course,
        address studentAddress
    ) external onlyMinter {
        //Verify if the student are already registered in the current course
        bytes4 hashes = bytes4(
            keccak256(abi.encodePacked(studentAddress, course))
        );
        require(
            registry[hashes] == 0,
            'Student already registered on this course'
        );
        // if not, will register
        registry[hashes] = 1;
        student_courses[course].push(studentAddress);

        bytes32 encoded_course = keccak256(abi.encodePacked(course));
        require(
            bytes(courseDescriptions[encoded_course]).length != 0,
            'Invalid Course'
        );

        bytes32 encoded_cohort = keccak256(abi.encodePacked(cohort));
        cohortNames[encoded_cohort] = cohort;

        _mintCertificate(encoded_cohort, encoded_course, studentAddress);
        emit StudentOnCourse(studentAddress, course, cohort);
    }

    function _mintCertificate(
        bytes32 encoded_cohort,
        bytes32 encoded_course,
        address studentAddress
    ) internal {
        cohortCounter[encoded_course][encoded_cohort] += 1;
        _tokenIds.increment();

        uint256 newTokenID = _tokenIds.current();
        uint256 newStudentID = cohortCounter[encoded_course][encoded_cohort];

        tokenIdNumbers[newTokenID] = newStudentID;
        tokenIdCourses[newTokenID] = encoded_course;
        tokenIdCohorts[newTokenID] = encoded_cohort;

        // console.log('TokenID: %s', finalTokenUri);
        _safeMint(studentAddress, newTokenID);
        // _setTokenURI(newTokenID, finalTokenUri);
    }

    function tokenURI(uint256 tokenId)
        public
        view
        virtual
        override
        returns (string memory)
    {
        string memory course = courseNames[tokenIdCourses[tokenId]];
        string memory cohort = cohortNames[tokenIdCohorts[tokenId]];
        string memory course_description = courseDescriptions[
            tokenIdCourses[tokenId]
        ];
        uint256 newStudentID = tokenIdNumbers[tokenId];

        string memory finalSvg = string(
            abi.encodePacked(
                baseSVG,
                course,
                svgPart2,
                Strings.toString(newStudentID),
                svgPart3,
                cohort,
                svgPart4
            )
        );
        string memory metadata = string(
            abi.encodePacked(
                '{"name": "WEB3DEV Bootcamp", ',
                '"attributes": [ { "trait_type": "course", "value": "',
                course,
                '"},{"trait_type": "cohort", "value": "',
                cohort,
                '"},{"trait_type": "number", "value": "',
                Strings.toString(newStudentID),
                '"}], "description": "',
                course_description,
                '", "image": "data:image/svg+xml;base64,',
                Base64.encode(bytes(finalSvg)),
                '"}'
            )
        );
        string memory json = Base64.encode(bytes(metadata));

        return string(abi.encodePacked('data:application/json;base64,', json));
    }

    modifier onlyAdmin() {
        require(
            hasRole(DEFAULT_ADMIN_ROLE, msg.sender),
            'Caller is not an Window Admin'
        );
        _;
    }

    modifier onlyMinter() {
        require(
            hasRole(DEFAULT_ADMIN_ROLE, msg.sender),
            'Caller is not an Window Admin'
        );
        _;
    }

    function addAuthorizedMinter(address account) external onlyAdmin {
        _grantRole(AUTH_MINT, account);
    }

    function removeAdmin(address account) external onlyAdmin {
        _revokeRole(AUTH_MINT, account);
    }

    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        revert('disabled');
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        revert('disabled');
    }
}

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

pragma solidity ^0.8.0;

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

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

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

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

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

File 3 of 16 : ERC721URIStorage.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721URIStorage.sol)

pragma solidity ^0.8.0;

import "../ERC721.sol";

/**
 * @dev ERC721 token with storage based token URI management.
 */
abstract contract ERC721URIStorage is ERC721 {
    using Strings for uint256;

    // Optional mapping for token URIs
    mapping(uint256 => string) private _tokenURIs;

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721URIStorage: URI query for nonexistent token");

        string memory _tokenURI = _tokenURIs[tokenId];
        string memory base = _baseURI();

        // If there is no base URI, return the token URI.
        if (bytes(base).length == 0) {
            return _tokenURI;
        }
        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
        if (bytes(_tokenURI).length > 0) {
            return string(abi.encodePacked(base, _tokenURI));
        }

        return super.tokenURI(tokenId);
    }

    /**
     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
        require(_exists(tokenId), "ERC721URIStorage: URI set of nonexistent token");
        _tokenURIs[tokenId] = _tokenURI;
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual override {
        super._burn(tokenId);

        if (bytes(_tokenURIs[tokenId]).length != 0) {
            delete _tokenURIs[tokenId];
        }
    }
}

File 4 of 16 : Counters.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}

File 5 of 16 : AccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (access/AccessControl.sol)

pragma solidity ^0.8.0;

import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";

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

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

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

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

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

    /**
     * @dev Revert with a standard message if `_msgSender()` is missing `role`.
     * Overriding this function changes the behavior of the {onlyRole} modifier.
     *
     * Format of the revert message is described in {_checkRole}.
     *
     * _Available since v4.6._
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @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 ",
                        Strings.toHexString(uint160(account), 20),
                        " is missing role ",
                        Strings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

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

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

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

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

        _revokeRole(role, account);
    }

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

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

    /**
     * @dev Grants `role` to `account`.
     *
     * Internal function without access restriction.
     */
    function _grantRole(bytes32 role, address account) internal virtual {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * Internal function without access restriction.
     */
    function _revokeRole(bytes32 role, address account) internal virtual {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

File 6 of 16 : console.sol
// SPDX-License-Identifier: MIT
pragma solidity >= 0.4.22 <0.9.0;

library console {
	address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);

	function _sendLogPayload(bytes memory payload) private view {
		uint256 payloadLength = payload.length;
		address consoleAddress = CONSOLE_ADDRESS;
		assembly {
			let payloadStart := add(payload, 32)
			let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
		}
	}

	function log() internal view {
		_sendLogPayload(abi.encodeWithSignature("log()"));
	}

	function logInt(int p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(int)", p0));
	}

	function logUint(uint p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
	}

	function logString(string memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
	}

	function logBool(bool p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
	}

	function logAddress(address p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
	}

	function logBytes(bytes memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
	}

	function logBytes1(bytes1 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
	}

	function logBytes2(bytes2 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
	}

	function logBytes3(bytes3 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
	}

	function logBytes4(bytes4 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
	}

	function logBytes5(bytes5 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
	}

	function logBytes6(bytes6 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
	}

	function logBytes7(bytes7 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
	}

	function logBytes8(bytes8 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
	}

	function logBytes9(bytes9 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
	}

	function logBytes10(bytes10 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
	}

	function logBytes11(bytes11 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
	}

	function logBytes12(bytes12 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
	}

	function logBytes13(bytes13 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
	}

	function logBytes14(bytes14 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
	}

	function logBytes15(bytes15 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
	}

	function logBytes16(bytes16 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
	}

	function logBytes17(bytes17 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
	}

	function logBytes18(bytes18 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
	}

	function logBytes19(bytes19 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
	}

	function logBytes20(bytes20 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
	}

	function logBytes21(bytes21 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
	}

	function logBytes22(bytes22 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
	}

	function logBytes23(bytes23 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
	}

	function logBytes24(bytes24 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
	}

	function logBytes25(bytes25 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
	}

	function logBytes26(bytes26 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
	}

	function logBytes27(bytes27 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
	}

	function logBytes28(bytes28 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
	}

	function logBytes29(bytes29 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
	}

	function logBytes30(bytes30 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
	}

	function logBytes31(bytes31 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
	}

	function logBytes32(bytes32 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
	}

	function log(uint p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
	}

	function log(string memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
	}

	function log(bool p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
	}

	function log(address p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
	}

	function log(uint p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1));
	}

	function log(uint p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1));
	}

	function log(uint p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1));
	}

	function log(uint p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1));
	}

	function log(string memory p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1));
	}

	function log(string memory p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
	}

	function log(string memory p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
	}

	function log(string memory p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
	}

	function log(bool p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1));
	}

	function log(bool p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
	}

	function log(bool p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
	}

	function log(bool p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
	}

	function log(address p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1));
	}

	function log(address p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
	}

	function log(address p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
	}

	function log(address p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
	}

	function log(uint p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2));
	}

	function log(uint p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2));
	}

	function log(uint p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2));
	}

	function log(uint p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2));
	}

	function log(uint p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2));
	}

	function log(uint p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2));
	}

	function log(uint p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2));
	}

	function log(uint p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2));
	}

	function log(uint p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2));
	}

	function log(uint p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2));
	}

	function log(uint p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2));
	}

	function log(uint p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
	}

	function log(string memory p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2));
	}

	function log(string memory p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
	}

	function log(string memory p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
	}

	function log(string memory p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
	}

	function log(bool p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2));
	}

	function log(bool p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2));
	}

	function log(bool p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2));
	}

	function log(bool p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
	}

	function log(bool p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2));
	}

	function log(bool p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
	}

	function log(bool p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
	}

	function log(bool p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
	}

	function log(bool p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2));
	}

	function log(bool p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
	}

	function log(bool p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
	}

	function log(bool p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
	}

	function log(address p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2));
	}

	function log(address p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2));
	}

	function log(address p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2));
	}

	function log(address p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2));
	}

	function log(address p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2));
	}

	function log(address p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
	}

	function log(address p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
	}

	function log(address p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
	}

	function log(address p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2));
	}

	function log(address p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
	}

	function log(address p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
	}

	function log(address p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
	}

	function log(address p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2));
	}

	function log(address p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
	}

	function log(address p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
	}

	function log(address p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
	}

	function log(uint p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
	}

}

File 7 of 16 : Base64.sol
/**
 *Submitted for verification at Etherscan.io on 2021-09-05
 */

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// [MIT License]
/// @title Base64
/// @notice Provides a function for encoding some bytes in base64
/// @author Brecht Devos <[email protected]>
library Base64 {
    bytes internal constant TABLE =
        'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

    /// @notice Encodes some bytes to the base64 representation
    function encode(bytes memory data) internal pure returns (string memory) {
        uint256 len = data.length;
        if (len == 0) return '';

        // multiply by 4/3 rounded up
        uint256 encodedLen = 4 * ((len + 2) / 3);

        // Add some extra buffer at the end
        bytes memory result = new bytes(encodedLen + 32);

        bytes memory table = TABLE;

        assembly {
            let tablePtr := add(table, 1)
            let resultPtr := add(result, 32)

            for {
                let i := 0
            } lt(i, len) {

            } {
                i := add(i, 3)
                let input := and(mload(add(data, i)), 0xffffff)

                let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))
                out := shl(8, out)
                out := add(
                    out,
                    and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF)
                )
                out := shl(8, out)
                out := add(
                    out,
                    and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF)
                )
                out := shl(8, out)
                out := add(
                    out,
                    and(mload(add(tablePtr, and(input, 0x3F))), 0xFF)
                )
                out := shl(224, out)

                mstore(resultPtr, out)

                resultPtr := add(resultPtr, 4)
            }

            switch mod(len, 3)
            case 1 {
                mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
            }
            case 2 {
                mstore(sub(resultPtr, 1), shl(248, 0x3d))
            }

            mstore(result, encodedLen)
        }

        return string(result);
    }
}

File 8 of 16 : ERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/ERC721.sol)

pragma solidity ^0.8.0;

import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

    // Mapping owner address to token count
    mapping(address => uint256) private _balances;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

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

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

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

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _owners[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");
        return owner;
    }

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

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

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overridden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not owner nor approved for all"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

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

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");

        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
        _safeTransfer(from, to, tokenId, _data);
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `_data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _owners[tokenId] != address(0);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
        require(_exists(tokenId), "ERC721: operator query for nonexistent token");
        address owner = ERC721.ownerOf(tokenId);
        return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _mint(to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, _data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

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

        _balances[to] += 1;
        _owners[tokenId] = to;

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

        _afterTokenTransfer(address(0), to, tokenId);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId);

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

        // Clear approvals
        _approve(address(0), tokenId);

        _balances[owner] -= 1;
        delete _owners[tokenId];

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

        _afterTokenTransfer(owner, address(0), tokenId);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId);

        _balances[from] -= 1;
        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits a {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits a {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        if (to.isContract()) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, ``from``'s `tokenId` will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}
}

File 9 of 16 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

File 10 of 16 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

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

File 11 of 16 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC721.sol";

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

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

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

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

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

pragma solidity ^0.8.0;

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

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

File 14 of 16 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

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

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

pragma solidity ^0.8.0;

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

File 16 of 16 : IAccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"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":"studentAddress","type":"address"},{"indexed":true,"internalType":"string","name":"course_name","type":"string"},{"indexed":true,"internalType":"string","name":"cohort_name","type":"string"}],"name":"StudentOnCourse","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"},{"inputs":[],"name":"AUTH_MINT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addAuthorizedMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newCourse","type":"string"},{"internalType":"string","name":"description","type":"string"}],"name":"addCourse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","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":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"cohort","type":"string"},{"internalType":"string","name":"course","type":"string"},{"internalType":"address","name":"studentAddress","type":"address"}],"name":"mintCertificate","outputs":[],"stateMutability":"nonpayable","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":"account","type":"address"}],"name":"removeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405260405180610160016040528061012d815260200162004ced61012d913960129080519060200190620000389291906200034c565b5060405180613b200160405280613afb815260200162004e1a613afb9139601390805190602001906200006d9291906200034c565b5060405180610100016040528060c881526020016200891560c8913960149080519060200190620000a09291906200034c565b506040518060c00160405280609e8152602001620089dd609e913960159080519060200190620000d29291906200034c565b50604051806101c0016040528061018e815260200162004b5f61018e913960169080519060200190620001079291906200034c565b503480156200011557600080fd5b506040518060400160405280601081526020017f5745423344455620426f6f7463616d70000000000000000000000000000000008152506040518060400160405280600381526020017f573344000000000000000000000000000000000000000000000000000000000081525081600090805190602001906200019a9291906200034c565b508060019080519060200190620001b39291906200034c565b505050620001cb6000801b33620001d160201b60201c565b62000461565b620001e38282620001e760201b60201c565b5050565b620001f98282620002d960201b60201c565b620002d55760016007600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506200027a6200034460201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b60006007600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600033905090565b8280546200035a90620003fc565b90600052602060002090601f0160209004810192826200037e5760008555620003ca565b82601f106200039957805160ff1916838001178555620003ca565b82800160010185558215620003ca579182015b82811115620003c9578251825591602001919060010190620003ac565b5b509050620003d99190620003dd565b5090565b5b80821115620003f8576000816000905550600101620003de565b5090565b600060028204905060018216806200041557607f821691505b602082108114156200042c576200042b62000432565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6146ee80620004716000396000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c80635f710f5c116100c3578063a217fddf1161007c578063a217fddf146103d3578063a22cb465146103f1578063b88d4fde1461040d578063c87b56dd14610429578063d547741f14610459578063e985e9c51461047557610158565b80635f710f5c146102ed5780636352211e146103095780636d7849521461033957806370a082311461035557806391d148541461038557806395d89b41146103b557610158565b8063248a9ca311610115578063248a9ca31461022f5780632b75565d1461025f5780632f2ff15d1461027b57806336568abe1461029757806342842e0e146102b357806350e63ddf146102cf57610158565b806301ffc9a71461015d57806306fdde031461018d578063081812fc146101ab578063095ea7b3146101db5780631785f53c146101f757806323b872dd14610213575b600080fd5b61017760048036038101906101729190612e37565b6104a5565b604051610184919061372b565b60405180910390f35b6101956104b7565b6040516101a29190613761565b60405180910390f35b6101c560048036038101906101c09190612f74565b610549565b6040516101d291906136c4565b60405180910390f35b6101f560048036038101906101f09190612d96565b6105ce565b005b610211600480360381019061020c9190612c2b565b6106e6565b005b61022d60048036038101906102289190612c90565b61075f565b005b61024960048036038101906102449190612dd2565b61079a565b6040516102569190613746565b60405180910390f35b61027960048036038101906102749190612e89565b6107ba565b005b61029560048036038101906102909190612dfb565b6108e8565b005b6102b160048036038101906102ac9190612dfb565b610909565b005b6102cd60048036038101906102c89190612c90565b61098c565b005b6102d76109c7565b6040516102e49190613746565b60405180910390f35b61030760048036038101906103029190612c2b565b6109eb565b005b610323600480360381019061031e9190612f74565b610a64565b60405161033091906136c4565b60405180910390f35b610353600480360381019061034e9190612ef5565b610b16565b005b61036f600480360381019061036a9190612c2b565b610e80565b60405161037c9190613a03565b60405180910390f35b61039f600480360381019061039a9190612dfb565b610f38565b6040516103ac919061372b565b60405180910390f35b6103bd610fa3565b6040516103ca9190613761565b60405180910390f35b6103db611035565b6040516103e89190613746565b60405180910390f35b61040b60048036038101906104069190612d5a565b61103c565b005b61042760048036038101906104229190612cdf565b611052565b005b610443600480360381019061043e9190612f74565b6110b4565b6040516104509190613761565b60405180910390f35b610473600480360381019061046e9190612dfb565b61139a565b005b61048f600480360381019061048a9190612c54565b6113bb565b60405161049c919061372b565b60405180910390f35b60006104b08261144f565b9050919050565b6060600080546104c690613cfc565b80601f01602080910402602001604051908101604052809291908181526020018280546104f290613cfc565b801561053f5780601f106105145761010080835404028352916020019161053f565b820191906000526020600020905b81548152906001019060200180831161052257829003601f168201915b5050505050905090565b6000610554826114c9565b610593576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161058a90613983565b60405180910390fd5b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60006105d982610a64565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561064a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610641906139a3565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610669611535565b73ffffffffffffffffffffffffffffffffffffffff161480610698575061069781610692611535565b6113bb565b5b6106d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106ce906138c3565b60405180910390fd5b6106e1838361153d565b505050565b6106f36000801b33610f38565b610732576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072990613963565b60405180910390fd5b61075c7fe918b231727c964e85d5ce841b7b0735aa540b813b93ecc15a2cd996d2608d62826115f6565b50565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079190613803565b60405180910390fd5b600060076000838152602001908152602001600020600101549050919050565b6107c76000801b33610f38565b610806576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107fd90613963565b60405180910390fd5b6000826040516020016108199190613554565b6040516020818303038152906040528051906020012090506000600c6000838152602001908152602001600020805461085190613cfc565b905014610893576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161088a90613843565b60405180910390fd5b81600c600083815260200190815260200160002090805190602001906108ba929190612a3a565b5082600d600083815260200190815260200160002090805190602001906108e2929190612a3a565b50505050565b6108f18261079a565b6108fa816116d8565b61090483836116ec565b505050565b610911611535565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461097e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610975906139e3565b60405180910390fd5b61098882826115f6565b5050565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109be90613803565b60405180910390fd5b7fe918b231727c964e85d5ce841b7b0735aa540b813b93ecc15a2cd996d2608d6281565b6109f86000801b33610f38565b610a37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a2e90613963565b60405180910390fd5b610a617fe918b231727c964e85d5ce841b7b0735aa540b813b93ecc15a2cd996d2608d62826116ec565b50565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610b0d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0490613903565b60405180910390fd5b80915050919050565b610b236000801b33610f38565b610b62576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b5990613963565b60405180910390fd5b60008183604051602001610b7792919061352c565b6040516020818303038152906040528051906020012090506000600a6000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff1660ff1614610c33576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c2a90613943565b60405180910390fd5b6001600a6000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff021916908360ff160217905550600983604051610cae9190613554565b9081526020016040518091039020829080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600083604051602001610d309190613554565b6040516020818303038152906040528051906020012090506000600c60008381526020019081526020016000208054610d6890613cfc565b90501415610dab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da290613823565b60405180910390fd5b600085604051602001610dbe9190613554565b60405160208183030381529060405280519060200120905085600e60008381526020019081526020016000209080519060200190610dfd929190612a3a565b50610e098183866117cd565b85604051610e179190613554565b604051809103902085604051610e2d9190613554565b60405180910390208573ffffffffffffffffffffffffffffffffffffffff167f8641a4aba657b283ac69dfb130cd01fc637d86b85263f3eb21439d491bd0debb60405160405180910390a4505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ef1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ee8906138e3565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60006007600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b606060018054610fb290613cfc565b80601f0160208091040260200160405190810160405280929190818152602001828054610fde90613cfc565b801561102b5780601f106110005761010080835404028352916020019161102b565b820191906000526020600020905b81548152906001019060200180831161100e57829003601f168201915b5050505050905090565b6000801b81565b61104e611047611535565b83836118a3565b5050565b61106361105d611535565b83611a10565b6110a2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611099906139c3565b60405180910390fd5b6110ae84848484611aee565b50505050565b60606000600d60006010600086815260200190815260200160002054815260200190815260200160002080546110e990613cfc565b80601f016020809104026020016040519081016040528092919081815260200182805461111590613cfc565b80156111625780601f1061113757610100808354040283529160200191611162565b820191906000526020600020905b81548152906001019060200180831161114557829003601f168201915b505050505090506000600e6000600f6000878152602001908152602001600020548152602001908152602001600020805461119c90613cfc565b80601f01602080910402602001604051908101604052809291908181526020018280546111c890613cfc565b80156112155780601f106111ea57610100808354040283529160200191611215565b820191906000526020600020905b8154815290600101906020018083116111f857829003601f168201915b505050505090506000600c600060106000888152602001908152602001600020548152602001908152602001600020805461124f90613cfc565b80601f016020809104026020016040519081016040528092919081815260200182805461127b90613cfc565b80156112c85780601f1061129d576101008083540402835291602001916112c8565b820191906000526020600020905b8154815290600101906020018083116112ab57829003601f168201915b50505050509050600060116000878152602001908152602001600020549050600060138560146112f785611b4a565b6015886016604051602001611312979695949392919061356b565b60405160208183030381529060405290506000858561133085611b4a565b8661133a86611cf7565b60405160200161134e9594939291906135d0565b6040516020818303038152906040529050600061136a82611cf7565b90508060405160200161137d9190613668565b604051602081830303815290604052975050505050505050919050565b6113a38261079a565b6113ac816116d8565b6113b683836115f6565b505050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806114c257506114c182611eb5565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff166115b083610a64565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6116008282610f38565b156116d45760006007600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611679611535565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b6116e9816116e4611535565b611f97565b50565b6116f68282610f38565b6117c95760016007600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555061176e611535565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b6001600b6000848152602001908152602001600020600085815260200190815260200160002060008282546118029190613afd565b925050819055506118136008612034565b600061181f600861204a565b90506000600b6000858152602001908152602001600020600086815260200190815260200160002054905080601160008481526020019081526020016000208190555083601060008481526020019081526020016000208190555084600f60008481526020019081526020016000208190555061189c8383612058565b5050505050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611912576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161190990613883565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611a03919061372b565b60405180910390a3505050565b6000611a1b826114c9565b611a5a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a51906138a3565b60405180910390fd5b6000611a6583610a64565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480611aa75750611aa681856113bb565b5b80611ae557508373ffffffffffffffffffffffffffffffffffffffff16611acd84610549565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b611af9848484612076565b611b05848484846122dd565b611b44576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b3b906137a3565b60405180910390fd5b50505050565b60606000821415611b92576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050611cf2565b600082905060005b60008214611bc4578080611bad90613d5f565b915050600a82611bbd9190613b53565b9150611b9a565b60008167ffffffffffffffff811115611c06577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611c385781602001600182028036833780820191505090505b5090505b60008514611ceb57600182611c519190613bde565b9150600a85611c609190613dcc565b6030611c6c9190613afd565b60f81b818381518110611ca8577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85611ce49190613b53565b9450611c3c565b8093505050505b919050565b60606000825190506000811415611d205760405180602001604052806000815250915050611eb0565b60006003600283611d319190613afd565b611d3b9190613b53565b6004611d479190613b84565b90506000602082611d589190613afd565b67ffffffffffffffff811115611d97577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611dc95781602001600182028036833780820191505090505b5090506000604051806060016040528060408152602001614679604091399050600181016020830160005b86811015611e6d5760038101905062ffffff818a015116603f8160121c168401518060081b905060ff603f83600c1c1686015116810190508060081b905060ff603f8360061c1686015116810190508060081b905060ff603f831686015116810190508060e01b90508084526004840193505050611df4565b506003860660018114611e875760028114611e9757611ea2565b613d3d60f01b6002830352611ea2565b603d60f81b60018303525b508484525050819450505050505b919050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611f8057507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611f905750611f8f82612474565b5b9050919050565b611fa18282610f38565b61203057611fc68173ffffffffffffffffffffffffffffffffffffffff1660146124de565b611fd48360001c60206124de565b604051602001611fe592919061368a565b6040516020818303038152906040526040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120279190613761565b60405180910390fd5b5050565b6001816000016000828254019250508190555050565b600081600001549050919050565b6120728282604051806020016040528060008152506127d8565b5050565b8273ffffffffffffffffffffffffffffffffffffffff1661209682610a64565b73ffffffffffffffffffffffffffffffffffffffff16146120ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e3906137c3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561215c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161215390613863565b60405180910390fd5b612167838383612833565b61217260008261153d565b6001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546121c29190613bde565b925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546122199190613afd565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46122d8838383612838565b505050565b60006122fe8473ffffffffffffffffffffffffffffffffffffffff1661283d565b15612467578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612327611535565b8786866040518563ffffffff1660e01b815260040161234994939291906136df565b602060405180830381600087803b15801561236357600080fd5b505af192505050801561239457506040513d601f19601f820116820180604052508101906123919190612e60565b60015b612417573d80600081146123c4576040519150601f19603f3d011682016040523d82523d6000602084013e6123c9565b606091505b5060008151141561240f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612406906137a3565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161491505061246c565b600190505b949350505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6060600060028360026124f19190613b84565b6124fb9190613afd565b67ffffffffffffffff81111561253a577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801561256c5781602001600182028036833780820191505090505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106125ca577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110612654577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600060018460026126949190613b84565b61269e9190613afd565b90505b600181111561278a577f3031323334353637383961626364656600000000000000000000000000000000600f861660108110612706577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b1a60f81b828281518110612743577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c94508061278390613cd2565b90506126a1565b50600084146127ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127c590613783565b60405180910390fd5b8091505092915050565b6127e28383612860565b6127ef60008484846122dd565b61282e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612825906137a3565b60405180910390fd5b505050565b505050565b505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156128d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128c790613923565b60405180910390fd5b6128d9816114c9565b15612919576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612910906137e3565b60405180910390fd5b61292560008383612833565b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546129759190613afd565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612a3660008383612838565b5050565b828054612a4690613cfc565b90600052602060002090601f016020900481019282612a685760008555612aaf565b82601f10612a8157805160ff1916838001178555612aaf565b82800160010185558215612aaf579182015b82811115612aae578251825591602001919060010190612a93565b5b509050612abc9190612ac0565b5090565b5b80821115612ad9576000816000905550600101612ac1565b5090565b6000612af0612aeb84613a43565b613a1e565b905082815260208101848484011115612b0857600080fd5b612b13848285613c90565b509392505050565b6000612b2e612b2984613a74565b613a1e565b905082815260208101848484011115612b4657600080fd5b612b51848285613c90565b509392505050565b600081359050612b6881614605565b92915050565b600081359050612b7d8161461c565b92915050565b600081359050612b9281614633565b92915050565b600081359050612ba78161464a565b92915050565b600081519050612bbc8161464a565b92915050565b600082601f830112612bd357600080fd5b8135612be3848260208601612add565b91505092915050565b600082601f830112612bfd57600080fd5b8135612c0d848260208601612b1b565b91505092915050565b600081359050612c2581614661565b92915050565b600060208284031215612c3d57600080fd5b6000612c4b84828501612b59565b91505092915050565b60008060408385031215612c6757600080fd5b6000612c7585828601612b59565b9250506020612c8685828601612b59565b9150509250929050565b600080600060608486031215612ca557600080fd5b6000612cb386828701612b59565b9350506020612cc486828701612b59565b9250506040612cd586828701612c16565b9150509250925092565b60008060008060808587031215612cf557600080fd5b6000612d0387828801612b59565b9450506020612d1487828801612b59565b9350506040612d2587828801612c16565b925050606085013567ffffffffffffffff811115612d4257600080fd5b612d4e87828801612bc2565b91505092959194509250565b60008060408385031215612d6d57600080fd5b6000612d7b85828601612b59565b9250506020612d8c85828601612b6e565b9150509250929050565b60008060408385031215612da957600080fd5b6000612db785828601612b59565b9250506020612dc885828601612c16565b9150509250929050565b600060208284031215612de457600080fd5b6000612df284828501612b83565b91505092915050565b60008060408385031215612e0e57600080fd5b6000612e1c85828601612b83565b9250506020612e2d85828601612b59565b9150509250929050565b600060208284031215612e4957600080fd5b6000612e5784828501612b98565b91505092915050565b600060208284031215612e7257600080fd5b6000612e8084828501612bad565b91505092915050565b60008060408385031215612e9c57600080fd5b600083013567ffffffffffffffff811115612eb657600080fd5b612ec285828601612bec565b925050602083013567ffffffffffffffff811115612edf57600080fd5b612eeb85828601612bec565b9150509250929050565b600080600060608486031215612f0a57600080fd5b600084013567ffffffffffffffff811115612f2457600080fd5b612f3086828701612bec565b935050602084013567ffffffffffffffff811115612f4d57600080fd5b612f5986828701612bec565b9250506040612f6a86828701612b59565b9150509250925092565b600060208284031215612f8657600080fd5b6000612f9484828501612c16565b91505092915050565b612fa681613c12565b82525050565b612fbd612fb882613c12565b613da8565b82525050565b612fcc81613c24565b82525050565b612fdb81613c30565b82525050565b6000612fec82613aba565b612ff68185613ad0565b9350613006818560208601613c9f565b61300f81613eb9565b840191505092915050565b600061302582613ac5565b61302f8185613ae1565b935061303f818560208601613c9f565b61304881613eb9565b840191505092915050565b600061305e82613ac5565b6130688185613af2565b9350613078818560208601613c9f565b80840191505092915050565b6000815461309181613cfc565b61309b8186613af2565b945060018216600081146130b657600181146130c7576130fa565b60ff198316865281860193506130fa565b6130d085613aa5565b60005b838110156130f2578154818901526001820191506020810190506130d3565b838801955050505b50505092915050565b6000613110602083613ae1565b915061311b82613ed7565b602082019050919050565b6000613133601d83613af2565b915061313e82613f00565b601d82019050919050565b6000613156603283613ae1565b915061316182613f29565b604082019050919050565b6000613179602583613ae1565b915061318482613f78565b604082019050919050565b600061319c601c83613ae1565b91506131a782613fc7565b602082019050919050565b60006131bf600883613ae1565b91506131ca82613ff0565b602082019050919050565b60006131e2600e83613ae1565b91506131ed82614019565b602082019050919050565b6000613205601983613ae1565b915061321082614042565b602082019050919050565b6000613228602483613ae1565b91506132338261406b565b604082019050919050565b600061324b602683613af2565b9150613256826140ba565b602682019050919050565b600061326e601983613ae1565b915061327982614109565b602082019050919050565b6000613291602c83613ae1565b915061329c82614132565b604082019050919050565b60006132b4603483613af2565b91506132bf82614181565b603482019050919050565b60006132d7603883613ae1565b91506132e2826141d0565b604082019050919050565b60006132fa602a83613ae1565b91506133058261421f565b604082019050919050565b600061331d602983613ae1565b91506133288261426e565b604082019050919050565b6000613340600283613af2565b915061334b826142bd565b600282019050919050565b6000613363602083613ae1565b915061336e826142e6565b602082019050919050565b6000613386601583613af2565b91506133918261430f565b601582019050919050565b60006133a9602983613ae1565b91506133b482614338565b604082019050919050565b60006133cc601d83613ae1565b91506133d782614387565b602082019050919050565b60006133ef602c83613ae1565b91506133fa826143b0565b604082019050919050565b6000613412602783613af2565b915061341d826143ff565b602782019050919050565b6000613435602183613ae1565b91506134408261444e565b604082019050919050565b6000613458601d83613af2565b91506134638261449d565b601d82019050919050565b600061347b603183613ae1565b9150613486826144c6565b604082019050919050565b600061349e602683613af2565b91506134a982614515565b602682019050919050565b60006134c1601783613af2565b91506134cc82614564565b601782019050919050565b60006134e4601183613af2565b91506134ef8261458d565b601182019050919050565b6000613507602f83613ae1565b9150613512826145b6565b604082019050919050565b61352681613c86565b82525050565b60006135388285612fac565b6014820191506135488284613053565b91508190509392505050565b60006135608284613053565b915081905092915050565b6000613577828a613084565b91506135838289613053565b915061358f8288613084565b915061359b8287613053565b91506135a78286613084565b91506135b38285613053565b91506135bf8284613084565b915081905098975050505050505050565b60006135db82613126565b91506135e6826132a7565b91506135f28288613053565b91506135fd82613491565b91506136098287613053565b91506136148261323e565b91506136208286613053565b915061362b82613379565b91506136378285613053565b915061364282613405565b915061364e8284613053565b915061365982613333565b91508190509695505050505050565b60006136738261344b565b915061367f8284613053565b915081905092915050565b6000613695826134b4565b91506136a18285613053565b91506136ac826134d7565b91506136b88284613053565b91508190509392505050565b60006020820190506136d96000830184612f9d565b92915050565b60006080820190506136f46000830187612f9d565b6137016020830186612f9d565b61370e604083018561351d565b81810360608301526137208184612fe1565b905095945050505050565b60006020820190506137406000830184612fc3565b92915050565b600060208201905061375b6000830184612fd2565b92915050565b6000602082019050818103600083015261377b818461301a565b905092915050565b6000602082019050818103600083015261379c81613103565b9050919050565b600060208201905081810360008301526137bc81613149565b9050919050565b600060208201905081810360008301526137dc8161316c565b9050919050565b600060208201905081810360008301526137fc8161318f565b9050919050565b6000602082019050818103600083015261381c816131b2565b9050919050565b6000602082019050818103600083015261383c816131d5565b9050919050565b6000602082019050818103600083015261385c816131f8565b9050919050565b6000602082019050818103600083015261387c8161321b565b9050919050565b6000602082019050818103600083015261389c81613261565b9050919050565b600060208201905081810360008301526138bc81613284565b9050919050565b600060208201905081810360008301526138dc816132ca565b9050919050565b600060208201905081810360008301526138fc816132ed565b9050919050565b6000602082019050818103600083015261391c81613310565b9050919050565b6000602082019050818103600083015261393c81613356565b9050919050565b6000602082019050818103600083015261395c8161339c565b9050919050565b6000602082019050818103600083015261397c816133bf565b9050919050565b6000602082019050818103600083015261399c816133e2565b9050919050565b600060208201905081810360008301526139bc81613428565b9050919050565b600060208201905081810360008301526139dc8161346e565b9050919050565b600060208201905081810360008301526139fc816134fa565b9050919050565b6000602082019050613a18600083018461351d565b92915050565b6000613a28613a39565b9050613a348282613d2e565b919050565b6000604051905090565b600067ffffffffffffffff821115613a5e57613a5d613e8a565b5b613a6782613eb9565b9050602081019050919050565b600067ffffffffffffffff821115613a8f57613a8e613e8a565b5b613a9882613eb9565b9050602081019050919050565b60008190508160005260206000209050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b6000613b0882613c86565b9150613b1383613c86565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115613b4857613b47613dfd565b5b828201905092915050565b6000613b5e82613c86565b9150613b6983613c86565b925082613b7957613b78613e2c565b5b828204905092915050565b6000613b8f82613c86565b9150613b9a83613c86565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613bd357613bd2613dfd565b5b828202905092915050565b6000613be982613c86565b9150613bf483613c86565b925082821015613c0757613c06613dfd565b5b828203905092915050565b6000613c1d82613c66565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b82818337600083830152505050565b60005b83811015613cbd578082015181840152602081019050613ca2565b83811115613ccc576000848401525b50505050565b6000613cdd82613c86565b91506000821415613cf157613cf0613dfd565b5b600182039050919050565b60006002820490506001821680613d1457607f821691505b60208210811415613d2857613d27613e5b565b5b50919050565b613d3782613eb9565b810181811067ffffffffffffffff82111715613d5657613d55613e8a565b5b80604052505050565b6000613d6a82613c86565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613d9d57613d9c613dfd565b5b600182019050919050565b6000613db382613dba565b9050919050565b6000613dc582613eca565b9050919050565b6000613dd782613c86565b9150613de283613c86565b925082613df257613df1613e2c565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b60008160601b9050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b7f7b226e616d65223a20225745423344455620426f6f7463616d70222c20000000600082015250565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b7f64697361626c6564000000000000000000000000000000000000000000000000600082015250565b7f496e76616c696420436f75727365000000000000000000000000000000000000600082015250565b7f436f7572736520616c7265616479207265676973746572656400000000000000600082015250565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f227d2c7b2274726169745f74797065223a20226e756d626572222c202276616c60008201527f7565223a20220000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b7f2261747472696275746573223a205b207b202274726169745f74797065223a2060008201527f22636f75727365222c202276616c7565223a2022000000000000000000000000602082015250565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b7f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008201527f656e7420746f6b656e0000000000000000000000000000000000000000000000602082015250565b7f227d000000000000000000000000000000000000000000000000000000000000600082015250565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b7f227d5d2c20226465736372697074696f6e223a20220000000000000000000000600082015250565b7f53747564656e7420616c72656164792072656769737465726564206f6e20746860008201527f697320636f757273650000000000000000000000000000000000000000000000602082015250565b7f43616c6c6572206973206e6f7420616e2057696e646f772041646d696e000000600082015250565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b7f222c2022696d616765223a2022646174613a696d6167652f7376672b786d6c3b60008201527f6261736536342c00000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000600082015250565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b7f227d2c7b2274726169745f74797065223a2022636f686f7274222c202276616c60008201527f7565223a20220000000000000000000000000000000000000000000000000000602082015250565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b61460e81613c12565b811461461957600080fd5b50565b61462581613c24565b811461463057600080fd5b50565b61463c81613c30565b811461464757600080fd5b50565b61465381613c3a565b811461465e57600080fd5b50565b61466a81613c86565b811461467557600080fd5b5056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa264697066735822122075bfce8047c5f4ef85a051e11c43ab1d08b41db01623de1570eead8e63bdb6c064736f6c634300080400333c2f746578743e3c7265637420783d2733382e31332720793d2733322e30322720636c6173733d2773743135272077696474683d2735352e373727206865696768743d2734382e3436272f3e3c7265637420783d273131392e322720793d2733322e30322720636c6173733d2773743136272077696474683d2735352e373727206865696768743d2734382e3436272f3e3c7265637420783d273230312e31382720793d2733322e30322720636c6173733d27737435272077696474683d2735352e373727206865696768743d2734382e3436272f3e3c74657874207472616e73666f726d3d276d617472697828312e32373634203020302031203133382e34373137203130312e33323238292720636c6173733d2773743133207374322073743138273e2d3c2f746578743e3c74657874207472616e73666f726d3d276d617472697828312e31373831203020302031203232372e36373732203130352e34333039292720636c6173733d2773743133207374322073743139273e2b3c2f746578743e3c2f673e3c2f7376673e3c73766720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f323030302f73766727207072657365727665417370656374526174696f3d27784d696e594d696e206d656574272076696577426f783d273020302033353020333530273e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b666f6e742d73697a653a20323470783b7d3c2f7374796c653e3c726563742077696474683d273130302527206865696768743d2731303025272066696c6c3d27626c61636b27202f3e3c7465787420783d273530252720793d273530252720636c6173733d27626173652720646f6d696e616e742d626173656c696e653d276d6964646c652720746578742d616e63686f723d276d6964646c65273e3c3f786d6c2076657273696f6e3d27312e302720656e636f64696e673d277574662d38273f3e3c7376672076657273696f6e3d27312e312720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f323030302f7376672720786d6c6e733a786c696e6b3d27687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b2720783d273070782720793d27307078272076696577426f783d27302030203835302e3339203835302e333927207374796c653d27656e61626c652d6261636b67726f756e643a6e657720302030203835302e3339203835302e33393b2720786d6c3a73706163653d277072657365727665273e203c646566733e203c7374796c653e2040666f6e742d66616365207b20666f6e742d66616d696c793a20274d696e65637261667469612d526567756c6172273b207372633a2075726c28646174613a6170706c69636174696f6e2f666f6e742d776f6666323b636861727365743d7574662d383b6261736536342c643039474d6741424141414141435a674142414141414141705267414143582f414145414141414141414141414141414141414141414141414141414141414150305a475645306347695947594143445767674f4359526c4551674b6771525567665a4443344e534141453241695144687941454941574848776546535178634778654c525164796a774e49316732694344594f4176786d3534324b6369364b4f50762f6c747751555445376744563957776f735a6970502f43784d626e516874546272445967457075556759525875314941542f545047754b357836386b34593479474c6f454a5337494d726732626c2b633635772b6d59366e334354762b6d65386c762b3654354d5957584854724969514863336f47746f333853553565654b42337274366b6d536a307375594472456c687861797245747055774f7668524d572f6a4b467a7251516d4d6837706a6d63544334724b6a797152463477696548364d656538626f6f6c736b5572335a6849616f5973336d44617a764c53384e453861523574593648717831765a464c6173303166627a315130496863677733554f6b53524a4e46784666784572434c2f66374e787641472f784173444d6e4b6b4b5a61766c5568666c513457716d5773377667694234426b5478394f504b54654678315566644f36524141627868672f6f58392b4d7a625a4e69437651656636433747777144647059634b5473332f312f6274386d36773765626e2f584a72496d2b344e714a395a78554e584c4253793071733671446846314a372f2b4e66765651315454766a414c376c49733772394148624d427739306a473050644e2f61517a5835626231545255756d4136594a3847774341697a5768327256334a396d2b39792f634f48557044415479504f36565556696f676f516b6a49536741734c79773350387953317256663754543352634464794a4d3275435141444a41426b6a364e622b2b646e37507a4f3630546e4f336f777368494d6570726d6d706b7a624d796b46377438344a3254424351794d7a6b67437a49626c6a6667624d69323569715741614a50584174582b727151624a575633547a585270523545566c6d45596e553451434b47507a38316c7545794d69622f4a3655614641695545416b6e6c2f33342f2f6636596264372b743757386c34686f70386b6744444f592f4f6344424f434430394536414b394e584c6b412b4f54682f703041566143766f5453433843314242786f515149424950534c704a4c33516755616e417831422b41416441467947523664672f7a3441774c4c317a52745a6f5071336e41366947413378482b436f41696743524541454443594176435643674d463039344778464a326a32694559644c4e4a72575263616838707471724351535352526950614d59546a6550696362766a336a77424579713759636e7330474164526833687545506737712f7476587a6f316c72762f686c6434696b6434776a317563494a74354a4638765433383062344739774f6932627367556d4d53784c77717458555559315757565958324c30716e5458314459314e7a5332746f6f3762326a7336753770376576763642776148686b64477838596e4a71656d5a32626e356863576c355a58567466574e7a6133746e643239665847484468383565757a34695a50424d63634b6b75576e56566d336d6e61333378734d7836504a644c356372446272772f353469677a6c746f4c73787976467550665645734e7874364538307473417442787733524f5748674b30486e355335566139323476726d346648323774446550776c66506e703766734877764d6e4f4f6f79723469616271694f433531314e346d6770313950494f6743494767454855757164434b436651795638317a5a4543376463417a4d5a4231314b4b4f752b373366642f677949565732315555554672386d33444369744d74624d6d75636a716a73785472776c7733522f4d5646524874594857333048666b624155374f6f507a765a2f53744b736c354e2b64754f482f38376e55527952627650685252323663763672695345412f2b4f68496a4f494c47506e33627a55307374726169484950744f4f777337682f6855332b4d4145395544597347784d596c42687555502b74507771776369476e74596e374c32654b6a785a35595a316d736a50726c534c443464436f6c78732f5254684d65455744657a4a3238424d475a5534655469346d6f41565468512b437278714e39505a5978497a6478516a61353249306235757730344e7545556e6630473237534d587754733176537a4332437345764c366e3036737a55524f664c6247386a79646b78544f5048454768644e7371394c7630707a306f5a7a5836493235524b67324e51766a2b4c476d7648764a514d314a316a51644c42622b4e37386638367153326536546b4f6a3668714a7666572b353744505951494f54553270374a75796f416139305a374e6634717038357559557943596d526941474854674c3361395a77464536616c6e4369706654357a6d67624e786e4b357036656b79685057586a5967492f4b63622f494c345142356834427444593442685675376e3061623770396435304179792f694f755931463253755449575346574167526742624f515a517457396c56785a2b5669652b66713969686234356e6759654f2f7a5a347a4d5a4b7a732f695351374b384d544668702f6b776c376e7a624741626a4a675a4e34666170452b3450585872634a59534b4c6535636b41524b6c34736e746b2f36362b7746566c7679695655507a6c79516a595a6a35354b6d5752616e4d66684f324979562b595a58545341396f4c6d4369742f7839522b5a3369634d42633342542b31716f65683154306d5a6754712b364f6a3374444364366a3267576d6632744d4b50585879467939354366764b2f6c6c52584239625831567366685449726e683936724e6f3955702f676d5a4f42372b6369376f6a4f4c693166726236415058634c716539374f332b614a334d746155505a35557a795338425438554a385a582f64486e71497a334976394b38626a766a5a5357642f4a754365555452713258417172373438366c7a374b31647a516e2b5a324c474b516e4c4a33615657396e6e79326965444f775a4d3074494c414874706e504a396a59346268637658512b443347697a6679726e52776241675a384d426a7075474567476a684a694a615177774455656d483578653866484a306d4930376c48584241346b36637530316c4445596168714239336457517954615278544e775243646151723146434f686278306b79633459524b757254446d6148737573425239673638623136444d62306d652f4f313662367432424462474537514f61416957426b51696e6b4b51396b3771724e504c7a395a596d353957684e6e44507a6e52737a7a32555947566946414c73535166536454766178334544665654304a47786b6e2b7671516d546f755973494f6a68416d436b2f2f75654a4149795546566956525732744b53395850493436437943697a5545345a566b574d4a526a496d664f74732b462b375241327a6d7a466b484771724a5838366339504b4d6c624f644d632b497076435968655968676c70557162426a6b56747655365a7835594e337a6e4d713955766f2b42305258716b31536456674954686c47697a5437545445353843647757436e38723431325158674c57326b6731757a616a446b6f7654792f396c666b344c633467475963546a6b736238464531534e5635774b354e30774c65534f354b324c5333346b346b76545543616e546c7a624c5275434b597131396f7a626e56717a3651342f336346477336684a6657426a4b31627a72474a58446a383038524b57674a56594c6f47313456596c306647475a6e465059654452636d706145753370626a6b6e50323270744b556e41482b4b4e314a325a6c617a4e736c61687245314b5a4857626d4a456549594c52794a4361594b6b524a57346d2b4d547333447646437835486175772b31534d6d4b4c706b54794b5048676a6c76436344346e57516f4571355765564d336c4c7864495259764445334664554d74624d62563036445a767555464a454d543657387a79574962304165574273477a54344c473565314c6573316768645572736d46686b62425a34654b516a7a3256484372427469634e725858344f6c516262697a4653537932634b4a7a6477334f58496975464f70524f303931586837344d2b6f6359684b57496d31425947324549546f49394a764667435256486c6c4579537957567542387156354369494e486278547a685261575658576336516864556a70386f56455857484c4d653961497852344c5a797052523844376d6b634a6251624539704655713075572f79634446764c56444b544e4a736b6647626347377247424b6c4f596a36626f4d77374d4b4e647777395a6e4a6e5255525838735767627a503545596e43523569396e4933353866754d6d35554d325476655641556d73306361676131684a7a3849347146552b714a4339376c4a3354536e54437546664c5744504b4e30444d6746366b574257384d36354a7a594339627156487a6f36306c426a52516778704532554976562b79345a426544586f716752525133534772485751477a3839463141676a6a6c464b4565724a73574176547977506e4e70567a6f494e6e752b2f5951744e446f654b4c4558452b456a72707a6e625265453330316f4b79566d444c486a3535717a306e535865486d6d77764e6e62385437374e4e754a334d4b2b4673466445305430316454644a4138463078304b4c6b38645651437a594b4273535a796a716f65686c7437394b616956724a376a327334354b51775a3063657a576654734579476e50536d5774302b587a54734956445a566a6d514f73524a715365333453394559333075674447486949354f45494371694b62557a50793158543162636c6538774b4e5667514a324359565a327657695366367178772f4b3043795675474f524e45744b77564f4449585841565a2f6136626b37334155357035624e4a3055564f774445576455314233615974366f6e4a6f56715057524956754c7064715755706c6261585766774773436f734156794c695734744d3957712b5a46764c79754f556164517351303079314153584356784464782f4669366761684f626d6d5a55724e63586667477932764b68652f7a5242682f62742b366d727a4b6c737730312f584d586246445669754651434e73547a71384d637945336a3874632f526e33697067304a36503676416d6b53782b497a6d3852452b2f3859446d4a7361782f2f6f734e49674665682b63323842734235492b6762544a4663493663796c4e706c58756c50564c7343662b4e7935423331644c4350314f43666272546f50336767453348516a77514d6452726633735541726f71313844386d77555839727868673263364b654430526639437834786d6e7034314c483755547633624e374e747473653934355774354562497350475a52723052663569674f443348355676754f7a6c732b51742b56547661504259656f6e585242676c7231617432364c655274764c30796f396d4a353759326345434d4b3065706c424f375556326152794338664368703549596d314c4e6c306c58566550394f75306d5a7774693150534e6547324a6672704c7751386c375a764850494f366278766d376254504338756c554f73626b397048705a4767326b38576e3471376d68685833656c525a327647682f576a555272745770654144657831534d4f7651644861344f30726479755273574f647546486943634f4e523857414832647532413032393468392b5a526358635938384d6f3378517a6a717536316a65665939627043784e354c326a674a504c6b743559752b6a46334f5664346f5034597839394f455149654c314a774355345058326b376a6b4a614278316d5363306837767a345252315763444d4a37784f786355434d6a792f55515a45784b6e766f2f6558726b31685741326f3979367139766232504c6a59652b75786c77314a73324753464b596250576c632f4d3959306d357363734f5448686444516447782f45476375776c4c464161366b7363346666374c5157676273786b6d4c47684f38766f3147337a76704247662b6345527775317a61332b64476b424539722b434839556c78313071354e3430786e686f61746f6c3474684c4f4a397a52734b4169502b48383344417059686972302f4878797779764863736e48557756534d5a52625254465776747555513656622b6535544232424b697031624f61696437726a49685848703937587676342b684246316f6e46613757654e6a644557397a46675047504b6a6c527644684e4e73427a496d3630616f636e723939354370752f6d6832756e683446616c4276724e74572b6950723258647677717275585230444d6242444b2b655854557843756244554b7361526c4e3538324b577737315a5043315744576b4e386742395937636e4474626a48566a4e69355a666c3965676933643844344f50645171356a542f6d55682b79397854464e6f39674f68326878527664766632386c746a544f777a67654b336c72766c737065706b5a763151464a366f737a57392b52524b6b6b6255575331494f4b6e764a7741304d6a54333033326f772f3464702b305a74626172574e2b41384666613742746e31377963493347592b43464c4e4f74747635724a635468325663654f37736363382b4767372f55503452536f6d63644b306553673176466b35697a62373154436564754f6a566633476e7172313873433666574a743632686166664e71754f547756775841786132742b64626b6f323849352f72456d2b36426e32574a3439754a68757647454f2b525a556a634a4a5938343065357642395a334c457277453467655476626878336d4c4f61366c513535303964776f6f6f792f30735668416754687655773246434d77357a7a4c347a4f66626e415468312f794d48447a6f63424759615a33416932754145526f73524a5930724e36635937584f4b6a42494f31394a3650504264422f55794f3559794d7172644474763371574234776d6f34446b5461635655463859356e4e495a796835496f6b7144775332784b7643685a70656b4d42753476367273334c684a62552f4a6f36636c4f725474616433487769627234587371775a6941366435653574456c57334d6163773954495048343131776d37574b65726b496d367757325a4f356d74724f4f6d2b6a65363476345a2b77715937353459642b3352624d33616e327272394d454e736d6b654b6d6f72426b572f677947503174654c476f39796b6a7544776d397a58415963553831726c4965316463795a71776269476342525a33682b7531393368666a2b4561504e76314b627631644253642f566f42706f4d7362612f2b4349337856674258314233466b476468417139595747526e3370364b314a314f66672b76357041494e5449623867664a4550734e71676d6b68766433516f484d317a4e6a2f636a3461686c587257387971517a5a63475573486c543271594d4c736e357467704c63706472655639547a6c4f5868742f4f65446c44515237633648304631564f746479714d67393346325966532f43355739416a774b673270396a596651664743425964464b786661344c4f33635859485143442b6949304e623352434e4c30514d67325879546c3530567443706f4843364245324a6f3831646743373634423746446445654c49764a697139525a6b59386a7067455975636d4c654a6a45683467737a5a437a596f634f6f737246786a592f75706853697a6c3939736e57464f32345252337862584b39584e2b334e3130456d41634954554466503647476351396b634d59347462394d7270666348684e4c51634f47454f7a54314f64336e554c4d426f364c4864576d6c364176744748696c2b72514b4e726948432b5933502b416d656a4c674456386e507541585834566779694b2f4a6252484f34324e766f58673844327647333043624d4743647759506a5038474b5a68306a3741366f47593671304135723452712b784173626c47354d39624f4977515461394250505442756d684b30477039516538455275563969776548517a6154497a7269456f614e432f354559614762714e5a683871525a5667444d422f457765684f5565363847654d622f6c68784251334d2f6879334d534e616758454845526872457a462b4c446a396a447a4f682b336658654d2f597464472b554478634169464a4249745856774a3139536446393331783059494841506136337569675569452f575158715137626b677568536a747036556945466b624d69325043755556504642734d444f744150444a7464355466583752687532664c2b35657577393767756c787365627a734e395275783732354e4976526a635031784836666c523074485776656952585163675a795a454949336556455a694d424c6b317643784568395555567171524b7a454f62774634527874787734617a5973726f68314e34664a4559724d543441696949314135466d537854354167356f6e784563663645674e4573673137374a7a337650364f71507263746e65394e6a6672524f64387a7a592b75534e496d54506353464450664b73473064726c4b71392f44714f50767254356a2b66586b56442f6277782b78535775432b714850794d41726f6d6c794458324241694f63594b364e716d4968727978594156453132424a677a334e50634d516b71304d764b704f37685763665a767051615661375767497930515146434f7275734762733937515573666d757a527663616248394b4e6b79453632367279376d6d5a485539442f516c4f48506d637556476642306f4b74316f684947414b63643656445475465445694b71714d62737154705a386c49414e4a5431574a544a5452734a6468376945745753684d43464b5768716e70727361773146636c41415354303732456c4f65657759787a59394575667864793045504974716f687a3342686f796a68365459524e73734c36593068732b6c65673848756f4c3049753159334b467144714b374670545a66667841475374306d6e58312b3944586f575336383252794f344471496a615348647971393674316c4d396c4870567466464f4b4a6b755147652b4a626e46697275537963426d50446b524147734d7737637051776c574c2b506e304e2f5373686358644c4b4c4d534f41424231796e6e78636b73565446555352496f75654b2b724d52554a4f667132647a464a42556d6f53346e464a78387a4c6d496b6e7533346355396f774b6a45454f5a7a4d306c6c6d554c687249426c62537945395a51615a634177735a752b4b4d4236633152414862586e36315841635a6435307a574a396f6e53706559702b3968574e306a46673368784a77452b795961344639365078595a7537524d65583839416b7767536f5571384e4138314451734b6a65565943796c565556476353667a623467426a5a715165745669667a4b694e4365434a354a5370313466744f35554535315243694368686a796a6c68674d787151344d4332695365703151516f543250514f437048556f75442f567959764e71535841696872314c633442362f454273616e7947324365514f79315346747a2b6a4854556f35586b704146374455373559636c52796c55737347644154384f7777786b50526559427070755a514731552b522f595a62504e314430323050345236734c3161444e6b3358796769706a424d62687455786b4e696f7339304755614d45787148344f654652686c505936352b2b676c463965386b5744446d7261654e35596e53677348337951502f776c6a576464676453577a682b4f4730754f6a57314f57695133474b64633959424f527763316b69557a4863446d4254705563727347687878686c3948612b73424d3641636c353177494e7a524d33345973434a6c747a736f30525a726a4856794d445a6f5763616b6b307434776a384a43716555426e3070696c577a6f63396d46687569416c4e394a4443554575363634556a624c3836754947533277334c32656d2b6969414e513631654d6d464a4d74495a31316a5166484b4363414b48665a426648586454486b475457795473427751654a646b536b4539734a6c6e54714744704377387469527975645633556672695253454d6a73583447533278346a5353584e43352f75364e532b6e72534d52633859496e65487956462f694f2b527646525349767963655034506a43554943454d754967504d31326c3572494d61585050452f707174756b566e3969573856694653555a77566e6c446164684f57725a444938327177344f596e4674652b5974766b4e63344c6a643641494142414b307872367031714b3551727271326e4d794b444a637a757944445a532b5045512f467031794b6c744541504f51646a494574673953633559356f4e3330616938365430527462734b43666167704638703973564d6a636250784d3832452b684579626b5a704463575637376147586e53584d5a4959453152714c306e752f384376786e42467853577450486b46634e363662674c66504551436768564f492f336765774855706a71686a6b583575555a4261444a336d726e2f4259422b455561512b6e5030485645584f7868474237572b65736b46433553597a65694c6d61525450454539706f75724b41424268454277513266774546663943546d7030544f6a316753747179414c4b5232343932344b487875647737686346366477575368576d2b72306968524a4d627463472b787858397746414d47707269384861454c61356d66767565556d753065306c7462596d527778714643674448555a66763252592f496e396875314d51705138494d6c4d3467794f59593052486b3156534942555a6a4c5551564b43594a5435756f4278753134595949364348534d59683774317070666c5633624f6744743533516c6d71614871536844775941412b3936527a6a4c723953735734436a366d6733684d6156465a30496361477344783448624b72446a54457271386445543579556f55533255426e47695052337859464b557345514a5a35537730656b53777573534973456f6945553158553743795753644c4b37772b4566434a4b336b474335634f4a59306c77496c34466371706a6842616a4e634362615962363769476330476a33726f7376324a634955424b5a70632f692b6b457a5a773136484167374674594468454d6c664f35705130702f39544776486535736f6968696170314751307849376c316951522b32437674443436765570315a4c4461446f715773756c73742b7a4735434637712b366a556e554247456b6447504c35314166694a714d48716b39482b345450475166654f62495357434f33346f447756346d496d344a316742636158434f52644372776a637559597043327152656a66567a332b2b79715a35366a5a6a77422f4f72484b386738445437384e3036416e33374c454b424957453771484842704b50726e353574527943776956576d5565637758336b4a434a4774356277487a45614e456a6770334758626849302b7961656d4e624362696441786e7177432b4f5a4943455568455749617331304e562b56344f6b62746774743465514e3150434447573434334267436563754679754937736b5a797134725163354a5869454a387465574652316e5544545679426d4375585647436b42323270497568373272596763417869446430713461447747556f484a4e2b4a6177486e4f425462443658595762344d367775515935764830364578497049714b495239374c61653646684a694d4a484f4f75786d6a51536b73566e31614c765078475439383351372f44797842376b6b6a4a334830496547685143715067614b6243756b7078716d3241615145504f692b6b50774264794f336f2f4b4b6c75476e754f774653634c4157724d6d734842533771557a6652446f7038795146634e4741436459526f35525a5569464f55786257766f425572584e434738685846734c36546e35615943426f566f30586f6b746d6d4a3533354f4e62452f3170613254464b5a7949424b69376e75726f7a6743717431457a557a4454426c78702b714a374e6d7967437973624e31426b32636b356b306272324c316f484d5341646e30746a44373277422b576461744b593175544a4f5273334d47316669496d417747785661655a3479435258326b55316b6d4b564434334965534b78736a74327a6d4279305a7a4e455438506f79414f4452676f786268685a6b4d6f69574862627a78522b416849786c66706d435166446f61475a3352694c694669523145482b55544665595531757448347065374d5179534b755639654e3836646a38424a7a7476306350636556434e616d56653534776f65396354456b2f56393142356571415a71387177532b5066475a2f544a7167413366794b45537763595250644b6f325537704d3666645173392b4e7541427639372b5775454c585042386d64394b6236355876472b71634a66525936734777576e362b51552f557961442b374e2b743732653848594a337a73526c6732544b46396d7763567954634e446c306a6d3761505a42504e4d3965774633594145727947547278376b6d42726b557965384a2b4c4735656f463135737158322f3751385647686b2f4c6f666356667433366e543167496b6c576d5670516f566e5078454953584743335575494a4833436634374f414f2f73714b4d46766e2f71322b545956384c72613739324767586e6d506f30576845366c4b4e725730414a4379424e5367556b772b727064522b5635437a5071576f4473765a2b6d44596e4f686972436d6d647464374c327970716864747962654532354b542f31376843736f6d4d6a726a616d61487761536f386b72614b6c6d717845384f42566237434f73545732707373304b4d45634b564959717a655a744458414177417778594b674f414c416b2b4a7076624d714d33706b6b7277386c723563785a365364767a396d7348655a545a684f4168414b54304f5a5a70567a3256664f77754d70644c4e75327745654141494e3375736d4f753558707651646d444f6b74396158773249326d396f71484f5a413177714c414a3645325a6f69354e7a79476b655358626e43784469504b316d416c4658563130562b33765850506274785933725a51494d7a384a55436e4c4b4e7566517950486f4c5765794138734543383768356b6a384a6f6c7877685359544b596555756e373067386c5272443161462b33356356514b53555a5579624b347745336351524a6c37303668464e426e5645457855726d426b63525968474b744336723259753069703361553379317576354977354d7159716e3247443068734c3353574c744f6a543255773142674c52356d55496e45316d5672512f736234484d69364674426f325a6c6959442f55767349676f77576950587776656f4c4c68314a63635961675443555544434756714539362f4e656d6b7336776136546b395278482f46775944615a73774863316f2f5745524b47496167335852674d7064524a7a7067454d677545766a53554f4c697444614b643344536c4f454652477633705a69684842723565545963324148623361617133317a794c776f4f6f6574665066714e3734726754396a5a516b7253337545654f556f4e312f50636e586337723354456563446438626c3153524477503936676471556e576f5343534542647074486f394c6f6b5836437a4e414d74625161636e4a313356504d35783839697348634468415567776f756d4649766d5867394f36464a56504a2b6449306c547054553863694a4b525a717032544b464250636d776a4f422b4b504c656d4b4136423857313932746841454a2b73446e5972614d612f6e4876703233323774616c5a376966364878684834614459556964763130734f325138776e6a7934324b396b2f636a58677243777647726f6d6b6f4d666a614c6f7a71677672554179627976517450563355534b5a6a50544d6e466669792b4e35344e5368686e58665267594b664179545238674b66717a62385a43752f71666863767a6a415364472b5a492f6234556d4c796d6b6d626b384d524b474f3638534365556c4830416b5a35474b39764e6a7a7563566b6f517553366b355665484444524c4470415635642b685a4e6d77546757706535516c69326c36366f586c643478656a624f332b746978765253726a2b655269575469396c576a66646565612b6b2f634c6a3970307850774e476659465058594c627248787666416b4869736838712b51584b796c59514f6f6e5878497149514e47314c497745566a705168453054463041397348754661345a6c3979456949463175624764646b415a4d4231474b543452513259756d5a4c504a48416139496f4a4373387a5232414d56516264676c424433724c6e475a56764842704464365671706a332b626b46716767453743662b494a584947706e735a4f6a344d516c48507a7834353348612b3672635536782b464f324a48504d6f6e507742323766644f324747424231782f32694f3646317471755141376c7855566566454a385433764266614a384669336450704b2f71416c3232616e4d4755367a785a4b49734a584a32776a3031754f75474a74384a4430364a4b58475a6d3644454b5a52516e4c6e4b55705254596250614e4a5539326a414f675a434674445658796c6c6a774c386741554359462b4868375737654568396b4137615a7147614354362b484e372f7a4d6e2b3850353471686553735072756b676b766d2f656d37766366576137365a624463392f6f356272303561316e79423249424c7235344b724d7934434d523233346943626468756a44556535427475556a38696956567064426639444859596a6f626948487478736a564f4c59543132516f667a2f3065502b726d4a524234324c2b624e34626f4f515761667a614355357665694a573736596a384c4f2f697a59542b6d7759345a4770463134426563777a51576559337a6d4154376272436e574b727761462b767936486662544a36416870795a73516c2b74746348536b4159386d533877574a76492b562f56424b37532b4c6e6d6235683647586c6576676953323742614d6a4a516d4337722b477348705058555866654f656b683751474a706a53746962496b56783842465448692f56783968614d696f2b784f617966747079477444514157582f4153363142576e6862686c706479366d2f44733677634476694a70566c6a45392b6a6c53545653364d437146736748367a365742467037676c637542354a71544257376a48615172567830376c786b717a493570714d65794848502f594a55644a784c36507961527337453142656c73363431504542384f705a47785078734e7a6c725432696c316e4833654758487667386e6866356c626b32314574665163593472614e5470695535696b366652524a633573425846384a2f52374c6f5861554f744f333878664a4535493855763573706d4477686f52712f57675371727358434832554559623364776d452b436d63366c33764c32536b346d68765175526e61595277315430654e4239684c70336b2f7a754a4a5979383178304e452b6f534c794b61365a6e50735174734535796c6a6938416c4f314a2f4f75636370794e567776564d4739784530694d5334786946524b6b5036365866612b784e572b2b506c794e692b5074502f63797874452f6a57484370496f56456b695175485a58345034692f4b31507a514b44552b314b657973332b6f30364d2f6438674c3253377548674c49736562634f38467032694b6e6f49424d715a67507861756a58573067655432586862796539326c517a51677744564b306c61355059436b4c6873634558576162614e6e62525159556e626a5651484c536954317443767552494738497172325441505076436e766766356a74733568456c49592f5859544e2f666c75544751396461774e582b6843565175774346474962433745514e70742f476870414e70706e767a3559426f627732494c333761682f724a7666656e774334546f4e57566c595730625a744d446e76437542316779696c6d344373666d476274304841646f624378536d69572b63426361454b676c796c6c34357335514b46475331366e613461377651505879505763484c567a2f482f484c7141394366673942582f2b7a542f38322b573547595466487542762b412b4f4b4d43694152434936763734426a4c6e54747a2f75652f53727955417a64545a4a734f67317066634665302b57615035454e3465316a5247502b436d545139314f704831737170314c3157455a6c5879627a546c304c467545797a556866787446706536546f766a4f5245777971723963727047563465584e325869527457564a35754c77483551307933335248516242563059687575344f707270614a7658482b556a4a3633615a764d5878564e6f6238437a566b75626a74696331484668507a32634f6f6b6c4f6f6d352f736b5134447354325141306771597642463445414c3338514d772b61417949454b554c5444504765454a662b7a784e564e474c474f7049547a6653355a375531374f6559615350506376346f4869322f6d4750584a2b626a4b7079642b5a566930666d396249784874357a2b716177393778594b6e7376694b62545231356b7047764c7a724d596d445a2b7936762b6c7866542f7855762f7356622f6e6b347a6e5a6b776c786566627a65556c42666271742f4a79767135646b6b69375872454d724a5373736f55425a716b3551544b464d32433755493543674e5975704e73565a576d3042436a692b6c494d753355534374714955764e387a2b4c326d69324d4278786d374666475879737471312b54557967586e383259494f7330777969632b6e55706a5a695346756f734432485033507a383075766b502f747179535654486f6164584b3065546c703041636b647361465258376e6b30797a477777664c424656725041736843324d596176705851713869553079305364715336426a6f3859596e366d53627557574c3957713542533571743476315967615a74416f785169445a743630526c3461704b796c69384d4a4b6f336a706c6c696d6c6d7154633152626f614e5042754336524d455958354437526246733575497469546c654d79326b4c7a2b4b777643507a762b523145696978434a786c4d4670764456615661314145385066545553323939394e565066774d4d4e4d6867517777316a464b6a56703368526868706c4e48474747756338536159614a4b596567306d6d324b716161616259615a5a5a70746a726e6e6d5732436852525a6259716c6c6c6c74687056565757324f746464614c3232436a5454626259717474747474687031313232324f766666627a41334f6c6f787a74596566347a6a464f63614b4c58652b716f446e42423435305a74436a77386e4f645a776e66524c654a57377774362b2f30733265393678624e456f3454644b4c417339357761746538724a5866432f6c5461393533613353666d4e34783176656c76476a6e7832765356617a56693361584b5a6470773435655555464a57552f714f67534f744442446e4b6679783371454963353345392b38594462334f354237336b2f516e5248542f5247582f544851417769516f77454b544c6b6334633733654e6554376e4c335a3532724274444d5939344e4a536f357152516f304737725837596b616d76693245326474635261362b454f3253374c644a6c334f36477761676857597a7264463275322f57345874666e2b74324147387945727a676472553732723745796d76547a6d62764c726b53334e3548317978667a77722f4e744b6b755777545366754e37422f776644563444766a7a4a3235436e536c3274504a334c4d59746d63637573326f4a7638523949554964484a4c684e594a615a3451777a4d50744d356158786a543631527745774b352b5a4f2f68557a643251773435564951413d2920666f726d61742827776f6666322729207d203c2f7374796c653e203c2f646566733e203c7374796c6520747970653d27746578742f637373273e202e7374307b7374726f6b653a234646464646463b7374726f6b652d6d697465726c696d69743a31303b7d202e7374317b66696c6c3a234130453534363b7d202e7374327b666f6e742d66616d696c793a274d696e65637261667469612d526567756c6172273b7d202e7374337b666f6e742d73697a653a323070783b7d202e7374347b66696c6c3a234646464646463b7d202e7374357b66696c6c3a233245434532393b7d202e7374367b66696c6c3a233737354345313b7d202e7374377b66696c6c3a234544423031353b7d202e7374387b6c65747465722d73706163696e673a32323b7d202e7374397b66696c6c3a234646464646463b7374726f6b653a234646464646463b7374726f6b652d6d697465726c696d69743a31303b7d202e737431307b66696c6c3a233443393845323b7d202e737431317b66696c6c3a6e6f6e653b7d202e737431327b666f6e742d73697a653a353570783b7d202e737431337b646973706c61793a6e6f6e653b7d202e737431347b666f6e742d73697a653a363070783b7d202e737431357b66696c6c3a234345333032383b7d202e737431367b66696c6c3a234541423532463b7d202e737431377b646973706c61793a6e6f6e653b66696c6c3a233732303930393b7d202e737431387b666f6e742d73697a653a33392e3233313870783b7d202e737431397b666f6e742d73697a653a34332e3137303770783b7d203c2f7374796c653e203c672069643d276c696e6861636f6469676f273e203c7061746820636c6173733d277374302720643d274d3834392e35352c3835302e333948302e3834632d302e34362c302d302e38342d302e33382d302e38342d302e383456302e383443302c302e33382c302e33382c302c302e38342c30683834382e37312063302e34362c302c302e38342c302e33382c302e38342c302e3834763834382e3731433835302e33392c3835302e30322c3835302e30322c3835302e33392c3834392e35352c3835302e33397a272f3e3c74657874207472616e73666f726d3d276d617472697828312030203020312034392e30333637203332352e3832383629273e3c747370616e20783d27302720793d27302720636c6173733d277374312073743220737433273e707261676d612020736f6c69646974793c2f747370616e3e3c747370616e20783d273139392e352720793d27302720636c6173733d277374342073743220737433273e2020302e382e31203b3c2f747370616e3e3c747370616e20783d27302720793d2739302720636c6173733d277374312073743220737433273e636f6e74726163743c2f747370616e3e3c747370616e20783d273132302720793d2739302720636c6173733d277374342073743220737433273e7765623364657620207b3c2f747370616e3e3c747370616e20783d2733322e39322720793d273133352720636c6173733d277374342073743220737433273e66756e6374696f6e20203c2f747370616e3e3c747370616e20783d273134352e34322720793d273133352720636c6173733d27737431302073743220737433273e626f6f7463616d703c2f747370616e3e3c747370616e20783d273236352e34322720793d273133352720636c6173733d277374342073743220737433273e2829203c2f747370616e3e3c747370616e20783d273330302e34322720793d273133352720636c6173733d277374312073743220737433273e7075626c696320766965772072657475726e733c2f747370616e3e3c747370616e20783d273534372720793d273133352720636c6173733d277374342073743220737433273e283c2f747370616e3e3c747370616e20783d273537302e34322720793d273133352720636c6173733d27737431302073743220737433273e737472696e67206d656d6f7279293c2f747370616e3e3c747370616e20783d273735352e34322720793d273133352720636c6173733d277374342073743220737433273e7b3c2f747370616e3e3c747370616e20783d273131312e36372720793d273138302720636c6173733d277374342073743220737433273e72657475726e203c2f747370616e3e3c747370616e20783d273231362e36372720793d273138302720636c6173733d277374362073743220737433273e3b3c2f747370616e3e3c747370616e20783d2733322e39322720793d273232352720636c6173733d277374342073743220737433273e7d3c2f747370616e3e3c747370616e20783d27302720793d273237302720636c6173733d277374342073743220737433273e7d3c2f747370616e3e3c2f746578743e3c2f673e3c673e3c74657874207472616e73666f726d3d276d61747269782831203020302031203635302e323133203738312e32313536292720636c6173733d27737434207374322073743132273e233c2f746578743e3c2f673e3c673e3c7265637420783d2734382e31332720793d273139322e38352720636c6173733d2773743131272077696474683d273439372e363627206865696768743d2739362e3939272f3e203c74657874207472616e73666f726d3d276d617472697828312030203020312034382e31323731203238322e38343935292720636c6173733d27737434207374322073743134273e

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101585760003560e01c80635f710f5c116100c3578063a217fddf1161007c578063a217fddf146103d3578063a22cb465146103f1578063b88d4fde1461040d578063c87b56dd14610429578063d547741f14610459578063e985e9c51461047557610158565b80635f710f5c146102ed5780636352211e146103095780636d7849521461033957806370a082311461035557806391d148541461038557806395d89b41146103b557610158565b8063248a9ca311610115578063248a9ca31461022f5780632b75565d1461025f5780632f2ff15d1461027b57806336568abe1461029757806342842e0e146102b357806350e63ddf146102cf57610158565b806301ffc9a71461015d57806306fdde031461018d578063081812fc146101ab578063095ea7b3146101db5780631785f53c146101f757806323b872dd14610213575b600080fd5b61017760048036038101906101729190612e37565b6104a5565b604051610184919061372b565b60405180910390f35b6101956104b7565b6040516101a29190613761565b60405180910390f35b6101c560048036038101906101c09190612f74565b610549565b6040516101d291906136c4565b60405180910390f35b6101f560048036038101906101f09190612d96565b6105ce565b005b610211600480360381019061020c9190612c2b565b6106e6565b005b61022d60048036038101906102289190612c90565b61075f565b005b61024960048036038101906102449190612dd2565b61079a565b6040516102569190613746565b60405180910390f35b61027960048036038101906102749190612e89565b6107ba565b005b61029560048036038101906102909190612dfb565b6108e8565b005b6102b160048036038101906102ac9190612dfb565b610909565b005b6102cd60048036038101906102c89190612c90565b61098c565b005b6102d76109c7565b6040516102e49190613746565b60405180910390f35b61030760048036038101906103029190612c2b565b6109eb565b005b610323600480360381019061031e9190612f74565b610a64565b60405161033091906136c4565b60405180910390f35b610353600480360381019061034e9190612ef5565b610b16565b005b61036f600480360381019061036a9190612c2b565b610e80565b60405161037c9190613a03565b60405180910390f35b61039f600480360381019061039a9190612dfb565b610f38565b6040516103ac919061372b565b60405180910390f35b6103bd610fa3565b6040516103ca9190613761565b60405180910390f35b6103db611035565b6040516103e89190613746565b60405180910390f35b61040b60048036038101906104069190612d5a565b61103c565b005b61042760048036038101906104229190612cdf565b611052565b005b610443600480360381019061043e9190612f74565b6110b4565b6040516104509190613761565b60405180910390f35b610473600480360381019061046e9190612dfb565b61139a565b005b61048f600480360381019061048a9190612c54565b6113bb565b60405161049c919061372b565b60405180910390f35b60006104b08261144f565b9050919050565b6060600080546104c690613cfc565b80601f01602080910402602001604051908101604052809291908181526020018280546104f290613cfc565b801561053f5780601f106105145761010080835404028352916020019161053f565b820191906000526020600020905b81548152906001019060200180831161052257829003601f168201915b5050505050905090565b6000610554826114c9565b610593576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161058a90613983565b60405180910390fd5b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60006105d982610a64565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561064a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610641906139a3565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610669611535565b73ffffffffffffffffffffffffffffffffffffffff161480610698575061069781610692611535565b6113bb565b5b6106d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106ce906138c3565b60405180910390fd5b6106e1838361153d565b505050565b6106f36000801b33610f38565b610732576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072990613963565b60405180910390fd5b61075c7fe918b231727c964e85d5ce841b7b0735aa540b813b93ecc15a2cd996d2608d62826115f6565b50565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079190613803565b60405180910390fd5b600060076000838152602001908152602001600020600101549050919050565b6107c76000801b33610f38565b610806576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107fd90613963565b60405180910390fd5b6000826040516020016108199190613554565b6040516020818303038152906040528051906020012090506000600c6000838152602001908152602001600020805461085190613cfc565b905014610893576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161088a90613843565b60405180910390fd5b81600c600083815260200190815260200160002090805190602001906108ba929190612a3a565b5082600d600083815260200190815260200160002090805190602001906108e2929190612a3a565b50505050565b6108f18261079a565b6108fa816116d8565b61090483836116ec565b505050565b610911611535565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461097e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610975906139e3565b60405180910390fd5b61098882826115f6565b5050565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109be90613803565b60405180910390fd5b7fe918b231727c964e85d5ce841b7b0735aa540b813b93ecc15a2cd996d2608d6281565b6109f86000801b33610f38565b610a37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a2e90613963565b60405180910390fd5b610a617fe918b231727c964e85d5ce841b7b0735aa540b813b93ecc15a2cd996d2608d62826116ec565b50565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610b0d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0490613903565b60405180910390fd5b80915050919050565b610b236000801b33610f38565b610b62576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b5990613963565b60405180910390fd5b60008183604051602001610b7792919061352c565b6040516020818303038152906040528051906020012090506000600a6000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff1660ff1614610c33576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c2a90613943565b60405180910390fd5b6001600a6000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff021916908360ff160217905550600983604051610cae9190613554565b9081526020016040518091039020829080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600083604051602001610d309190613554565b6040516020818303038152906040528051906020012090506000600c60008381526020019081526020016000208054610d6890613cfc565b90501415610dab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da290613823565b60405180910390fd5b600085604051602001610dbe9190613554565b60405160208183030381529060405280519060200120905085600e60008381526020019081526020016000209080519060200190610dfd929190612a3a565b50610e098183866117cd565b85604051610e179190613554565b604051809103902085604051610e2d9190613554565b60405180910390208573ffffffffffffffffffffffffffffffffffffffff167f8641a4aba657b283ac69dfb130cd01fc637d86b85263f3eb21439d491bd0debb60405160405180910390a4505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ef1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ee8906138e3565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60006007600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b606060018054610fb290613cfc565b80601f0160208091040260200160405190810160405280929190818152602001828054610fde90613cfc565b801561102b5780601f106110005761010080835404028352916020019161102b565b820191906000526020600020905b81548152906001019060200180831161100e57829003601f168201915b5050505050905090565b6000801b81565b61104e611047611535565b83836118a3565b5050565b61106361105d611535565b83611a10565b6110a2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611099906139c3565b60405180910390fd5b6110ae84848484611aee565b50505050565b60606000600d60006010600086815260200190815260200160002054815260200190815260200160002080546110e990613cfc565b80601f016020809104026020016040519081016040528092919081815260200182805461111590613cfc565b80156111625780601f1061113757610100808354040283529160200191611162565b820191906000526020600020905b81548152906001019060200180831161114557829003601f168201915b505050505090506000600e6000600f6000878152602001908152602001600020548152602001908152602001600020805461119c90613cfc565b80601f01602080910402602001604051908101604052809291908181526020018280546111c890613cfc565b80156112155780601f106111ea57610100808354040283529160200191611215565b820191906000526020600020905b8154815290600101906020018083116111f857829003601f168201915b505050505090506000600c600060106000888152602001908152602001600020548152602001908152602001600020805461124f90613cfc565b80601f016020809104026020016040519081016040528092919081815260200182805461127b90613cfc565b80156112c85780601f1061129d576101008083540402835291602001916112c8565b820191906000526020600020905b8154815290600101906020018083116112ab57829003601f168201915b50505050509050600060116000878152602001908152602001600020549050600060138560146112f785611b4a565b6015886016604051602001611312979695949392919061356b565b60405160208183030381529060405290506000858561133085611b4a565b8661133a86611cf7565b60405160200161134e9594939291906135d0565b6040516020818303038152906040529050600061136a82611cf7565b90508060405160200161137d9190613668565b604051602081830303815290604052975050505050505050919050565b6113a38261079a565b6113ac816116d8565b6113b683836115f6565b505050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806114c257506114c182611eb5565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff166115b083610a64565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6116008282610f38565b156116d45760006007600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611679611535565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b6116e9816116e4611535565b611f97565b50565b6116f68282610f38565b6117c95760016007600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555061176e611535565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b6001600b6000848152602001908152602001600020600085815260200190815260200160002060008282546118029190613afd565b925050819055506118136008612034565b600061181f600861204a565b90506000600b6000858152602001908152602001600020600086815260200190815260200160002054905080601160008481526020019081526020016000208190555083601060008481526020019081526020016000208190555084600f60008481526020019081526020016000208190555061189c8383612058565b5050505050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611912576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161190990613883565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611a03919061372b565b60405180910390a3505050565b6000611a1b826114c9565b611a5a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a51906138a3565b60405180910390fd5b6000611a6583610a64565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480611aa75750611aa681856113bb565b5b80611ae557508373ffffffffffffffffffffffffffffffffffffffff16611acd84610549565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b611af9848484612076565b611b05848484846122dd565b611b44576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b3b906137a3565b60405180910390fd5b50505050565b60606000821415611b92576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050611cf2565b600082905060005b60008214611bc4578080611bad90613d5f565b915050600a82611bbd9190613b53565b9150611b9a565b60008167ffffffffffffffff811115611c06577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611c385781602001600182028036833780820191505090505b5090505b60008514611ceb57600182611c519190613bde565b9150600a85611c609190613dcc565b6030611c6c9190613afd565b60f81b818381518110611ca8577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85611ce49190613b53565b9450611c3c565b8093505050505b919050565b60606000825190506000811415611d205760405180602001604052806000815250915050611eb0565b60006003600283611d319190613afd565b611d3b9190613b53565b6004611d479190613b84565b90506000602082611d589190613afd565b67ffffffffffffffff811115611d97577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611dc95781602001600182028036833780820191505090505b5090506000604051806060016040528060408152602001614679604091399050600181016020830160005b86811015611e6d5760038101905062ffffff818a015116603f8160121c168401518060081b905060ff603f83600c1c1686015116810190508060081b905060ff603f8360061c1686015116810190508060081b905060ff603f831686015116810190508060e01b90508084526004840193505050611df4565b506003860660018114611e875760028114611e9757611ea2565b613d3d60f01b6002830352611ea2565b603d60f81b60018303525b508484525050819450505050505b919050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611f8057507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611f905750611f8f82612474565b5b9050919050565b611fa18282610f38565b61203057611fc68173ffffffffffffffffffffffffffffffffffffffff1660146124de565b611fd48360001c60206124de565b604051602001611fe592919061368a565b6040516020818303038152906040526040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120279190613761565b60405180910390fd5b5050565b6001816000016000828254019250508190555050565b600081600001549050919050565b6120728282604051806020016040528060008152506127d8565b5050565b8273ffffffffffffffffffffffffffffffffffffffff1661209682610a64565b73ffffffffffffffffffffffffffffffffffffffff16146120ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e3906137c3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561215c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161215390613863565b60405180910390fd5b612167838383612833565b61217260008261153d565b6001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546121c29190613bde565b925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546122199190613afd565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46122d8838383612838565b505050565b60006122fe8473ffffffffffffffffffffffffffffffffffffffff1661283d565b15612467578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612327611535565b8786866040518563ffffffff1660e01b815260040161234994939291906136df565b602060405180830381600087803b15801561236357600080fd5b505af192505050801561239457506040513d601f19601f820116820180604052508101906123919190612e60565b60015b612417573d80600081146123c4576040519150601f19603f3d011682016040523d82523d6000602084013e6123c9565b606091505b5060008151141561240f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612406906137a3565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161491505061246c565b600190505b949350505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6060600060028360026124f19190613b84565b6124fb9190613afd565b67ffffffffffffffff81111561253a577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801561256c5781602001600182028036833780820191505090505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106125ca577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110612654577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600060018460026126949190613b84565b61269e9190613afd565b90505b600181111561278a577f3031323334353637383961626364656600000000000000000000000000000000600f861660108110612706577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b1a60f81b828281518110612743577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c94508061278390613cd2565b90506126a1565b50600084146127ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127c590613783565b60405180910390fd5b8091505092915050565b6127e28383612860565b6127ef60008484846122dd565b61282e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612825906137a3565b60405180910390fd5b505050565b505050565b505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156128d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128c790613923565b60405180910390fd5b6128d9816114c9565b15612919576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612910906137e3565b60405180910390fd5b61292560008383612833565b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546129759190613afd565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612a3660008383612838565b5050565b828054612a4690613cfc565b90600052602060002090601f016020900481019282612a685760008555612aaf565b82601f10612a8157805160ff1916838001178555612aaf565b82800160010185558215612aaf579182015b82811115612aae578251825591602001919060010190612a93565b5b509050612abc9190612ac0565b5090565b5b80821115612ad9576000816000905550600101612ac1565b5090565b6000612af0612aeb84613a43565b613a1e565b905082815260208101848484011115612b0857600080fd5b612b13848285613c90565b509392505050565b6000612b2e612b2984613a74565b613a1e565b905082815260208101848484011115612b4657600080fd5b612b51848285613c90565b509392505050565b600081359050612b6881614605565b92915050565b600081359050612b7d8161461c565b92915050565b600081359050612b9281614633565b92915050565b600081359050612ba78161464a565b92915050565b600081519050612bbc8161464a565b92915050565b600082601f830112612bd357600080fd5b8135612be3848260208601612add565b91505092915050565b600082601f830112612bfd57600080fd5b8135612c0d848260208601612b1b565b91505092915050565b600081359050612c2581614661565b92915050565b600060208284031215612c3d57600080fd5b6000612c4b84828501612b59565b91505092915050565b60008060408385031215612c6757600080fd5b6000612c7585828601612b59565b9250506020612c8685828601612b59565b9150509250929050565b600080600060608486031215612ca557600080fd5b6000612cb386828701612b59565b9350506020612cc486828701612b59565b9250506040612cd586828701612c16565b9150509250925092565b60008060008060808587031215612cf557600080fd5b6000612d0387828801612b59565b9450506020612d1487828801612b59565b9350506040612d2587828801612c16565b925050606085013567ffffffffffffffff811115612d4257600080fd5b612d4e87828801612bc2565b91505092959194509250565b60008060408385031215612d6d57600080fd5b6000612d7b85828601612b59565b9250506020612d8c85828601612b6e565b9150509250929050565b60008060408385031215612da957600080fd5b6000612db785828601612b59565b9250506020612dc885828601612c16565b9150509250929050565b600060208284031215612de457600080fd5b6000612df284828501612b83565b91505092915050565b60008060408385031215612e0e57600080fd5b6000612e1c85828601612b83565b9250506020612e2d85828601612b59565b9150509250929050565b600060208284031215612e4957600080fd5b6000612e5784828501612b98565b91505092915050565b600060208284031215612e7257600080fd5b6000612e8084828501612bad565b91505092915050565b60008060408385031215612e9c57600080fd5b600083013567ffffffffffffffff811115612eb657600080fd5b612ec285828601612bec565b925050602083013567ffffffffffffffff811115612edf57600080fd5b612eeb85828601612bec565b9150509250929050565b600080600060608486031215612f0a57600080fd5b600084013567ffffffffffffffff811115612f2457600080fd5b612f3086828701612bec565b935050602084013567ffffffffffffffff811115612f4d57600080fd5b612f5986828701612bec565b9250506040612f6a86828701612b59565b9150509250925092565b600060208284031215612f8657600080fd5b6000612f9484828501612c16565b91505092915050565b612fa681613c12565b82525050565b612fbd612fb882613c12565b613da8565b82525050565b612fcc81613c24565b82525050565b612fdb81613c30565b82525050565b6000612fec82613aba565b612ff68185613ad0565b9350613006818560208601613c9f565b61300f81613eb9565b840191505092915050565b600061302582613ac5565b61302f8185613ae1565b935061303f818560208601613c9f565b61304881613eb9565b840191505092915050565b600061305e82613ac5565b6130688185613af2565b9350613078818560208601613c9f565b80840191505092915050565b6000815461309181613cfc565b61309b8186613af2565b945060018216600081146130b657600181146130c7576130fa565b60ff198316865281860193506130fa565b6130d085613aa5565b60005b838110156130f2578154818901526001820191506020810190506130d3565b838801955050505b50505092915050565b6000613110602083613ae1565b915061311b82613ed7565b602082019050919050565b6000613133601d83613af2565b915061313e82613f00565b601d82019050919050565b6000613156603283613ae1565b915061316182613f29565b604082019050919050565b6000613179602583613ae1565b915061318482613f78565b604082019050919050565b600061319c601c83613ae1565b91506131a782613fc7565b602082019050919050565b60006131bf600883613ae1565b91506131ca82613ff0565b602082019050919050565b60006131e2600e83613ae1565b91506131ed82614019565b602082019050919050565b6000613205601983613ae1565b915061321082614042565b602082019050919050565b6000613228602483613ae1565b91506132338261406b565b604082019050919050565b600061324b602683613af2565b9150613256826140ba565b602682019050919050565b600061326e601983613ae1565b915061327982614109565b602082019050919050565b6000613291602c83613ae1565b915061329c82614132565b604082019050919050565b60006132b4603483613af2565b91506132bf82614181565b603482019050919050565b60006132d7603883613ae1565b91506132e2826141d0565b604082019050919050565b60006132fa602a83613ae1565b91506133058261421f565b604082019050919050565b600061331d602983613ae1565b91506133288261426e565b604082019050919050565b6000613340600283613af2565b915061334b826142bd565b600282019050919050565b6000613363602083613ae1565b915061336e826142e6565b602082019050919050565b6000613386601583613af2565b91506133918261430f565b601582019050919050565b60006133a9602983613ae1565b91506133b482614338565b604082019050919050565b60006133cc601d83613ae1565b91506133d782614387565b602082019050919050565b60006133ef602c83613ae1565b91506133fa826143b0565b604082019050919050565b6000613412602783613af2565b915061341d826143ff565b602782019050919050565b6000613435602183613ae1565b91506134408261444e565b604082019050919050565b6000613458601d83613af2565b91506134638261449d565b601d82019050919050565b600061347b603183613ae1565b9150613486826144c6565b604082019050919050565b600061349e602683613af2565b91506134a982614515565b602682019050919050565b60006134c1601783613af2565b91506134cc82614564565b601782019050919050565b60006134e4601183613af2565b91506134ef8261458d565b601182019050919050565b6000613507602f83613ae1565b9150613512826145b6565b604082019050919050565b61352681613c86565b82525050565b60006135388285612fac565b6014820191506135488284613053565b91508190509392505050565b60006135608284613053565b915081905092915050565b6000613577828a613084565b91506135838289613053565b915061358f8288613084565b915061359b8287613053565b91506135a78286613084565b91506135b38285613053565b91506135bf8284613084565b915081905098975050505050505050565b60006135db82613126565b91506135e6826132a7565b91506135f28288613053565b91506135fd82613491565b91506136098287613053565b91506136148261323e565b91506136208286613053565b915061362b82613379565b91506136378285613053565b915061364282613405565b915061364e8284613053565b915061365982613333565b91508190509695505050505050565b60006136738261344b565b915061367f8284613053565b915081905092915050565b6000613695826134b4565b91506136a18285613053565b91506136ac826134d7565b91506136b88284613053565b91508190509392505050565b60006020820190506136d96000830184612f9d565b92915050565b60006080820190506136f46000830187612f9d565b6137016020830186612f9d565b61370e604083018561351d565b81810360608301526137208184612fe1565b905095945050505050565b60006020820190506137406000830184612fc3565b92915050565b600060208201905061375b6000830184612fd2565b92915050565b6000602082019050818103600083015261377b818461301a565b905092915050565b6000602082019050818103600083015261379c81613103565b9050919050565b600060208201905081810360008301526137bc81613149565b9050919050565b600060208201905081810360008301526137dc8161316c565b9050919050565b600060208201905081810360008301526137fc8161318f565b9050919050565b6000602082019050818103600083015261381c816131b2565b9050919050565b6000602082019050818103600083015261383c816131d5565b9050919050565b6000602082019050818103600083015261385c816131f8565b9050919050565b6000602082019050818103600083015261387c8161321b565b9050919050565b6000602082019050818103600083015261389c81613261565b9050919050565b600060208201905081810360008301526138bc81613284565b9050919050565b600060208201905081810360008301526138dc816132ca565b9050919050565b600060208201905081810360008301526138fc816132ed565b9050919050565b6000602082019050818103600083015261391c81613310565b9050919050565b6000602082019050818103600083015261393c81613356565b9050919050565b6000602082019050818103600083015261395c8161339c565b9050919050565b6000602082019050818103600083015261397c816133bf565b9050919050565b6000602082019050818103600083015261399c816133e2565b9050919050565b600060208201905081810360008301526139bc81613428565b9050919050565b600060208201905081810360008301526139dc8161346e565b9050919050565b600060208201905081810360008301526139fc816134fa565b9050919050565b6000602082019050613a18600083018461351d565b92915050565b6000613a28613a39565b9050613a348282613d2e565b919050565b6000604051905090565b600067ffffffffffffffff821115613a5e57613a5d613e8a565b5b613a6782613eb9565b9050602081019050919050565b600067ffffffffffffffff821115613a8f57613a8e613e8a565b5b613a9882613eb9565b9050602081019050919050565b60008190508160005260206000209050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b6000613b0882613c86565b9150613b1383613c86565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115613b4857613b47613dfd565b5b828201905092915050565b6000613b5e82613c86565b9150613b6983613c86565b925082613b7957613b78613e2c565b5b828204905092915050565b6000613b8f82613c86565b9150613b9a83613c86565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613bd357613bd2613dfd565b5b828202905092915050565b6000613be982613c86565b9150613bf483613c86565b925082821015613c0757613c06613dfd565b5b828203905092915050565b6000613c1d82613c66565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b82818337600083830152505050565b60005b83811015613cbd578082015181840152602081019050613ca2565b83811115613ccc576000848401525b50505050565b6000613cdd82613c86565b91506000821415613cf157613cf0613dfd565b5b600182039050919050565b60006002820490506001821680613d1457607f821691505b60208210811415613d2857613d27613e5b565b5b50919050565b613d3782613eb9565b810181811067ffffffffffffffff82111715613d5657613d55613e8a565b5b80604052505050565b6000613d6a82613c86565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613d9d57613d9c613dfd565b5b600182019050919050565b6000613db382613dba565b9050919050565b6000613dc582613eca565b9050919050565b6000613dd782613c86565b9150613de283613c86565b925082613df257613df1613e2c565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b60008160601b9050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b7f7b226e616d65223a20225745423344455620426f6f7463616d70222c20000000600082015250565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b7f64697361626c6564000000000000000000000000000000000000000000000000600082015250565b7f496e76616c696420436f75727365000000000000000000000000000000000000600082015250565b7f436f7572736520616c7265616479207265676973746572656400000000000000600082015250565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f227d2c7b2274726169745f74797065223a20226e756d626572222c202276616c60008201527f7565223a20220000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b7f2261747472696275746573223a205b207b202274726169745f74797065223a2060008201527f22636f75727365222c202276616c7565223a2022000000000000000000000000602082015250565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b7f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008201527f656e7420746f6b656e0000000000000000000000000000000000000000000000602082015250565b7f227d000000000000000000000000000000000000000000000000000000000000600082015250565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b7f227d5d2c20226465736372697074696f6e223a20220000000000000000000000600082015250565b7f53747564656e7420616c72656164792072656769737465726564206f6e20746860008201527f697320636f757273650000000000000000000000000000000000000000000000602082015250565b7f43616c6c6572206973206e6f7420616e2057696e646f772041646d696e000000600082015250565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b7f222c2022696d616765223a2022646174613a696d6167652f7376672b786d6c3b60008201527f6261736536342c00000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000600082015250565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b7f227d2c7b2274726169745f74797065223a2022636f686f7274222c202276616c60008201527f7565223a20220000000000000000000000000000000000000000000000000000602082015250565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b61460e81613c12565b811461461957600080fd5b50565b61462581613c24565b811461463057600080fd5b50565b61463c81613c30565b811461464757600080fd5b50565b61465381613c3a565b811461465e57600080fd5b50565b61466a81613c86565b811461467557600080fd5b5056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa264697066735822122075bfce8047c5f4ef85a051e11c43ab1d08b41db01623de1570eead8e63bdb6c064736f6c63430008040033

Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.