ETH Price: $1,979.10 (-5.41%)
Gas: 0.05 Gwei

Contract

0xE2a3EDF6D1924dfca2c7E59189dd5BBeED25d09C
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Method Block
From
To
0x60806040200310602024-06-06 6:40:59638 days ago1717656059  Contract Creation0 ETH
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

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

Contract Source Code Verified (Exact Match)

Contract Name:
TokenLauncherFactoryFacet

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 10 runs

Other Settings:
london EvmVersion, MIT license
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import { IAccessControl } from "@solidstate/contracts/access/access_control/IAccessControl.sol";

import { ITokenLauncherFactory } from "../interfaces/ITokenLauncherFactory.sol";
import { ITokenFiErc20 } from "../interfaces/ITokenFiErc20.sol";
import { ITokenFiErc20Init } from "../interfaces/ITokenFiErc20Init.sol";
import { ITokenFiErc721 } from "../interfaces/ITokenFiErc721.sol";
import { ITokenFiErc721Init } from "../interfaces/ITokenFiErc721Init.sol";
import { ITokenFiErc1155 } from "../interfaces/ITokenFiErc1155.sol";
import { ITokenFiErc1155Init } from "../interfaces/ITokenFiErc1155Init.sol";
import { LibTokenLauncherFactoryStorage } from "../libraries/LibTokenLauncherFactoryStorage.sol";
import { LibTokenLauncherConsts } from "../libraries/LibTokenLauncherConsts.sol";
import { IPaymentModule } from "../../common/admin/interfaces/IPaymentModule.sol";
import { ICrossPaymentModule } from "../../common/admin/interfaces/ICrossPaymentModule.sol";
import { IPlatformModule } from "../../common/admin/interfaces/IPlatformModule.sol";
import { LibPaymentModuleConsts } from "../../common/admin/libraries/LibPaymentModuleConsts.sol";
import { IDiamondCut } from "../../common/diamonds/interfaces/IDiamondCut.sol";
import { LibDiamond } from "../../common/diamonds/libraries/LibDiamond.sol";
import { LibDiamondHelpers } from "../../common/diamonds/libraries/LibDiamondHelpers.sol";
import { Diamond } from "../../common/diamonds/Diamond.sol";
import { IDiamondProxy } from "../../common/diamonds/interfaces/IDiamondProxy.sol";

contract TokenLauncherFactoryFacet is ITokenLauncherFactory {
    // solhint-disable-next-line function-max-lines
    function createErc20(CreateErc20Input memory input) external payable override returns (address tokenAddress) {
        uint256 paymentIndex = _processPayment(TokenType.ERC20, input.referrer, input.paymentToken);
        tokenAddress = _createErc20(input, paymentIndex);
    }

    function createErc20WithPaymentSignature(
        CreateErc20Input memory input,
        ICrossPaymentModule.CrossPaymentSignatureInput memory crossPaymentSignatureInput
    ) external override returns (address tokenAddress) {
        _spendCrossPaymentSignature(TokenType.ERC20, crossPaymentSignatureInput);
        tokenAddress = _createErc20(input, crossPaymentSignatureInput.paymentIndex);
    }

    function _createErc20(CreateErc20Input memory input, uint256 paymentIndex) private returns (address tokenAddress) {
        LibTokenLauncherFactoryStorage.DiamondStorage storage ds = LibTokenLauncherFactoryStorage.diamondStorage();

        // Now let's create a diamond
        tokenAddress = _createTokenDiamond();

        _prepareTokenFiErc20Diamond(tokenAddress, input.tokenInfo);

        // set TokenFiErc20Implementation for etherscan
        IDiamondProxy(tokenAddress).setImplementation(ds.tokenFiErc20Implementation);

        ITokenFiErc20 token = ITokenFiErc20(tokenAddress);

        // set metadata
        token.setName(input.tokenInfo.name);
        token.setSymbol(input.tokenInfo.symbol);
        token.setDecimals(input.tokenInfo.decimals);

        // mint initial supply to treasury if it's not a reflection token
        if (input.tokenInfo.initialSupply > 0) {
            token.mint(input.tokenInfo.treasury, input.tokenInfo.initialSupply);
        }

        // exempt this address as a liquidity factory
        token.addExemptAddress(address(this));
        // exempt the buybackHandler to avoid recursive transfer
        token.addExemptAddress(ds.buybackHandler);

        // set buybackHandler
        token.setBuybackHandler(ds.buybackHandler);
        // grant BUYBACK_CALLER_ROLE to the tokenFiErc20
        IAccessControl(ds.buybackHandler).grantRole(LibTokenLauncherConsts.BUYBACK_CALLER_ROLE, tokenAddress);

        // Log new token into store
        StoreTokenInput memory storeInput = StoreTokenInput({
            tokenAddress: tokenAddress,
            owner: input.tokenInfo.owner,
            referrer: input.referrer,
            paymentIndex: paymentIndex,
            tokenType: TokenType.ERC20
        });
        _addToken(storeInput);
    }

    function createErc721(CreateErc721Input memory input) external payable override returns (address tokenAddress) {
        uint256 paymentIndex = _processPayment(TokenType.ERC721, input.referrer, input.paymentToken);
        tokenAddress = _createErc721(input, paymentIndex);
    }

    function createErc721WithPaymentSignature(
        CreateErc721Input memory input,
        ICrossPaymentModule.CrossPaymentSignatureInput memory crossPaymentSignatureInput
    ) external override returns (address tokenAddress) {
        _spendCrossPaymentSignature(TokenType.ERC721, crossPaymentSignatureInput);
        tokenAddress = _createErc721(input, crossPaymentSignatureInput.paymentIndex);
    }

    function _createErc721(CreateErc721Input memory input, uint256 paymentIndex) private returns (address tokenAddress) {
        // Now let's create a diamond
        tokenAddress = _createTokenDiamond();

        _prepareTokenFiErc721Diamond(tokenAddress, input.tokenInfo);

        // set TokenFiErc721Implementation for etherscan
        LibTokenLauncherFactoryStorage.DiamondStorage storage ds = LibTokenLauncherFactoryStorage.diamondStorage();
        IDiamondProxy(tokenAddress).setImplementation(ds.tokenFiErc721Implementation);

        // add a new payment platform for the mint payment of the created token
        IPlatformModule.Service[] memory services = new IPlatformModule.Service[](1);
        services[0] = IPlatformModule.Service({ name: "ERC721 Mint", usdPrice: input.publicMintPaymentInfo.usdPrice });
        IPlatformModule.Platform memory platform = IPlatformModule.Platform({
            name: input.tokenInfo.name,
            id: keccak256(abi.encodePacked(tokenAddress)),
            owner: input.tokenInfo.owner,
            treasury: input.publicMintPaymentInfo.treasury,
            referrerBasisPoints: input.publicMintPaymentInfo.referrerBasisPoints,
            burnToken: IPlatformModule(address(this)).getPlatformById(LibTokenLauncherConsts.PRODUCT_ID).burnToken,
            burnBasisPoints: input.publicMintPaymentInfo.burnBasisPoints,
            isDiscountEnabled: false,
            services: services
        });
        IPlatformModule(address(this)).addPlatform(platform);

        // set TokenInfo
        ITokenFiErc721(tokenAddress).setTokenInfo(input.tokenInfo);

        // grant PAYMENT_PROCESSOR_ROLE to the created Token
        IAccessControl(address(this)).grantRole(LibPaymentModuleConsts.PAYMENT_PROCESSOR_ROLE, tokenAddress);

        // Log new token into store
        StoreTokenInput memory storeInput = StoreTokenInput({
            tokenAddress: tokenAddress,
            owner: input.tokenInfo.owner,
            referrer: input.referrer,
            paymentIndex: paymentIndex,
            tokenType: TokenType.ERC721
        });
        _addToken(storeInput);
    }

    function createErc1155(CreateErc1155Input memory input) external payable override returns (address tokenAddress) {
        uint256 paymentIndex = _processPayment(TokenType.ERC1155, input.referrer, input.paymentToken);
        tokenAddress = _createErc1155(input, paymentIndex);
    }

    function createErc1155WithPaymentSignature(
        CreateErc1155Input memory input,
        ICrossPaymentModule.CrossPaymentSignatureInput memory crossPaymentSignatureInput
    ) external override returns (address tokenAddress) {
        _spendCrossPaymentSignature(TokenType.ERC1155, crossPaymentSignatureInput);
        tokenAddress = _createErc1155(input, crossPaymentSignatureInput.paymentIndex);
    }

    function _createErc1155(CreateErc1155Input memory input, uint256 paymentIndex) private returns (address tokenAddress) {
        // Now let's create a diamond
        tokenAddress = _createTokenDiamond();

        _prepareTokenFiErc1155Diamond(tokenAddress, input.tokenInfo);

        // set TokenFiErc1155Implementation for etherscan
        LibTokenLauncherFactoryStorage.DiamondStorage storage ds = LibTokenLauncherFactoryStorage.diamondStorage();
        IDiamondProxy(tokenAddress).setImplementation(ds.tokenFiErc1155Implementation);

        // add a new payment platform for the mint payment of the created token
        IPlatformModule.Service[] memory services;
        IPlatformModule.Platform memory platform = IPlatformModule.Platform({
            name: input.tokenInfo.name,
            id: keccak256(abi.encodePacked(tokenAddress)),
            owner: tokenAddress,
            treasury: input.publicMintPaymentInfo.treasury,
            referrerBasisPoints: input.publicMintPaymentInfo.referrerBasisPoints,
            burnToken: IPlatformModule(address(this)).getPlatformById(LibTokenLauncherConsts.PRODUCT_ID).burnToken,
            burnBasisPoints: input.publicMintPaymentInfo.burnBasisPoints,
            isDiscountEnabled: false,
            services: services
        });
        IPlatformModule(address(this)).addPlatform(platform);

        // grant PAYMENT_PROCESSOR_ROLE to the created Token
        IAccessControl(address(this)).grantRole(LibPaymentModuleConsts.PAYMENT_PROCESSOR_ROLE, tokenAddress);

        //create initial tokens
        for (uint256 i = 0; i < input.initialTokens.length; i++) {
            ITokenFiErc1155(tokenAddress).createToken(input.initialTokens[i]);
        }

        // Log new token into store
        StoreTokenInput memory storeInput = StoreTokenInput({
            tokenAddress: tokenAddress,
            owner: input.tokenInfo.owner,
            referrer: input.referrer,
            paymentIndex: paymentIndex,
            tokenType: TokenType.ERC1155
        });
        _addToken(storeInput);
    }

    function _spendCrossPaymentSignature(TokenType tokenType, ICrossPaymentModule.CrossPaymentSignatureInput memory crossPaymentSignatureInput) private {
        // Now let's process the payment
        uint32[] memory services = new uint32[](1);
        services[0] = uint32(tokenType);
        uint32[] memory serviceAmounts = new uint32[](1);
        serviceAmounts[0] = 1;

        ICrossPaymentModule.ProcessCrossPaymentOutput memory processCrossPaymentOutput = ICrossPaymentModule.ProcessCrossPaymentOutput({
            platformId: LibTokenLauncherConsts.PRODUCT_ID,
            services: services,
            serviceAmounts: serviceAmounts,
            spender: msg.sender,
            destinationChainId: ICrossPaymentModule(address(this)).getChainID(),
            payer: crossPaymentSignatureInput.payer,
            sourceChainId: crossPaymentSignatureInput.sourceChainId,
            paymentIndex: crossPaymentSignatureInput.paymentIndex
        });
        ICrossPaymentModule(address(this)).spendCrossPaymentSignature(msg.sender, processCrossPaymentOutput, crossPaymentSignatureInput.signature);
    }

    function _processPayment(TokenType tokenType, address referrer, address paymentToken) private returns (uint256 paymentIndex) {
        // Now let's process the payment
        uint32[] memory services = new uint32[](1);
        services[0] = uint32(tokenType);
        uint32[] memory serviceAmounts = new uint32[](1);
        serviceAmounts[0] = 1;
        IPaymentModule.ProcessPaymentInput memory paymentInput = IPaymentModule.ProcessPaymentInput({
            platformId: LibTokenLauncherConsts.PRODUCT_ID,
            services: services,
            serviceAmounts: serviceAmounts,
            referrer: referrer,
            user: msg.sender,
            tokenAddress: paymentToken
        });
        paymentIndex = IPaymentModule(address(this)).processPayment{ value: msg.value }(paymentInput);
    }

    function _createTokenDiamond() private returns (address tokenAddress) {
        // Create the new Diamond
        LibDiamond.DiamondStorage storage diamondStorage = LibDiamond.diamondStorage();
        LibDiamond.FacetAddressAndPosition memory diamondCutFacet = diamondStorage.selectorToFacetAndPosition[IDiamondCut.diamondCut.selector];
        tokenAddress = address(new Diamond(address(this), diamondCutFacet.facetAddress));
    }

    function _prepareCommonFacetCuts() private view returns (IDiamondCut.FacetCut[] memory commonFacetCuts) {
        LibTokenLauncherFactoryStorage.DiamondStorage storage ds = LibTokenLauncherFactoryStorage.diamondStorage();

        commonFacetCuts = new IDiamondCut.FacetCut[](5);

        // Add AccessControlFacet
        bytes4[] memory functionSelectors = LibDiamondHelpers.getAccessControlSelectors();
        commonFacetCuts[1] = IDiamondCut.FacetCut({
            facetAddress: ds.accessControlFacet,
            action: IDiamondCut.FacetCutAction.Add,
            functionSelectors: functionSelectors
        });

        // Add PausableFacet
        functionSelectors = LibDiamondHelpers.getPausableSelectors();
        commonFacetCuts[2] = IDiamondCut.FacetCut({
            facetAddress: ds.pausableFacet,
            action: IDiamondCut.FacetCutAction.Add,
            functionSelectors: functionSelectors
        });

        // Add DiamondLoupeFacet
        functionSelectors = LibDiamondHelpers.getDiamondLoupeSelectors();
        commonFacetCuts[3] = IDiamondCut.FacetCut({
            facetAddress: ds.loupeFacet,
            action: IDiamondCut.FacetCutAction.Add,
            functionSelectors: functionSelectors
        });

        // Add DiamondProxy
        functionSelectors = LibDiamondHelpers.getDiamondProxySelectors();
        commonFacetCuts[4] = IDiamondCut.FacetCut({
            facetAddress: ds.proxyFacet,
            action: IDiamondCut.FacetCutAction.Add,
            functionSelectors: functionSelectors
        });
    }

    function _prepareTokenFiErc20Diamond(address tokenFiErc20, ITokenFiErc20.TokenInfo memory input) private {
        LibTokenLauncherFactoryStorage.DiamondStorage storage ds = LibTokenLauncherFactoryStorage.diamondStorage();

        IDiamondCut.FacetCut[] memory cut = _prepareCommonFacetCuts();

        // Add TokenFiErc20Facet
        bytes4[] memory functionSelectors = LibTokenLauncherFactoryStorage.getTokenFiErc20FunctionSelectors();
        cut[0] = IDiamondCut.FacetCut({ facetAddress: ds.tokenFiErc20Facet, action: IDiamondCut.FacetCutAction.Add, functionSelectors: functionSelectors });

        // Add Facets to TokenFiErc20 Diamond and initialize it
        bytes memory _calldata = abi.encodeCall(ITokenFiErc20Init.init, input);
        IDiamondCut(tokenFiErc20).diamondCut(cut, ds.tokenFiErc20DiamondInit, _calldata);
    }

    function _prepareTokenFiErc721Diamond(address tokenFiErc721, ITokenFiErc721.TokenInfo memory input) private {
        LibTokenLauncherFactoryStorage.DiamondStorage storage ds = LibTokenLauncherFactoryStorage.diamondStorage();

        IDiamondCut.FacetCut[] memory cut = _prepareCommonFacetCuts();

        // Add TokenFiErc721Facet
        bytes4[] memory functionSelectors = LibTokenLauncherFactoryStorage.getTokenFiErc721FunctionSelectors();

        cut[0] = IDiamondCut.FacetCut({ facetAddress: ds.tokenFiErc721Facet, action: IDiamondCut.FacetCutAction.Add, functionSelectors: functionSelectors });

        // Add Facets to TokenFiErc721 Diamond and initialize it
        bytes memory _calldata = abi.encodeCall(ITokenFiErc721Init.init, input);
        IDiamondCut(tokenFiErc721).diamondCut(cut, ds.tokenFiErc721DiamondInit, _calldata);
    }

    function _prepareTokenFiErc1155Diamond(address tokenFiErc1155, ITokenFiErc1155.TokenInfo memory input) private {
        LibTokenLauncherFactoryStorage.DiamondStorage storage ds = LibTokenLauncherFactoryStorage.diamondStorage();

        IDiamondCut.FacetCut[] memory cut = _prepareCommonFacetCuts();

        // Add TokenFiErc1155Facet
        bytes4[] memory functionSelectors = LibTokenLauncherFactoryStorage.getTokenFiErc1155FunctionSelectors();

        cut[0] = IDiamondCut.FacetCut({ facetAddress: ds.tokenFiErc1155Facet, action: IDiamondCut.FacetCutAction.Add, functionSelectors: functionSelectors });

        // Add Facets to TokenFiErc1155 Diamond and initialize it
        bytes memory _calldata = abi.encodeCall(ITokenFiErc1155Init.init, input);
        IDiamondCut(tokenFiErc1155).diamondCut(cut, ds.tokenFiErc1155DiamondInit, _calldata);
    }

    function _addToken(StoreTokenInput memory input) private {
        LibTokenLauncherFactoryStorage.DiamondStorage storage ds = LibTokenLauncherFactoryStorage.diamondStorage();

        ds.tokensByOwnerByType[input.tokenType][input.owner].push(input.tokenAddress);
        ds.tokenOwnerByToken[input.tokenAddress] = input.owner;
        ds.tokensByType[input.tokenType].push(input.tokenAddress);
        emit TokenCreated(ds.currentBlockTokenCreated, input);
        ds.currentBlockTokenCreated = block.number;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IAccessControl } from './IAccessControl.sol';
import { AccessControlInternal } from './AccessControlInternal.sol';

/**
 * @title Role-based access control system
 * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license)
 */
abstract contract AccessControl is IAccessControl, AccessControlInternal {
    /**
     * @inheritdoc IAccessControl
     */
    function grantRole(
        bytes32 role,
        address account
    ) external onlyRole(_getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @inheritdoc IAccessControl
     */
    function hasRole(
        bytes32 role,
        address account
    ) external view returns (bool) {
        return _hasRole(role, account);
    }

    /**
     * @inheritdoc IAccessControl
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32) {
        return _getRoleAdmin(role);
    }

    /**
     * @inheritdoc IAccessControl
     */
    function revokeRole(
        bytes32 role,
        address account
    ) external onlyRole(_getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @inheritdoc IAccessControl
     */
    function renounceRole(bytes32 role) external {
        _renounceRole(role);
    }

    /**
     * @inheritdoc IAccessControl
     */
    function getRoleMember(
        bytes32 role,
        uint256 index
    ) external view returns (address) {
        return _getRoleMember(role, index);
    }

    /**
     * @inheritdoc IAccessControl
     */
    function getRoleMemberCount(bytes32 role) external view returns (uint256) {
        return _getRoleMemberCount(role);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { EnumerableSet } from '../../data/EnumerableSet.sol';
import { AddressUtils } from '../../utils/AddressUtils.sol';
import { UintUtils } from '../../utils/UintUtils.sol';
import { IAccessControlInternal } from './IAccessControlInternal.sol';
import { AccessControlStorage } from './AccessControlStorage.sol';

/**
 * @title Role-based access control system
 * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license)
 */
abstract contract AccessControlInternal is IAccessControlInternal {
    using AddressUtils for address;
    using EnumerableSet for EnumerableSet.AddressSet;
    using UintUtils for uint256;

    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

    /*
     * @notice query whether role is assigned to account
     * @param role role to query
     * @param account account to query
     * @return whether role is assigned to account
     */
    function _hasRole(
        bytes32 role,
        address account
    ) internal view virtual returns (bool) {
        return
            AccessControlStorage.layout().roles[role].members.contains(account);
    }

    /**
     * @notice revert if sender does not have given role
     * @param role role to query
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, msg.sender);
    }

    /**
     * @notice revert if given account does not have given role
     * @param role role to query
     * @param account to query
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!_hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        'AccessControl: account ',
                        account.toString(),
                        ' is missing role ',
                        uint256(role).toHexString(32)
                    )
                )
            );
        }
    }

    /*
     * @notice query admin role for given role
     * @param role role to query
     * @return admin role
     */
    function _getRoleAdmin(
        bytes32 role
    ) internal view virtual returns (bytes32) {
        return AccessControlStorage.layout().roles[role].adminRole;
    }

    /**
     * @notice set role as admin role
     * @param role role to set
     * @param adminRole admin role to set
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = _getRoleAdmin(role);
        AccessControlStorage.layout().roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /*
     * @notice assign role to given account
     * @param role role to assign
     * @param account recipient of role assignment
     */
    function _grantRole(bytes32 role, address account) internal virtual {
        AccessControlStorage.layout().roles[role].members.add(account);
        emit RoleGranted(role, account, msg.sender);
    }

    /*
     * @notice unassign role from given account
     * @param role role to unassign
     * @parm account
     */
    function _revokeRole(bytes32 role, address account) internal virtual {
        AccessControlStorage.layout().roles[role].members.remove(account);
        emit RoleRevoked(role, account, msg.sender);
    }

    /**
     * @notice relinquish role
     * @param role role to relinquish
     */
    function _renounceRole(bytes32 role) internal virtual {
        _revokeRole(role, msg.sender);
    }

    /**
     * @notice query role for member at given index
     * @param role role to query
     * @param index index to query
     */
    function _getRoleMember(
        bytes32 role,
        uint256 index
    ) internal view virtual returns (address) {
        return AccessControlStorage.layout().roles[role].members.at(index);
    }

    /**
     * @notice query role for member count
     * @param role role to query
     */
    function _getRoleMemberCount(
        bytes32 role
    ) internal view virtual returns (uint256) {
        return AccessControlStorage.layout().roles[role].members.length();
    }
}

File 4 of 58 : AccessControlStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { EnumerableSet } from '../../data/EnumerableSet.sol';

library AccessControlStorage {
    struct RoleData {
        EnumerableSet.AddressSet members;
        bytes32 adminRole;
    }

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

    bytes32 internal constant DEFAULT_ADMIN_ROLE = 0x00;

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

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

/**
 * @title AccessControl interface
 */
interface IAccessControl is IAccessControlInternal {
    /*
     * @notice query whether role is assigned to account
     * @param role role to query
     * @param account account to query
     * @return whether role is assigned to account
     */
    function hasRole(
        bytes32 role,
        address account
    ) external view returns (bool);

    /*
     * @notice query admin role for given role
     * @param role role to query
     * @return admin role
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /*
     * @notice assign role to given account
     * @param role role to assign
     * @param account recipient of role assignment
     */
    function grantRole(bytes32 role, address account) external;

    /*
     * @notice unassign role from given account
     * @param role role to unassign
     * @parm account
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @notice relinquish role
     * @param role role to relinquish
     */
    function renounceRole(bytes32 role) external;

    /**
     * @notice Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(
        bytes32 role,
        uint256 index
    ) external view returns (address);

    /**
     * @notice Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role) external view returns (uint256);
}

File 6 of 58 : IAccessControlInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title Partial AccessControl interface needed by internal functions
 */
interface IAccessControlInternal {
    event RoleAdminChanged(
        bytes32 indexed role,
        bytes32 indexed previousAdminRole,
        bytes32 indexed newAdminRole
    );

    event RoleGranted(
        bytes32 indexed role,
        address indexed account,
        address indexed sender
    );

    event RoleRevoked(
        bytes32 indexed role,
        address indexed account,
        address indexed sender
    );
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

/**
 * @title Set implementation with enumeration functions
 * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license)
 */
library EnumerableSet {
    error EnumerableSet__IndexOutOfBounds();

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

    struct Bytes32Set {
        Set _inner;
    }

    struct AddressSet {
        Set _inner;
    }

    struct UintSet {
        Set _inner;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    function toArray(
        Bytes32Set storage set
    ) internal view returns (bytes32[] memory) {
        return set._inner._values;
    }

    function toArray(
        AddressSet storage set
    ) internal view returns (address[] memory) {
        bytes32[] storage values = set._inner._values;
        address[] storage array;

        assembly {
            array.slot := values.slot
        }

        return array;
    }

    function toArray(
        UintSet storage set
    ) internal view returns (uint256[] memory) {
        bytes32[] storage values = set._inner._values;
        uint256[] storage array;

        assembly {
            array.slot := values.slot
        }

        return array;
    }

    function _at(
        Set storage set,
        uint256 index
    ) private view returns (bytes32) {
        if (index >= set._values.length)
            revert EnumerableSet__IndexOutOfBounds();
        return set._values[index];
    }

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

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

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

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

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

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

                // move last value to now-vacant index

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

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

            status = true;
        }
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

/**
 * @title ERC1155 interface
 * @dev see https://eips.ethereum.org/EIPS/eip-1155
 */
interface IERC1155 is IERC1155Internal, IERC165 {
    /**
     * @notice query the balance of given token held by given address
     * @param account address to query
     * @param id token to query
     * @return token balance
     */
    function balanceOf(
        address account,
        uint256 id
    ) external view returns (uint256);

    /**
     * @notice query the balances of given tokens held by given addresses
     * @param accounts addresss to query
     * @param ids tokens to query
     * @return token balances
     */
    function balanceOfBatch(
        address[] calldata accounts,
        uint256[] calldata ids
    ) external view returns (uint256[] memory);

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

    /**
     * @notice grant approval to or revoke approval from given operator to spend held tokens
     * @param operator address whose approval status to update
     * @param status whether operator should be considered approved
     */
    function setApprovalForAll(address operator, bool status) external;

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

    /**
     * @notice transfer batch of tokens between given addresses, checking for ERC1155Receiver implementation if applicable
     * @param from sender of tokens
     * @param to receiver of tokens
     * @param ids list of token IDs
     * @param amounts list of quantities of tokens to transfer
     * @param data data payload
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) external;
}

File 9 of 58 : IERC1155Internal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

/**
 * @title Partial ERC1155 interface needed by internal functions
 */
interface IERC1155Internal {
    event TransferSingle(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256 id,
        uint256 value
    );

    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] values
    );

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

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

File 11 of 58 : IERC165Internal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

/**
 * @title ERC165 interface registration interface
 */
interface IERC165Internal {

}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

/**
 * @title ERC20 interface
 * @dev see https://eips.ethereum.org/EIPS/eip-20
 */
interface IERC20 is IERC20Internal {
    /**
     * @notice query the total minted token supply
     * @return token supply
     */
    function totalSupply() external view returns (uint256);

    /**
     * @notice query the token balance of given account
     * @param account address to query
     * @return token balance
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @notice query the allowance granted from given holder to given spender
     * @param holder approver of allowance
     * @param spender recipient of allowance
     * @return token allowance
     */
    function allowance(
        address holder,
        address spender
    ) external view returns (uint256);

    /**
     * @notice grant approval to spender to spend tokens
     * @dev prefer ERC20Extended functions to avoid transaction-ordering vulnerability (see https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729)
     * @param spender recipient of allowance
     * @param amount quantity of tokens approved for spending
     * @return success status (always true; otherwise function should revert)
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @notice transfer tokens to given recipient
     * @param recipient beneficiary of token transfer
     * @param amount quantity of tokens to transfer
     * @return success status (always true; otherwise function should revert)
     */
    function transfer(
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @notice transfer tokens to given recipient on behalf of given holder
     * @param holder holder of tokens prior to transfer
     * @param recipient beneficiary of token transfer
     * @param amount quantity of tokens to transfer
     * @return success status (always true; otherwise function should revert)
     */
    function transferFrom(
        address holder,
        address recipient,
        uint256 amount
    ) external returns (bool);
}

File 13 of 58 : IERC20Internal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

/**
 * @title Partial ERC20 interface needed by internal functions
 */
interface IERC20Internal {
    event Transfer(address indexed from, address indexed to, uint256 value);

    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

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

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

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

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

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

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

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

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

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

File 15 of 58 : IERC721Internal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

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

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

interface IPausable is IPausableInternal {
    /**
     * @notice query whether contract is paused
     * @return status whether contract is paused
     */
    function paused() external view returns (bool status);
}

File 17 of 58 : IPausableInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

interface IPausableInternal {
    error Pausable__Paused();
    error Pausable__NotPaused();

    event Paused(address account);
    event Unpaused(address account);
}

File 18 of 58 : Pausable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IPausable } from './IPausable.sol';
import { PausableInternal } from './PausableInternal.sol';

/**
 * @title Pausable security control module.
 */
abstract contract Pausable is IPausable, PausableInternal {
    /**
     * @inheritdoc IPausable
     */
    function paused() external view virtual returns (bool status) {
        status = _paused();
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IPausableInternal } from './IPausableInternal.sol';
import { PausableStorage } from './PausableStorage.sol';

/**
 * @title Internal functions for Pausable security control module.
 */
abstract contract PausableInternal is IPausableInternal {
    modifier whenNotPaused() {
        if (_paused()) revert Pausable__Paused();
        _;
    }

    modifier whenPaused() {
        if (!_paused()) revert Pausable__NotPaused();
        _;
    }

    /**
     * @notice query whether contract is paused
     * @return status whether contract is paused
     */
    function _paused() internal view virtual returns (bool status) {
        status = PausableStorage.layout().paused;
    }

    /**
     * @notice Triggers paused state, when contract is unpaused.
     */
    function _pause() internal virtual whenNotPaused {
        PausableStorage.layout().paused = true;
        emit Paused(msg.sender);
    }

    /**
     * @notice Triggers unpaused state, when contract is paused.
     */
    function _unpause() internal virtual whenPaused {
        delete PausableStorage.layout().paused;
        emit Unpaused(msg.sender);
    }
}

File 20 of 58 : PausableStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

library PausableStorage {
    struct Layout {
        bool paused;
    }

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

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

File 21 of 58 : IERC1155BaseInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IERC1155Internal } from '../../../interfaces/IERC1155Internal.sol';

/**
 * @title ERC1155 base interface
 */
interface IERC1155BaseInternal is IERC1155Internal {
    error ERC1155Base__ArrayLengthMismatch();
    error ERC1155Base__BalanceQueryZeroAddress();
    error ERC1155Base__NotOwnerOrApproved();
    error ERC1155Base__SelfApproval();
    error ERC1155Base__BurnExceedsBalance();
    error ERC1155Base__BurnFromZeroAddress();
    error ERC1155Base__ERC1155ReceiverRejected();
    error ERC1155Base__ERC1155ReceiverNotImplemented();
    error ERC1155Base__MintToZeroAddress();
    error ERC1155Base__TransferExceedsBalance();
    error ERC1155Base__TransferToZeroAddress();
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

/**
 * @title ERC1155 enumerable and aggregate function interface
 */
interface IERC1155Enumerable is IERC1155BaseInternal {
    /**
     * @notice query total minted supply of given token
     * @param id token id to query
     * @return token supply
     */
    function totalSupply(uint256 id) external view returns (uint256);

    /**
     * @notice query total number of holders for given token
     * @param id token id to query
     * @return quantity of holders
     */
    function totalHolders(uint256 id) external view returns (uint256);

    /**
     * @notice query holders of given token
     * @param id token id to query
     * @return list of holder addresses
     */
    function accountsByToken(
        uint256 id
    ) external view returns (address[] memory);

    /**
     * @notice query tokens held by given address
     * @param account address to query
     * @return list of token ids
     */
    function tokensByAccount(
        address account
    ) external view returns (uint256[] memory);
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

/**
 * @title ERC1155Metadata interface
 */
interface IERC1155Metadata is IERC1155MetadataInternal {
    /**
     * @notice get generated URI for given token
     * @return token URI
     */
    function uri(uint256 tokenId) external view returns (string memory);
}

File 24 of 58 : IERC1155MetadataInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

/**
 * @title Partial ERC1155Metadata interface needed by internal functions
 */
interface IERC1155MetadataInternal {
    event URI(string value, uint256 indexed tokenId);
}

File 25 of 58 : IERC20BaseInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IERC20Internal } from '../../../interfaces/IERC20Internal.sol';

/**
 * @title ERC20 base interface
 */
interface IERC20BaseInternal is IERC20Internal {
    error ERC20Base__ApproveFromZeroAddress();
    error ERC20Base__ApproveToZeroAddress();
    error ERC20Base__BurnExceedsBalance();
    error ERC20Base__BurnFromZeroAddress();
    error ERC20Base__InsufficientAllowance();
    error ERC20Base__MintToZeroAddress();
    error ERC20Base__TransferExceedsBalance();
    error ERC20Base__TransferFromZeroAddress();
    error ERC20Base__TransferToZeroAddress();
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

/**
 * @title ERC20 extended interface
 */
interface IERC20Extended is IERC20ExtendedInternal {
    /**
     * @notice increase spend amount granted to spender
     * @param spender address whose allowance to increase
     * @param amount quantity by which to increase allowance
     * @return success status (always true; otherwise function will revert)
     */
    function increaseAllowance(
        address spender,
        uint256 amount
    ) external returns (bool);

    /**
     * @notice decrease spend amount granted to spender
     * @param spender address whose allowance to decrease
     * @param amount quantity by which to decrease allowance
     * @return success status (always true; otherwise function will revert)
     */
    function decreaseAllowance(
        address spender,
        uint256 amount
    ) external returns (bool);
}

File 27 of 58 : IERC20ExtendedInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

/**
 * @title ERC20 extended internal interface
 */
interface IERC20ExtendedInternal is IERC20BaseInternal {
    error ERC20Extended__ExcessiveAllowance();
    error ERC20Extended__InsufficientAllowance();
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

/**
 * @title ERC20 metadata interface
 */
interface IERC20Metadata is IERC20MetadataInternal {
    /**
     * @notice return token name
     * @return token name
     */
    function name() external view returns (string memory);

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

    /**
     * @notice return token decimals, generally used only for display purposes
     * @return token decimals
     */
    function decimals() external view returns (uint8);
}

File 29 of 58 : IERC20MetadataInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

/**
 * @title ERC20 metadata internal interface
 */
interface IERC20MetadataInternal {

}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

/**
 * @title ERC2612 interface
 * @dev see https://eips.ethereum.org/EIPS/eip-2612.
 */
interface IERC2612 is IERC2612Internal {
    /**
     * @notice return the EIP-712 domain separator unique to contract and chain
     * @return domainSeparator domain separator
     */
    function DOMAIN_SEPARATOR() external view returns (bytes32 domainSeparator);

    /**
     * @notice get the current ERC2612 nonce for the given address
     * @return current nonce
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @notice approve spender to transfer tokens held by owner via signature
     * @dev this function may be vulnerable to approval replay attacks
     * @param owner holder of tokens and signer of permit
     * @param spender beneficiary of approval
     * @param amount quantity of tokens to approve
     * @param v secp256k1 'v' value
     * @param r secp256k1 'r' value
     * @param s secp256k1 's' value
     */
    function permit(
        address owner,
        address spender,
        uint256 amount,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;
}

File 31 of 58 : IERC2612Internal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

interface IERC2612Internal {}

File 32 of 58 : IERC721BaseInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IERC721Internal } from '../../../interfaces/IERC721Internal.sol';

/**
 * @title ERC721 base interface
 */
interface IERC721BaseInternal is IERC721Internal {
    error ERC721Base__NotOwnerOrApproved();
    error ERC721Base__SelfApproval();
    error ERC721Base__BalanceQueryZeroAddress();
    error ERC721Base__ERC721ReceiverNotImplemented();
    error ERC721Base__InvalidOwner();
    error ERC721Base__MintToZeroAddress();
    error ERC721Base__NonExistentToken();
    error ERC721Base__NotTokenOwner();
    error ERC721Base__TokenAlreadyMinted();
    error ERC721Base__TransferToZeroAddress();
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

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

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

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

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

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

File 35 of 58 : IERC721MetadataInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

/**
 * @title ERC721Metadata internal interface
 */
interface IERC721MetadataInternal is IERC721BaseInternal {
    error ERC721Metadata__NonExistentToken();
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

library AddressUtils {
    using UintUtils for uint256;

    error AddressUtils__InsufficientBalance();
    error AddressUtils__NotContract();
    error AddressUtils__SendValueFailed();

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

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

    function sendValue(address payable account, uint256 amount) internal {
        (bool success, ) = account.call{ value: amount }('');
        if (!success) revert AddressUtils__SendValueFailed();
    }

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

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

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

    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory error
    ) internal returns (bytes memory) {
        if (value > address(this).balance)
            revert AddressUtils__InsufficientBalance();
        return _functionCallWithValue(target, data, value, error);
    }

    /**
     * @notice execute arbitrary external call with limited gas usage and amount of copied return data
     * @dev derived from https://github.com/nomad-xyz/ExcessivelySafeCall (MIT License)
     * @param target recipient of call
     * @param gasAmount gas allowance for call
     * @param value native token value to include in call
     * @param maxCopy maximum number of bytes to copy from return data
     * @param data encoded call data
     * @return success whether call is successful
     * @return returnData copied return data
     */
    function excessivelySafeCall(
        address target,
        uint256 gasAmount,
        uint256 value,
        uint16 maxCopy,
        bytes memory data
    ) internal returns (bool success, bytes memory returnData) {
        returnData = new bytes(maxCopy);

        assembly {
            // execute external call via assembly to avoid automatic copying of return data
            success := call(
                gasAmount,
                target,
                value,
                add(data, 0x20),
                mload(data),
                0,
                0
            )

            // determine whether to limit amount of data to copy
            let toCopy := returndatasize()

            if gt(toCopy, maxCopy) {
                toCopy := maxCopy
            }

            // store the length of the copied bytes
            mstore(returnData, toCopy)

            // copy the bytes from returndata[0:toCopy]
            returndatacopy(add(returnData, 0x20), 0, toCopy)
        }
    }

    function _functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory error
    ) private returns (bytes memory) {
        if (!isContract(target)) revert AddressUtils__NotContract();

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

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

/**
 * @title utility functions for uint256 operations
 * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts/ (MIT license)
 */
library UintUtils {
    error UintUtils__InsufficientHexLength();

    bytes16 private constant HEX_SYMBOLS = '0123456789abcdef';

    function add(uint256 a, int256 b) internal pure returns (uint256) {
        return b < 0 ? sub(a, -b) : a + uint256(b);
    }

    function sub(uint256 a, int256 b) internal pure returns (uint256) {
        return b < 0 ? add(a, -b) : a - uint256(b);
    }

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

        uint256 temp = value;
        uint256 digits;

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

        bytes memory buffer = new bytes(digits);

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

        return string(buffer);
    }

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

        uint256 length = 0;

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

        return toHexString(value, length);
    }

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

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

        if (value != 0) revert UintUtils__InsufficientHexLength();

        return string(buffer);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import { IPaymentModule } from "./IPaymentModule.sol";

interface ICrossPaymentModule {
    struct CrossPaymentSignatureInput {
        address payer;
        uint256 sourceChainId;
        uint256 paymentIndex;
        bytes signature;
    }

    struct ProcessCrossPaymentOutput {
        bytes32 platformId;
        uint32[] services;
        uint32[] serviceAmounts;
        address spender;
        uint256 destinationChainId;
        address payer;
        uint256 sourceChainId;
        uint256 paymentIndex;
    }

    function updateCrossPaymentSignerAddress(address newSignerAddress) external;
    function processCrossPayment(
        IPaymentModule.ProcessPaymentInput memory paymentInput,
        address spender,
        uint256 destinationChainId
    ) external payable returns (uint256);
    function spendCrossPaymentSignature(address spender, ProcessCrossPaymentOutput memory output, bytes memory signature) external;
    function getCrossPaymentSignerAddress() external view returns (address);
    function getCrossPaymentOutputByIndex(uint256 paymentIndex) external view returns (ProcessCrossPaymentOutput memory);
    function prefixedMessage(bytes32 hash) external pure returns (bytes32);
    function getHashedMessage(ProcessCrossPaymentOutput memory output) external pure returns (bytes32);
    function recoverSigner(bytes32 message, bytes memory signature) external pure returns (address);
    function checkSignature(ProcessCrossPaymentOutput memory output, bytes memory signature) external view;
    function getChainID() external view returns (uint256);

    /** EVENTS */
    event CrossPaymentProcessed(uint256 indexed previousBlock, uint256 indexed paymentIndex);
    event CrossPaymentSignatureSpent(uint256 indexed previousBlock, uint256 indexed sourceChainId, uint256 indexed paymentIndex);
    event CrossPaymentSignerAddressUpdated(address indexed oldSigner, address indexed newSigner);

    /** ERRORS */
    error ProcessCrossPaymentError(string errorMessage);
    error CheckSignatureError(string errorMessage);
    error ProcessCrossPaymentSignatureError(string errorMessage);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

interface IPaymentModule {
    enum PaymentMethod {
        NATIVE,
        USD,
        ALTCOIN
    }

    enum PaymentType {
        NATIVE,
        GIFT,
        CROSSCHAIN
    }

    struct AcceptedToken {
        string name;
        PaymentMethod tokenType;
        address token;
        address router;
        bool isV2Router;
        uint256 slippageTolerance;
    }

    struct ProcessPaymentInput {
        bytes32 platformId;
        uint32[] services;
        uint32[] serviceAmounts;
        address referrer;
        address user;
        address tokenAddress;
    }

    struct ProcessPaymentOutput {
        ProcessPaymentInput processPaymentInput;
        uint256 usdPrice;
        uint256 paymentAmount;
        uint256 burnedAmount;
        uint256 treasuryShare;
        uint256 referrerShare;
    }

    struct ProcessCrossPaymentOutput {
        bytes32 platformId;
        uint32[] services;
        uint32[] serviceAmounts;
        address payer;
        address spender;
        uint256 sourceChainId;
        uint256 destinationChainId;
    }

    // solhint-disable-next-line func-name-mixedcase
    function PAYMENT_PROCESSOR_ROLE() external pure returns (bytes32);
    function adminWithdraw(address tokenAddress, uint256 amount, address treasury) external;
    function setUsdToken(address newUsdToken) external;
    function setRouterAddress(address newRouter) external;
    function addAcceptedToken(AcceptedToken memory acceptedToken) external;
    function removeAcceptedToken(address tokenAddress) external;
    function updateAcceptedToken(AcceptedToken memory acceptedToken) external;
    function setV3PoolFeeForTokenNative(address token, uint24 poolFee) external;
    function getUsdToken() external view returns (address);
    function processPayment(ProcessPaymentInput memory params) external payable returns (uint256);
    function getPaymentByIndex(uint256 paymentIndex) external view returns (ProcessPaymentOutput memory);
    function getQuoteTokenPrice(address token0, address token1) external view returns (uint256 price);
    function getV3PoolFeeForTokenWithNative(address token) external view returns (uint24);
    function isV2Router() external view returns (bool);
    function getRouterAddress() external view returns (address);
    function getAcceptedTokenByAddress(address tokenAddress) external view returns (AcceptedToken memory);
    function getAcceptedTokens() external view returns (address[] memory);

    /** EVENTS */
    event TokenBurned(uint256 indexed tokenBurnedLastBlock, address indexed tokenAddress, uint256 amount);
    event PaymentProcessed(uint256 indexed previousBlock, uint256 indexed paymentIndex);
    event TreasuryAddressUpdated(address indexed oldTreasury, address indexed newTreasury);

    /** ERRORS */
    error ProcessPaymentError(string errorMessage);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;
interface IPlatformModule {
    struct Service {
        string name;
        uint256 usdPrice;
    }

    struct Platform {
        string name;
        bytes32 id;
        address owner;
        address treasury;
        uint256 referrerBasisPoints;
        address burnToken;
        uint256 burnBasisPoints;
        bool isDiscountEnabled;
        Service[] services;
    }

    // solhint-disable-next-line func-name-mixedcase
    function PLATFORM_MANAGER_ROLE() external pure returns (bytes32);

    function getPlatformCount() external view returns (uint256);

    function getPlatformIds() external view returns (bytes32[] memory);

    function getPlatformIdByIndex(uint256 index) external view returns (bytes32);

    function getPlatformById(bytes32 platformId) external view returns (IPlatformModule.Platform memory);

    function addPlatform(IPlatformModule.Platform memory platform) external;

    function removePlatform(uint256 index) external;

    function updatePlatform(IPlatformModule.Platform memory platform) external;

    function addPlatformService(bytes32 platformId, IPlatformModule.Service memory service) external;

    function removePlatformService(bytes32 platformId, uint256 serviceId) external;

    function updatePlatformService(bytes32 platformId, uint256 serviceId, IPlatformModule.Service memory service) external;
}

File 41 of 58 : LibPaymentModuleConsts.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

library LibPaymentModuleConsts {
    bytes32 internal constant PAYMENT_PROCESSOR_ROLE = keccak256("PAYMENT_PROCESSOR_ROLE");
    bytes32 internal constant PLATFORM_MANAGER_ROLE = keccak256("PLATFORM_MANAGER_ROLE");
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/******************************************************************************\
* Author: Nick Mudge <nick@perfectabstractions.com> (https://twitter.com/mudgen)
* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535
*
* Implementation of a diamond.
/******************************************************************************/

import { LibDiamond } from "./libraries/LibDiamond.sol";
import { IDiamondCut } from "./interfaces/IDiamondCut.sol";

contract Diamond {
    constructor(address _contractOwner, address _diamondCutFacet) payable {
        LibDiamond.setContractOwner(_contractOwner);

        // Add the diamondCut external function from the diamondCutFacet
        IDiamondCut.FacetCut[] memory cut = new IDiamondCut.FacetCut[](1);
        bytes4[] memory functionSelectors = new bytes4[](1);
        functionSelectors[0] = IDiamondCut.diamondCut.selector;
        cut[0] = IDiamondCut.FacetCut({ facetAddress: _diamondCutFacet, action: IDiamondCut.FacetCutAction.Add, functionSelectors: functionSelectors });
        LibDiamond.diamondCut(cut, address(0), "");
    }

    // Find facet for function that is called and execute the
    // function if a facet is found and return any value.
    // solhint-disable-next-line no-complex-fallback
    fallback() external payable {
        LibDiamond.DiamondStorage storage ds;
        bytes32 position = LibDiamond.DIAMOND_STORAGE_POSITION;
        // get diamond storage
        assembly {
            ds.slot := position
        }
        // get facet from function selector
        address facet = ds.selectorToFacetAndPosition[msg.sig].facetAddress;
        require(facet != address(0), "Diamond: Function does not exist");
        // Execute external function from facet using delegatecall and return any value.
        assembly {
            // copy function selector and any arguments
            calldatacopy(0, 0, calldatasize())
            // execute function call using the facet
            let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)
            // get any return value
            returndatacopy(0, 0, returndatasize())
            // return any return value or error back to the caller
            switch result
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    receive() external payable {}
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/******************************************************************************\
* Author: Nick Mudge <nick@perfectabstractions.com> (https://twitter.com/mudgen)
* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535
/******************************************************************************/

interface IDiamondCut {
    enum FacetCutAction {
        Add,
        Replace,
        Remove
    }
    // Add=0, Replace=1, Remove=2

    struct FacetCut {
        address facetAddress;
        FacetCutAction action;
        bytes4[] functionSelectors;
    }

    /// @notice Add/replace/remove any number of functions and optionally execute
    ///         a function with delegatecall
    /// @param _diamondCut Contains the facet addresses and function selectors
    /// @param _init The address of the contract or facet to execute _calldata
    /// @param _calldata A function call, including function selector and arguments
    ///                  _calldata is executed with delegatecall on _init
    function diamondCut(FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata) external;
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/******************************************************************************\
* Author: Nick Mudge <nick@perfectabstractions.com> (https://twitter.com/mudgen)
* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535
/******************************************************************************/

// A loupe is a small magnifying glass used to look at diamonds.
// These functions look at diamonds
interface IDiamondLoupe {
    /// These functions are expected to be called frequently
    /// by tools.

    struct Facet {
        address facetAddress;
        bytes4[] functionSelectors;
    }

    /// @notice Gets all facet addresses and their four byte function selectors.
    /// @return facets_ Facet
    function facets() external view returns (Facet[] memory facets_);

    /// @notice Gets all the function selectors supported by a specific facet.
    /// @param _facet The facet address.
    /// @return facetFunctionSelectors_
    function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory facetFunctionSelectors_);

    /// @notice Get all the facet addresses used by a diamond.
    /// @return facetAddresses_
    function facetAddresses() external view returns (address[] memory facetAddresses_);

    /// @notice Gets the facet that supports the given selector.
    /// @dev If facet is not found return address(0).
    /// @param _functionSelector The function selector.
    /// @return facetAddress_ The facet address.
    function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/******************************************************************************\
* Author: Nick Mudge <nick@perfectabstractions.com> (https://twitter.com/mudgen)
* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535
/******************************************************************************/

interface IDiamondProxy {
    function implementation() external view returns (address);

    function setImplementation(address _implementation) external;
}

// SPDX-License-Identifier: MIT

pragma solidity 0.8.23;

import { IPausable } from "@solidstate/contracts/security/pausable/Pausable.sol";

interface IPausableFacet is IPausable {
    function pause() external;

    function unpause() external;
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/******************************************************************************\
* Author: Nick Mudge <nick@perfectabstractions.com> (https://twitter.com/mudgen)
* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535
/******************************************************************************/
import { IDiamondCut } from "../interfaces/IDiamondCut.sol";

// Remember to add the loupe functions from DiamondLoupeFacet to the diamond.
// The loupe functions are required by the EIP2535 Diamonds standard

error InitializationFunctionReverted(address _initializationContractAddress, bytes _calldata);

library LibDiamond {
    bytes32 public constant DIAMOND_STORAGE_POSITION = keccak256("diamond.standard.diamond.storage");

    struct FacetAddressAndPosition {
        address facetAddress;
        uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array
    }

    struct FacetFunctionSelectors {
        bytes4[] functionSelectors;
        uint256 facetAddressPosition; // position of facetAddress in facetAddresses array
    }

    struct DiamondStorage {
        // maps function selector to the facet address and
        // the position of the selector in the facetFunctionSelectors.selectors array
        mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;
        // maps facet addresses to function selectors
        mapping(address => FacetFunctionSelectors) facetFunctionSelectors;
        // facet addresses
        address[] facetAddresses;
        // Used to query if a contract implements an interface.
        // Used to implement ERC-165.
        mapping(bytes4 => bool) supportedInterfaces;
        // owner of the contract
        address contractOwner;
    }

    function diamondStorage() internal pure returns (DiamondStorage storage ds) {
        bytes32 position = DIAMOND_STORAGE_POSITION;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            ds.slot := position
        }
    }

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

    function setContractOwner(address _newOwner) internal {
        DiamondStorage storage ds = diamondStorage();
        address previousOwner = ds.contractOwner;
        ds.contractOwner = _newOwner;
        emit OwnershipTransferred(previousOwner, _newOwner);
    }

    function contractOwner() internal view returns (address contractOwner_) {
        contractOwner_ = diamondStorage().contractOwner;
    }

    function enforceIsContractOwner() internal view {
        require(msg.sender == diamondStorage().contractOwner, "LibDiamond: Must be contract owner");
    }

    event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);

    // Internal function version of diamondCut
    function diamondCut(IDiamondCut.FacetCut[] memory _diamondCut, address _init, bytes memory _calldata) internal {
        for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) {
            IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;
            if (action == IDiamondCut.FacetCutAction.Add) {
                addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);
            } else if (action == IDiamondCut.FacetCutAction.Replace) {
                replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);
            } else if (action == IDiamondCut.FacetCutAction.Remove) {
                removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);
            } else {
                revert("LibDiamondCut: Incorrect FacetCutAction");
            }
        }
        emit DiamondCut(_diamondCut, _init, _calldata);
        initializeDiamondCut(_init, _calldata);
    }

    function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {
        require(_functionSelectors.length > 0, "LibDiamondCut: No selectors in facet to cut");
        DiamondStorage storage ds = diamondStorage();
        require(_facetAddress != address(0), "LibDiamondCut: Add facet can't be address(0)");
        uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);
        // add new facet address if it does not exist
        if (selectorPosition == 0) {
            addFacet(ds, _facetAddress);
        }
        for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
            bytes4 selector = _functionSelectors[selectorIndex];
            address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;
            require(oldFacetAddress == address(0), "LibDiamondCut: Can't add function that already exists");
            addFunction(ds, selector, selectorPosition, _facetAddress);
            selectorPosition++;
        }
    }

    function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {
        require(_functionSelectors.length > 0, "LibDiamondCut: No selectors in facet to cut");
        DiamondStorage storage ds = diamondStorage();
        require(_facetAddress != address(0), "LibDiamondCut: Add facet can't be address(0)");
        uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);
        // add new facet address if it does not exist
        if (selectorPosition == 0) {
            addFacet(ds, _facetAddress);
        }
        for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
            bytes4 selector = _functionSelectors[selectorIndex];
            address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;
            require(oldFacetAddress != _facetAddress, "LibDiamondCut: Can't replace function with same function");
            removeFunction(ds, oldFacetAddress, selector);
            addFunction(ds, selector, selectorPosition, _facetAddress);
            selectorPosition++;
        }
    }

    function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {
        require(_functionSelectors.length > 0, "LibDiamondCut: No selectors in facet to cut");
        DiamondStorage storage ds = diamondStorage();
        // if function does not exist then do nothing and return
        require(_facetAddress == address(0), "LibDiamondCut: Remove facet address must be address(0)");
        for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
            bytes4 selector = _functionSelectors[selectorIndex];
            address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;
            removeFunction(ds, oldFacetAddress, selector);
        }
    }

    function addFacet(DiamondStorage storage ds, address _facetAddress) internal {
        enforceHasContractCode(_facetAddress, "LibDiamondCut: New facet has no code");
        ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds.facetAddresses.length;
        ds.facetAddresses.push(_facetAddress);
    }

    function addFunction(DiamondStorage storage ds, bytes4 _selector, uint96 _selectorPosition, address _facetAddress) internal {
        ds.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;
        ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);
        ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;
    }

    function removeFunction(DiamondStorage storage ds, address _facetAddress, bytes4 _selector) internal {
        require(_facetAddress != address(0), "LibDiamondCut: Can't remove function that doesn't exist");
        // an immutable function is a function defined directly in a diamond
        require(_facetAddress != address(this), "LibDiamondCut: Can't remove immutable function");
        // replace selector with last selector, then delete last selector
        uint256 selectorPosition = ds.selectorToFacetAndPosition[_selector].functionSelectorPosition;
        uint256 lastSelectorPosition = ds.facetFunctionSelectors[_facetAddress].functionSelectors.length - 1;
        // if not the same then replace _selector with lastSelector
        if (selectorPosition != lastSelectorPosition) {
            bytes4 lastSelector = ds.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];
            ds.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;
            ds.selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);
        }
        // delete the last selector
        ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();
        delete ds.selectorToFacetAndPosition[_selector];

        // if no more selectors for facet address then delete the facet address
        if (lastSelectorPosition == 0) {
            // replace facet address with last facet address and delete last facet address
            uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;
            uint256 facetAddressPosition = ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;
            if (facetAddressPosition != lastFacetAddressPosition) {
                address lastFacetAddress = ds.facetAddresses[lastFacetAddressPosition];
                ds.facetAddresses[facetAddressPosition] = lastFacetAddress;
                ds.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;
            }
            ds.facetAddresses.pop();
            delete ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;
        }
    }

    function initializeDiamondCut(address _init, bytes memory _calldata) internal {
        if (_init == address(0)) {
            return;
        }
        enforceHasContractCode(_init, "LibDiamondCut: _init address has no code");
        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory error) = _init.delegatecall(_calldata);
        if (!success) {
            if (error.length > 0) {
                // bubble up error
                /// @solidity memory-safe-assembly
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(error)
                    revert(add(32, error), returndata_size)
                }
            } else {
                revert InitializationFunctionReverted(_init, _calldata);
            }
        }
    }

    function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {
        uint256 contractSize;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            contractSize := extcodesize(_contract)
        }
        require(contractSize > 0, _errorMessage);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import { IAccessControl } from "@solidstate/contracts/access/access_control/AccessControl.sol";

import { IDiamondLoupe } from "../interfaces/IDiamondLoupe.sol";
import { IDiamondProxy } from "../interfaces/IDiamondProxy.sol";
import { IPausableFacet, IPausable } from "../interfaces/IPausableFacet.sol";

library LibDiamondHelpers {
    function getAccessControlSelectors() internal pure returns (bytes4[] memory functionSelectors) {
        functionSelectors = new bytes4[](7);
        functionSelectors[0] = IAccessControl.hasRole.selector;
        functionSelectors[1] = IAccessControl.getRoleAdmin.selector;
        functionSelectors[2] = IAccessControl.grantRole.selector;
        functionSelectors[3] = IAccessControl.revokeRole.selector;
        functionSelectors[4] = IAccessControl.renounceRole.selector;
        functionSelectors[5] = IAccessControl.getRoleMember.selector;
        functionSelectors[6] = IAccessControl.getRoleMemberCount.selector;
    }

    function getPausableSelectors() internal pure returns (bytes4[] memory functionSelectors) {
        functionSelectors = new bytes4[](3);
        functionSelectors[0] = IPausable.paused.selector;
        functionSelectors[1] = IPausableFacet.pause.selector;
        functionSelectors[2] = IPausableFacet.unpause.selector;
    }

    function getDiamondLoupeSelectors() internal pure returns (bytes4[] memory functionSelectors) {
        functionSelectors = new bytes4[](4);
        functionSelectors[0] = IDiamondLoupe.facetFunctionSelectors.selector;
        functionSelectors[1] = IDiamondLoupe.facetAddress.selector;
        functionSelectors[2] = IDiamondLoupe.facetAddresses.selector;
        functionSelectors[3] = IDiamondLoupe.facets.selector;
    }

    function getDiamondProxySelectors() internal pure returns (bytes4[] memory functionSelectors) {
        functionSelectors = new bytes4[](2);
        functionSelectors[0] = IDiamondProxy.implementation.selector;
        functionSelectors[1] = IDiamondProxy.setImplementation.selector;
    }

    function getReentrancyGuardSelectors() internal pure returns (bytes4[] memory functionSelectors) {
        functionSelectors = new bytes4[](0);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import { ICrossPaymentModule } from "../../common/admin/interfaces/ICrossPaymentModule.sol";

interface ITokenFiErc1155 {
    struct TokenInfo {
        string name;
        string symbol;
        string collectionLogo;
        string baseURI;
        bool isPublicMintEnabled;
        bool isAdminMintEnabled;
        address owner;
    }

    struct CreateTokenInput {
        uint256 tokenId;
        uint256 maxSupply;
        uint256 publicMintUsdPrice;
        uint8 decimals;
        string uri;
    }

    function adminMint(address account, uint256 id, uint256 amount) external;
    function setTokenInfo(TokenInfo memory _newTokenInfo) external;
    function createToken(CreateTokenInput memory input) external;
    function setTokenPublicMintPrice(uint256 _tokenId, uint256 _price) external;
    function setTokenUri(uint256 _tokenId, string memory _uri) external;
    function mint(address account, uint256 id, uint256 amount, address paymentToken, address referrer) external payable;
    function mintWithPaymentSignature(
        address account,
        uint256 id,
        uint256 amount,
        ICrossPaymentModule.CrossPaymentSignatureInput memory crossPaymentSignatureInput
    ) external;
    function tokenInfo() external view returns (TokenInfo memory);
    function maxSupply(uint256 tokenId) external view returns (uint256);
    function decimals(uint256 tokenId) external view returns (uint256);
    function paymentServiceIndexByTokenId(uint256 tokenId) external view returns (uint256);
    function exists(uint256 id) external view returns (bool);
    function getExistingTokenIds() external view returns (uint256[] memory);
    function paymentModule() external view returns (address);

    event TokenInfoUpdated(TokenInfo indexed oldTokenInfo, TokenInfo indexed newTokenInfo);
    event MintPaymentProccessed(address indexed user, uint256 indexed paymentId);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import { ITokenFiErc1155 } from "./ITokenFiErc1155.sol";

interface ITokenFiErc1155Init {
    function init(ITokenFiErc1155.TokenInfo memory input) external;
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

interface ITokenFiErc20 {
    struct FeeDetails {
        uint256 percentage;
        bool onlyOnSwaps;
    }

    struct Fees {
        FeeDetails transferFee;
        FeeDetails burn;
        FeeDetails reflection;
        FeeDetails buyback;
    }

    struct BuybackDetails {
        address pairToken;
        address router;
        uint256 liquidityBasisPoints;
        uint256 priceImpactBasisPoints;
    }

    struct TokenInfo {
        string name;
        string symbol;
        string logo;
        uint8 decimals;
        uint256 initialSupply;
        uint256 maxSupply;
        address treasury;
        address owner;
        Fees fees;
        BuybackDetails buybackDetails;
    }

    struct TotalReflection {
        uint256 tTotal;
        uint256 rTotal;
        uint256 tFeeTotal;
    }

    struct ReflectionInfo {
        TotalReflection totalReflection;
        mapping(address => uint256) rOwned;
        mapping(address => uint256) tOwned;
        mapping(address => bool) isExcludedFromReflectionRewards;
        address[] excluded;
    }

    /** ONLY ROLES */
    function mint(address to, uint256 amount) external;
    function updateTokenLauncher(address _newTokenLauncher) external;
    function updateTreasury(address _newTreasury) external;
    function setName(string memory name) external;
    function setSymbol(string memory symbol) external;
    function setDecimals(uint8 decimals) external;
    function updateFees(Fees memory _fees) external;
    function setBuybackDetails(BuybackDetails memory _buybackDetails) external;
    function setBuybackHandler(address _newBuybackHandler) external;
    function addExchangePool(address pool) external;
    function removeExchangePool(address pool) external;
    function addExemptAddress(address account) external;
    function removeExemptAddress(address account) external;

    /** VIEW */
    function fees() external view returns (Fees memory);
    function tokenInfo() external view returns (TokenInfo memory);
    function buybackHandler() external view returns (address);
    function isExchangePool(address pool) external view returns (bool);
    function isExemptedFromTax(address account) external view returns (bool);
    function isReflectionToken() external view returns (bool);

    /** REFLECTION Implemetation */
    function reflect(uint256 tAmount) external;
    function excludeAccount(address account) external;
    function includeAccount(address account) external;
    function isExcludedFromReflectionRewards(address account) external view returns (bool);
    function totalReflection() external view returns (TotalReflection memory);
    function reflectionFromToken(uint256 tAmount, bool deductTransferFee) external view returns (uint256);
    function tokenFromReflection(uint256 rAmount) external view returns (uint256);
    function totalFees() external view returns (uint256);

    event ExemptedAdded(address indexed account);
    event ExemptedRemoved(address indexed account);
    event ExchangePoolAdded(address indexed pool);
    event ExchangePoolRemoved(address indexed pool);
    event TokenLauncherUpdated(address indexed oldTokenLauncher, address indexed newTokenLauncher);
    event TransferTax(address indexed account, address indexed receiver, uint256 amount, string indexed taxType);
    event BuybackHandlerUpdated(address indexed oldBuybackHandler, address indexed newBuybackHandler);
    event BuybackDetailsUpdated(address indexed router, address indexed pairToken, uint256 liquidityBasisPoints, uint256 priceImpactBasisPoints);
    event TreasuryUpdated(address indexed oldTreasury, address indexed newTreasury);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import { ITokenFiErc20 } from "./ITokenFiErc20.sol";

interface ITokenFiErc20Init {
    function init(ITokenFiErc20.TokenInfo memory input) external;
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import { ICrossPaymentModule } from "../../common/admin/interfaces/ICrossPaymentModule.sol";

interface ITokenFiErc721 {
    enum PaymentServices {
        TOKEN_MINT
    }

    struct TokenInfo {
        string name;
        string symbol;
        string collectionLogo;
        string baseURI;
        uint256 maxSupply;
        bool isPublicMintEnabled;
        bool isAdminMintEnabled;
        address owner;
    }

    function adminMint(address _to) external;
    function adminMintBatch(address _to, uint256 _amount) external;
    function setTokenInfo(TokenInfo memory _newTokenInfo) external;
    function setTokenUri(uint256 tokenId, string memory uri) external;
    function mint(address _to, address paymentToken, address referrer) external payable;
    function mintWithPaymentSignature(address _to, ICrossPaymentModule.CrossPaymentSignatureInput memory crossPaymentSignatureInput) external;
    function mintBatch(address _to, uint256 _amount, address paymentToken, address referrer) external payable;
    function mintBatchWithPaymentSignature(
        address _to,
        uint256 _amount,
        ICrossPaymentModule.CrossPaymentSignatureInput memory crossPaymentSignatureInput
    ) external;
    function tokenInfo() external view returns (TokenInfo memory);
    function paymentModule() external view returns (address);

    event TokenInfoUpdated(TokenInfo indexed oldTokenInfo, TokenInfo indexed newTokenInfo);
    event MintPaymentProccessed(address indexed user, uint256 indexed paymentId);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import { ITokenFiErc721 } from "./ITokenFiErc721.sol";

interface ITokenFiErc721Init {
    function init(ITokenFiErc721.TokenInfo memory input) external;
}

File 55 of 58 : ITokenLauncherCommon.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

interface ITokenLauncherCommon {
    enum TokenType {
        ERC20,
        ERC721,
        ERC1155
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import { ITokenLauncherCommon } from "./ITokenLauncherCommon.sol";
import { ITokenFiErc20 } from "./ITokenFiErc20.sol";
import { ITokenFiErc721 } from "./ITokenFiErc721.sol";
import { ITokenFiErc1155 } from "./ITokenFiErc1155.sol";
import { ICrossPaymentModule } from "../../common/admin/interfaces/ICrossPaymentModule.sol";

interface ITokenLauncherFactory is ITokenLauncherCommon {
    struct CreateErc20Input {
        ITokenFiErc20.TokenInfo tokenInfo;
        address referrer;
        address paymentToken;
    }

    struct PublicErc721MintPaymentInfo {
        uint256 usdPrice;
        address treasury;
        uint256 burnBasisPoints;
        uint256 referrerBasisPoints;
    }

    struct CreateErc721Input {
        ITokenFiErc721.TokenInfo tokenInfo;
        PublicErc721MintPaymentInfo publicMintPaymentInfo;
        address referrer;
        address paymentToken;
    }

    struct PublicErc1155MintPaymentInfo {
        address treasury;
        uint256 burnBasisPoints;
        uint256 referrerBasisPoints;
    }

    struct CreateErc1155Input {
        ITokenFiErc1155.TokenInfo tokenInfo;
        PublicErc1155MintPaymentInfo publicMintPaymentInfo;
        ITokenFiErc1155.CreateTokenInput[] initialTokens;
        address referrer;
        address paymentToken;
    }

    struct StoreTokenInput {
        address tokenAddress;
        address owner;
        address referrer;
        uint256 paymentIndex;
        TokenType tokenType;
    }

    function createErc20(CreateErc20Input memory input) external payable returns (address tokenAddress);
    function createErc20WithPaymentSignature(
        CreateErc20Input memory input,
        ICrossPaymentModule.CrossPaymentSignatureInput memory crossPaymentSignatureInput
    ) external returns (address tokenAddress);
    function createErc721(CreateErc721Input memory input) external payable returns (address tokenAddress);
    function createErc721WithPaymentSignature(
        CreateErc721Input memory input,
        ICrossPaymentModule.CrossPaymentSignatureInput memory crossPaymentSignatureInput
    ) external returns (address tokenAddress);
    function createErc1155(CreateErc1155Input memory input) external payable returns (address tokenAddress);
    function createErc1155WithPaymentSignature(
        CreateErc1155Input memory input,
        ICrossPaymentModule.CrossPaymentSignatureInput memory crossPaymentSignatureInput
    ) external returns (address tokenAddress);

    /** EVNETS */
    event TokenCreated(uint256 indexed currentBlockTokenCreated, StoreTokenInput input);
}

File 57 of 58 : LibTokenLauncherConsts.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

library LibTokenLauncherConsts {
    bytes32 internal constant PRODUCT_ID = keccak256("tokenfi.tokenLauncher");

    // TOKEN LAUNCHER ROLES
    bytes32 internal constant FEE_MANAGER_ROLE = keccak256("FEE_MANAGER_ROLE");
    bytes32 public constant BUYBACK_CALLER_ROLE = keccak256("BUYBACK_CALLER_ROLE");

    uint256 public constant SLIPPAGE_TOLERANCE = 500;
    uint256 public constant REFLECTION_MAX = type(uint256).max / 2;
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import { ITokenLauncherCommon } from "../interfaces/ITokenLauncherCommon.sol";
// ITokenFiErc20
import { IERC20 } from "@solidstate/contracts/interfaces/IERC20.sol";
import { IERC20Extended } from "@solidstate/contracts/token/ERC20/extended/IERC20Extended.sol";
import { IERC20Metadata } from "@solidstate/contracts/token/ERC20/metadata/IERC20Metadata.sol";
import { IERC2612 } from "@solidstate/contracts/token/ERC20/permit/IERC2612.sol";
import { ITokenFiErc20 } from "../interfaces/ITokenFiErc20.sol";
// ITokenFiErc721
import { IERC721 } from "@solidstate/contracts/interfaces/IERC721.sol";
import { IERC721Enumerable } from "@solidstate/contracts/token/ERC721/enumerable/IERC721Enumerable.sol";
import { IERC721Metadata } from "@solidstate/contracts/token/ERC721/metadata/IERC721Metadata.sol";
import { ITokenFiErc721 } from "../interfaces/ITokenFiErc721.sol";
// ITokenFiErc1155
import { IERC165 } from "@solidstate/contracts/interfaces/IERC165.sol";
import { IERC1155 } from "@solidstate/contracts/interfaces/IERC1155.sol";
import { IERC1155Enumerable } from "@solidstate/contracts/token/ERC1155/enumerable/IERC1155Enumerable.sol";
import { IERC1155Metadata } from "@solidstate/contracts/token/ERC1155/metadata/IERC1155Metadata.sol";
import { ITokenFiErc1155 } from "../interfaces/ITokenFiErc1155.sol";

library LibTokenLauncherFactoryStorage {
    bytes32 internal constant DIAMOND_STORAGE_POSITION = keccak256("tokenfi.tokenlauncher.factory.diamond.storage");

    struct DiamondStorage {
        mapping(ITokenLauncherCommon.TokenType => address[]) tokensByType;
        mapping(ITokenLauncherCommon.TokenType => mapping(address => address[])) tokensByOwnerByType;
        mapping(address => address) tokenOwnerByToken;
        uint256 currentBlockTokenCreated;
        uint256 currentBlockTokenOwnerUpdated;
        address buybackHandler;
        address accessControlFacet;
        address pausableFacet;
        address loupeFacet;
        address proxyFacet;
        address tokenFiErc20Facet;
        address tokenFiErc20DiamondInit;
        address tokenFiErc721Facet;
        address tokenFiErc721DiamondInit;
        address tokenFiErc1155Facet;
        address tokenFiErc1155DiamondInit;
        address tokenFiErc20Implementation;
        address tokenFiErc721Implementation;
        address tokenFiErc1155Implementation;
    }

    function diamondStorage() internal pure returns (DiamondStorage storage ds) {
        bytes32 position = DIAMOND_STORAGE_POSITION;
        assembly {
            ds.slot := position
        }
    }

    function getTokenFiErc20FunctionSelectors() internal pure returns (bytes4[] memory) {
        bytes4[] memory selectors = new bytes4[](41);

        /** IERC20 selectors */
        selectors[0] = IERC20.totalSupply.selector;
        selectors[1] = IERC20.balanceOf.selector;
        selectors[2] = IERC20.allowance.selector;
        selectors[3] = IERC20.approve.selector;
        selectors[4] = IERC20.transfer.selector;
        selectors[5] = IERC20.transferFrom.selector;

        /** IERC20Extended selectors */

        selectors[6] = IERC20Extended.increaseAllowance.selector;
        selectors[7] = IERC20Extended.decreaseAllowance.selector;

        /** IERC20Metadata selectors */
        selectors[8] = IERC20Metadata.name.selector;
        selectors[9] = IERC20Metadata.symbol.selector;
        selectors[10] = IERC20Metadata.decimals.selector;

        /** IERC2612 selectors */
        selectors[11] = IERC2612.DOMAIN_SEPARATOR.selector;
        selectors[12] = IERC2612.nonces.selector;
        selectors[13] = IERC2612.permit.selector;

        /** ITokenFiErc20 selectors */
        selectors[14] = ITokenFiErc20.mint.selector;
        selectors[15] = ITokenFiErc20.updateTokenLauncher.selector;
        selectors[16] = ITokenFiErc20.updateTreasury.selector;
        selectors[17] = ITokenFiErc20.setName.selector;
        selectors[18] = ITokenFiErc20.setSymbol.selector;
        selectors[19] = ITokenFiErc20.setDecimals.selector;
        selectors[20] = ITokenFiErc20.updateFees.selector;
        selectors[21] = ITokenFiErc20.setBuybackDetails.selector;
        selectors[22] = ITokenFiErc20.setBuybackHandler.selector;
        selectors[23] = ITokenFiErc20.addExchangePool.selector;
        selectors[24] = ITokenFiErc20.removeExchangePool.selector;
        selectors[25] = ITokenFiErc20.addExemptAddress.selector;
        selectors[26] = ITokenFiErc20.removeExemptAddress.selector;
        /** VIEW */
        selectors[27] = ITokenFiErc20.fees.selector;
        selectors[28] = ITokenFiErc20.tokenInfo.selector;
        selectors[29] = ITokenFiErc20.buybackHandler.selector;
        selectors[30] = ITokenFiErc20.isExchangePool.selector;
        selectors[31] = ITokenFiErc20.isExemptedFromTax.selector;
        selectors[32] = ITokenFiErc20.isReflectionToken.selector;

        // Reflection function selectors
        selectors[33] = ITokenFiErc20.reflect.selector;
        selectors[34] = ITokenFiErc20.excludeAccount.selector;
        selectors[35] = ITokenFiErc20.includeAccount.selector;
        selectors[36] = ITokenFiErc20.isExcludedFromReflectionRewards.selector;
        selectors[37] = ITokenFiErc20.totalReflection.selector;
        selectors[38] = ITokenFiErc20.reflectionFromToken.selector;
        selectors[39] = ITokenFiErc20.tokenFromReflection.selector;
        selectors[40] = ITokenFiErc20.totalFees.selector;

        return selectors;
    }

    function getTokenFiErc721FunctionSelectors() internal pure returns (bytes4[] memory) {
        bytes4[] memory selectors = new bytes4[](24);

        // IERC165 selectors
        selectors[0] = IERC165.supportsInterface.selector;

        // IERC721 function selectors
        selectors[1] = IERC721.balanceOf.selector;
        selectors[2] = IERC721.ownerOf.selector;
        // selectors[8] = IERC721.safeTransferFrom.selector;
        selectors[3] = IERC721.transferFrom.selector;
        selectors[4] = IERC721.approve.selector;
        selectors[5] = IERC721.getApproved.selector;
        selectors[6] = IERC721.setApprovalForAll.selector;
        selectors[7] = IERC721.isApprovedForAll.selector;

        // IERC721Enumerable selectors
        selectors[8] = IERC721Enumerable.totalSupply.selector;
        selectors[9] = IERC721Enumerable.tokenOfOwnerByIndex.selector;
        selectors[10] = IERC721Enumerable.tokenByIndex.selector;

        // IERC721Metadata selectors
        selectors[11] = IERC721Metadata.name.selector;
        selectors[12] = IERC721Metadata.symbol.selector;
        selectors[13] = IERC721Metadata.tokenURI.selector;

        // ITokenFiErc721 function selectors
        selectors[14] = ITokenFiErc721.adminMint.selector;
        selectors[15] = ITokenFiErc721.adminMintBatch.selector;
        selectors[16] = ITokenFiErc721.setTokenInfo.selector;
        selectors[17] = ITokenFiErc721.setTokenUri.selector;
        selectors[18] = ITokenFiErc721.mint.selector;
        selectors[19] = ITokenFiErc721.mintWithPaymentSignature.selector;
        selectors[20] = ITokenFiErc721.mintBatch.selector;
        selectors[21] = ITokenFiErc721.mintBatchWithPaymentSignature.selector;
        selectors[22] = ITokenFiErc721.tokenInfo.selector;
        selectors[23] = ITokenFiErc721.paymentModule.selector;

        return selectors;
    }

    function getTokenFiErc1155FunctionSelectors() internal pure returns (bytes4[] memory) {
        bytes4[] memory selectors = new bytes4[](26);

        // IERC165 selectors
        selectors[0] = IERC165.supportsInterface.selector;

        // IERC1155 selectors
        selectors[1] = IERC1155.balanceOf.selector;
        selectors[2] = IERC1155.balanceOfBatch.selector;
        selectors[3] = IERC1155.isApprovedForAll.selector;
        selectors[4] = IERC1155.setApprovalForAll.selector;
        selectors[5] = IERC1155.safeTransferFrom.selector;
        selectors[6] = IERC1155.safeBatchTransferFrom.selector;

        // IERC1155Enumerable selectors
        selectors[7] = IERC1155Enumerable.totalSupply.selector;
        selectors[8] = IERC1155Enumerable.totalHolders.selector;
        selectors[9] = IERC1155Enumerable.accountsByToken.selector;
        selectors[10] = IERC1155Enumerable.tokensByAccount.selector;

        // IERC1155Metadata selectors
        selectors[11] = IERC1155Metadata.uri.selector;

        // ITokenFiErc1155 selectors
        selectors[12] = ITokenFiErc1155.adminMint.selector;
        selectors[13] = ITokenFiErc1155.setTokenInfo.selector;
        selectors[14] = ITokenFiErc1155.createToken.selector;
        selectors[15] = ITokenFiErc1155.setTokenPublicMintPrice.selector;
        selectors[16] = ITokenFiErc1155.setTokenUri.selector;
        selectors[17] = ITokenFiErc1155.mint.selector;
        selectors[18] = ITokenFiErc1155.mintWithPaymentSignature.selector;
        selectors[19] = ITokenFiErc1155.tokenInfo.selector;
        selectors[20] = ITokenFiErc1155.maxSupply.selector;
        selectors[21] = ITokenFiErc1155.decimals.selector;
        selectors[22] = ITokenFiErc1155.paymentServiceIndexByTokenId.selector;
        selectors[23] = ITokenFiErc1155.exists.selector;
        selectors[24] = ITokenFiErc1155.getExistingTokenIds.selector;
        selectors[25] = ITokenFiErc1155.paymentModule.selector;

        return selectors;
    }
}

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

Contract Security Audit

Contract ABI

API
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"currentBlockTokenCreated","type":"uint256"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"uint256","name":"paymentIndex","type":"uint256"},{"internalType":"enum ITokenLauncherCommon.TokenType","name":"tokenType","type":"uint8"}],"indexed":false,"internalType":"struct ITokenLauncherFactory.StoreTokenInput","name":"input","type":"tuple"}],"name":"TokenCreated","type":"event"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"collectionLogo","type":"string"},{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"bool","name":"isPublicMintEnabled","type":"bool"},{"internalType":"bool","name":"isAdminMintEnabled","type":"bool"},{"internalType":"address","name":"owner","type":"address"}],"internalType":"struct ITokenFiErc1155.TokenInfo","name":"tokenInfo","type":"tuple"},{"components":[{"internalType":"address","name":"treasury","type":"address"},{"internalType":"uint256","name":"burnBasisPoints","type":"uint256"},{"internalType":"uint256","name":"referrerBasisPoints","type":"uint256"}],"internalType":"struct ITokenLauncherFactory.PublicErc1155MintPaymentInfo","name":"publicMintPaymentInfo","type":"tuple"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"publicMintUsdPrice","type":"uint256"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"string","name":"uri","type":"string"}],"internalType":"struct ITokenFiErc1155.CreateTokenInput[]","name":"initialTokens","type":"tuple[]"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"address","name":"paymentToken","type":"address"}],"internalType":"struct ITokenLauncherFactory.CreateErc1155Input","name":"input","type":"tuple"}],"name":"createErc1155","outputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"collectionLogo","type":"string"},{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"bool","name":"isPublicMintEnabled","type":"bool"},{"internalType":"bool","name":"isAdminMintEnabled","type":"bool"},{"internalType":"address","name":"owner","type":"address"}],"internalType":"struct ITokenFiErc1155.TokenInfo","name":"tokenInfo","type":"tuple"},{"components":[{"internalType":"address","name":"treasury","type":"address"},{"internalType":"uint256","name":"burnBasisPoints","type":"uint256"},{"internalType":"uint256","name":"referrerBasisPoints","type":"uint256"}],"internalType":"struct ITokenLauncherFactory.PublicErc1155MintPaymentInfo","name":"publicMintPaymentInfo","type":"tuple"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"publicMintUsdPrice","type":"uint256"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"string","name":"uri","type":"string"}],"internalType":"struct ITokenFiErc1155.CreateTokenInput[]","name":"initialTokens","type":"tuple[]"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"address","name":"paymentToken","type":"address"}],"internalType":"struct ITokenLauncherFactory.CreateErc1155Input","name":"input","type":"tuple"},{"components":[{"internalType":"address","name":"payer","type":"address"},{"internalType":"uint256","name":"sourceChainId","type":"uint256"},{"internalType":"uint256","name":"paymentIndex","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct ICrossPaymentModule.CrossPaymentSignatureInput","name":"crossPaymentSignatureInput","type":"tuple"}],"name":"createErc1155WithPaymentSignature","outputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"logo","type":"string"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"initialSupply","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"address","name":"treasury","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"components":[{"components":[{"internalType":"uint256","name":"percentage","type":"uint256"},{"internalType":"bool","name":"onlyOnSwaps","type":"bool"}],"internalType":"struct ITokenFiErc20.FeeDetails","name":"transferFee","type":"tuple"},{"components":[{"internalType":"uint256","name":"percentage","type":"uint256"},{"internalType":"bool","name":"onlyOnSwaps","type":"bool"}],"internalType":"struct ITokenFiErc20.FeeDetails","name":"burn","type":"tuple"},{"components":[{"internalType":"uint256","name":"percentage","type":"uint256"},{"internalType":"bool","name":"onlyOnSwaps","type":"bool"}],"internalType":"struct ITokenFiErc20.FeeDetails","name":"reflection","type":"tuple"},{"components":[{"internalType":"uint256","name":"percentage","type":"uint256"},{"internalType":"bool","name":"onlyOnSwaps","type":"bool"}],"internalType":"struct ITokenFiErc20.FeeDetails","name":"buyback","type":"tuple"}],"internalType":"struct ITokenFiErc20.Fees","name":"fees","type":"tuple"},{"components":[{"internalType":"address","name":"pairToken","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"uint256","name":"liquidityBasisPoints","type":"uint256"},{"internalType":"uint256","name":"priceImpactBasisPoints","type":"uint256"}],"internalType":"struct ITokenFiErc20.BuybackDetails","name":"buybackDetails","type":"tuple"}],"internalType":"struct ITokenFiErc20.TokenInfo","name":"tokenInfo","type":"tuple"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"address","name":"paymentToken","type":"address"}],"internalType":"struct ITokenLauncherFactory.CreateErc20Input","name":"input","type":"tuple"}],"name":"createErc20","outputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"logo","type":"string"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"initialSupply","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"address","name":"treasury","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"components":[{"components":[{"internalType":"uint256","name":"percentage","type":"uint256"},{"internalType":"bool","name":"onlyOnSwaps","type":"bool"}],"internalType":"struct ITokenFiErc20.FeeDetails","name":"transferFee","type":"tuple"},{"components":[{"internalType":"uint256","name":"percentage","type":"uint256"},{"internalType":"bool","name":"onlyOnSwaps","type":"bool"}],"internalType":"struct ITokenFiErc20.FeeDetails","name":"burn","type":"tuple"},{"components":[{"internalType":"uint256","name":"percentage","type":"uint256"},{"internalType":"bool","name":"onlyOnSwaps","type":"bool"}],"internalType":"struct ITokenFiErc20.FeeDetails","name":"reflection","type":"tuple"},{"components":[{"internalType":"uint256","name":"percentage","type":"uint256"},{"internalType":"bool","name":"onlyOnSwaps","type":"bool"}],"internalType":"struct ITokenFiErc20.FeeDetails","name":"buyback","type":"tuple"}],"internalType":"struct ITokenFiErc20.Fees","name":"fees","type":"tuple"},{"components":[{"internalType":"address","name":"pairToken","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"uint256","name":"liquidityBasisPoints","type":"uint256"},{"internalType":"uint256","name":"priceImpactBasisPoints","type":"uint256"}],"internalType":"struct ITokenFiErc20.BuybackDetails","name":"buybackDetails","type":"tuple"}],"internalType":"struct ITokenFiErc20.TokenInfo","name":"tokenInfo","type":"tuple"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"address","name":"paymentToken","type":"address"}],"internalType":"struct ITokenLauncherFactory.CreateErc20Input","name":"input","type":"tuple"},{"components":[{"internalType":"address","name":"payer","type":"address"},{"internalType":"uint256","name":"sourceChainId","type":"uint256"},{"internalType":"uint256","name":"paymentIndex","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct ICrossPaymentModule.CrossPaymentSignatureInput","name":"crossPaymentSignatureInput","type":"tuple"}],"name":"createErc20WithPaymentSignature","outputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"collectionLogo","type":"string"},{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"bool","name":"isPublicMintEnabled","type":"bool"},{"internalType":"bool","name":"isAdminMintEnabled","type":"bool"},{"internalType":"address","name":"owner","type":"address"}],"internalType":"struct ITokenFiErc721.TokenInfo","name":"tokenInfo","type":"tuple"},{"components":[{"internalType":"uint256","name":"usdPrice","type":"uint256"},{"internalType":"address","name":"treasury","type":"address"},{"internalType":"uint256","name":"burnBasisPoints","type":"uint256"},{"internalType":"uint256","name":"referrerBasisPoints","type":"uint256"}],"internalType":"struct ITokenLauncherFactory.PublicErc721MintPaymentInfo","name":"publicMintPaymentInfo","type":"tuple"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"address","name":"paymentToken","type":"address"}],"internalType":"struct ITokenLauncherFactory.CreateErc721Input","name":"input","type":"tuple"}],"name":"createErc721","outputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"collectionLogo","type":"string"},{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"bool","name":"isPublicMintEnabled","type":"bool"},{"internalType":"bool","name":"isAdminMintEnabled","type":"bool"},{"internalType":"address","name":"owner","type":"address"}],"internalType":"struct ITokenFiErc721.TokenInfo","name":"tokenInfo","type":"tuple"},{"components":[{"internalType":"uint256","name":"usdPrice","type":"uint256"},{"internalType":"address","name":"treasury","type":"address"},{"internalType":"uint256","name":"burnBasisPoints","type":"uint256"},{"internalType":"uint256","name":"referrerBasisPoints","type":"uint256"}],"internalType":"struct ITokenLauncherFactory.PublicErc721MintPaymentInfo","name":"publicMintPaymentInfo","type":"tuple"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"address","name":"paymentToken","type":"address"}],"internalType":"struct ITokenLauncherFactory.CreateErc721Input","name":"input","type":"tuple"},{"components":[{"internalType":"address","name":"payer","type":"address"},{"internalType":"uint256","name":"sourceChainId","type":"uint256"},{"internalType":"uint256","name":"paymentIndex","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct ICrossPaymentModule.CrossPaymentSignatureInput","name":"crossPaymentSignatureInput","type":"tuple"}],"name":"createErc721WithPaymentSignature","outputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b506159f2806100206000396000f3fe6080604052600436106200005c5760003560e01c80636791a805146200006157806394ed410e14620000905780639f65bd5314620000b5578063b205911314620000da578063cb4a55d914620000f1578063ded782941462000116575b600080fd5b620000786200007236600462003657565b6200012d565b604051620000879190620036a4565b60405180910390f35b3480156200009d57600080fd5b5062000078620000af366004620038e0565b6200015b565b348015620000c257600080fd5b5062000078620000d43660046200394a565b6200017a565b62000078620000eb36600462003c88565b62000199565b348015620000fe57600080fd5b50620000786200011036600462003cc0565b620001c0565b620000786200012736600462003cfa565b620001df565b6000806200014660008460200151856040015162000206565b905062000154838262000377565b9392505050565b60006200016a60018362000804565b62000154838360400151620009fd565b60006200018960008362000804565b6200015483836040015162000377565b600080620001b260028460600151856080015162000206565b905062000154838262000e0b565b6000620001cf60028362000804565b6200015483836040015162000e0b565b600080620001f860018460400151856060015162000206565b9050620001548382620009fd565b6040805160018082528183019092526000918291906020808301908036833701905050905084600281111562000240576200024062003d32565b8160008151811062000256576200025662003d48565b63ffffffff9290921660209283029190910190910152604080516001808252818301909252600091816020016020820280368337019050509050600181600081518110620002a857620002a862003d48565b63ffffffff9092166020928302919091018201526040805160c081018252600080516020620059a683398151915281529182018490528181018390526001600160a01b038088166060840152336080840152861660a083015251635d048b2560e11b8152309063ba09164a9034906200032690859060040162003da2565b60206040518083038185885af115801562000345573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906200036c919062003e24565b979650505050505050565b6000806200038462001187565b905062000390620011ab565b9150620003a28285600001516200127b565b6010810154604051636bc26a1360e11b81526001600160a01b038481169263d784d42692620003d89290911690600401620036a4565b600060405180830381600087803b158015620003f357600080fd5b505af115801562000408573d6000803e3d6000fd5b505085515160405163c47f002760e01b81528593506001600160a01b038416925063c47f0027916200043d9160040162003e92565b600060405180830381600087803b1580156200045857600080fd5b505af11580156200046d573d6000803e3d6000fd5b5050865160200151604051635c26412360e11b81526001600160a01b038516935063b84c82469250620004a4919060040162003e92565b600060405180830381600087803b158015620004bf57600080fd5b505af1158015620004d4573d6000803e3d6000fd5b5050865160600151604051633d09cad560e11b815260ff90911660048201526001600160a01b0384169250637a1395aa9150602401600060405180830381600087803b1580156200052457600080fd5b505af115801562000539573d6000803e3d6000fd5b5050865160800151159150620005cc905057845160c08101516080909101516040516340c10f1960e01b81526001600160a01b038416926340c10f199262000597926004016001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015620005b257600080fd5b505af1158015620005c7573d6000803e3d6000fd5b505050505b604051636078c0f960e01b81526001600160a01b03821690636078c0f990620005fa903090600401620036a4565b600060405180830381600087803b1580156200061557600080fd5b505af11580156200062a573d6000803e3d6000fd5b5050506005830154604051636078c0f960e01b81526001600160a01b038085169350636078c0f9926200066392911690600401620036a4565b600060405180830381600087803b1580156200067e57600080fd5b505af115801562000693573d6000803e3d6000fd5b505050600583015460405163019cc55360e51b81526001600160a01b038085169350633398aa6092620006cc92911690600401620036a4565b600060405180830381600087803b158015620006e757600080fd5b505af1158015620006fc573d6000803e3d6000fd5b5050506005830154604051632f2ff15d60e01b81526001600160a01b039091169150632f2ff15d9062000756907f0e512f22a4a66880dbe62f43c3840e18a3b81e1a4c1c40bba7dc19b0503e51a990879060040162003ea7565b600060405180830381600087803b1580156200077157600080fd5b505af115801562000786573d6000803e3d6000fd5b5050505060006040518060a00160405280856001600160a01b03168152602001876000015160e001516001600160a01b0316815260200187602001516001600160a01b0316815260200186815260200160006002811115620007ec57620007ec62003d32565b90529050620007fb81620013a7565b50505092915050565b604080516001808252818301909252600091602080830190803683370190505090508260028111156200083b576200083b62003d32565b8160008151811062000851576200085162003d48565b63ffffffff9290921660209283029190910190910152604080516001808252818301909252600091816020016020820280368337019050509050600181600081518110620008a357620008a362003d48565b602002602001019063ffffffff16908163ffffffff16815250506000604051806101000160405280600080516020620059a68339815191528152602001848152602001838152602001336001600160a01b03168152602001306001600160a01b031663564b81ef6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200093a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000960919062003e24565b815260200185600001516001600160a01b031681526020018560200151815260200185604001518152509050306001600160a01b031663b459f7ca338387606001516040518463ffffffff1660e01b8152600401620009c29392919062003ebe565b600060405180830381600087803b158015620009dd57600080fd5b505af1158015620009f2573d6000803e3d6000fd5b505050505050505050565b600062000a09620011ab565b905062000a1b81846000015162001518565b600062000a2762001187565b6011810154604051636bc26a1360e11b81529192506001600160a01b038085169263d784d4269262000a5e921690600401620036a4565b600060405180830381600087803b15801562000a7957600080fd5b505af115801562000a8e573d6000803e3d6000fd5b50600092506001915062000a9f9050565b60405190808252806020026020018201604052801562000ae757816020015b60408051808201909152606081526000602082015281526020019060019003908162000abe5790505b5060408051608081018252600b9181019182526a115490cdcc8c48135a5b9d60aa1b60608201529081526020878101515190820152815191925090829060009062000b365762000b3662003d48565b6020026020010181905250600060405180610120016040528087600001516000015181526020018560405160200162000b70919062003f70565b60408051601f1981840301815291815281516020928301208352895160e001516001600160a01b03908116848401528a83018051909301511683820152905160609081015190830152516323cb241360e11b8152600080516020620059a683398151915260048201526080909101903090634796482690602401600060405180830381865afa15801562000c08573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000c329190810190620040ba565b60a001516001600160a01b031681526020018760200151604001518152602001600015158152602001838152509050306001600160a01b031663f5616c1f826040518263ffffffff1660e01b815260040162000c8f919062004236565b600060405180830381600087803b15801562000caa57600080fd5b505af115801562000cbf573d6000803e3d6000fd5b50508751604051636fe49ad960e01b81526001600160a01b0388169350636fe49ad9925062000cf29190600401620042f2565b600060405180830381600087803b15801562000d0d57600080fd5b505af115801562000d22573d6000803e3d6000fd5b5050604051632f2ff15d60e01b8152309250632f2ff15d915062000d5c90600080516020620059c683398151915290889060040162003ea7565b600060405180830381600087803b15801562000d7757600080fd5b505af115801562000d8c573d6000803e3d6000fd5b5050505060006040518060a00160405280866001600160a01b03168152602001886000015160e001516001600160a01b0316815260200188604001516001600160a01b031681526020018781526020016001600281111562000df25762000df262003d32565b9052905062000e0181620013a7565b5050505092915050565b600062000e17620011ab565b905062000e2981846000015162001608565b600062000e3562001187565b6012810154604051636bc26a1360e11b81529192506001600160a01b038085169263d784d4269262000e6c921690600401620036a4565b600060405180830381600087803b15801562000e8757600080fd5b505af115801562000e9c573d6000803e3d6000fd5b505050506060600060405180610120016040528087600001516000015181526020018560405160200162000ed1919062003f70565b60408051808303601f19018152918152815160209283012083526001600160a01b0388811684840152918a018051519092168382015290518101516060830152516323cb241360e11b8152600080516020620059a683398151915260048201526080909101903090634796482690602401600060405180830381865afa15801562000f60573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000f8a9190810190620040ba565b60a001516001600160a01b031681526020018760200151602001518152602001600015158152602001838152509050306001600160a01b031663f5616c1f826040518263ffffffff1660e01b815260040162000fe7919062004236565b600060405180830381600087803b1580156200100257600080fd5b505af115801562001017573d6000803e3d6000fd5b5050604051632f2ff15d60e01b8152309250632f2ff15d91506200105190600080516020620059c683398151915290889060040162003ea7565b600060405180830381600087803b1580156200106c57600080fd5b505af115801562001081573d6000803e3d6000fd5b5050505060005b8660400151518110156200112557846001600160a01b03166307e10c0d88604001518381518110620010be57620010be62003d48565b60200260200101516040518263ffffffff1660e01b8152600401620010e49190620043bf565b600060405180830381600087803b158015620010ff57600080fd5b505af115801562001114573d6000803e3d6000fd5b505060019092019150620010889050565b5060006040518060a00160405280866001600160a01b03168152602001886000015160c001516001600160a01b0316815260200188606001516001600160a01b0316815260200187815260200160028081111562000df25762000df262003d32565b7fae91e73249036d298733b3485b49b39bcb9229df52016e2810a03f18355028f690565b6307e4c70760e21b60009081527fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c60208181526040805180820182527f9f0ce991cd9c4f6eaf19f214129f7a5c88ce0f46a01a0f164d4f0d44366a92a8546001600160a01b038116808352600160a01b9091046001600160601b0316938201939093529051909130916200123f9062003168565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562001273573d6000803e3d6000fd5b509250505090565b60006200128762001187565b9050600062001295620016f8565b90506000620012a3620018b7565b6040805160608101909152600a8501546001600160a01b0316815290915060208101600081526020018281525082600081518110620012e657620012e662003d48565b602002602001018190525060008460405160240162001306919062004468565b60408051601f198184030181529181526020820180516001600160e01b0316634e06b2e160e11b179052600b86015490516307e4c70760e21b81529192506001600160a01b0380891692631f931c1c926200136b928892911690869060040162004598565b600060405180830381600087803b1580156200138657600080fd5b505af11580156200139b573d6000803e3d6000fd5b50505050505050505050565b6000620013b362001187565b905080600101600083608001516002811115620013d457620013d462003d32565b6002811115620013e857620013e862003d32565b81526020808201929092526040908101600090812085840180516001600160a01b0390811684529185528383208751815460018101835591855286852090910180549184166001600160a01b0319928316179055905187518316845260028088019096529383208054949092169316929092179091556080840151839281111562001477576200147762003d32565b60028111156200148b576200148b62003d32565b81526020808201929092526040908101600090812085518154600181018355918352939091200180546001600160a01b0319166001600160a01b0390931692909217909155600382015490517f5bb644ee2a83060962b095d7d1eb91687997dbc60b60ea2a63eba7cd42c16fb6906200150690859062004690565b60405180910390a24360039091015550565b60006200152462001187565b9050600062001532620016f8565b905060006200154062002227565b6040805160608101909152600c8501546001600160a01b031681529091506020810160008152602001828152508260008151811062001583576200158362003d48565b6020026020010181905250600084604051602401620015a39190620042f2565b60408051601f198184030181529181526020820180516001600160e01b03166345d4de7b60e01b179052600d86015490516307e4c70760e21b81529192506001600160a01b0380891692631f931c1c926200136b928892911690869060040162004598565b60006200161462001187565b9050600062001622620016f8565b9050600062001630620027a4565b6040805160608101909152600e8501546001600160a01b031681529091506020810160008152602001828152508260008151811062001673576200167362003d48565b6020026020010181905250600084604051602401620016939190620046e4565b60408051601f198184030181529181526020820180516001600160e01b031663c952bb1960e01b179052600f86015490516307e4c70760e21b81529192506001600160a01b0380891692631f931c1c926200136b928892911690869060040162004598565b606060006200170662001187565b60408051600580825260c08201909252919250816020015b604080516060808201835260008083526020830152918101919091528152602001906001900390816200171e57905050915060006200175c62002d93565b604080516060810190915260068401546001600160a01b03168152909150602081016000815260200182815250836001815181106200179f576200179f62003d48565b6020026020010181905250620017b462002f4d565b604080516060810190915260078401546001600160a01b0316815290915060208101600081526020018281525083600281518110620017f757620017f762003d48565b60200260200101819052506200180c62003001565b604080516060810190915260088401546001600160a01b03168152909150602081016000815260200182815250836003815181106200184f576200184f62003d48565b602002602001018190525062001864620030f0565b604080516060810190915260098401546001600160a01b0316815290915060208101600081526020018281525083600481518110620018a757620018a762003d48565b6020026020010181905250505090565b60408051602980825261054082019092526060916000919060208201610520803683370190505090506318160ddd60e01b81600081518110620018fe57620018fe62003d48565b6001600160e01b03199092166020928302919091019091015280516370a0823160e01b908290600190811062001938576200193862003d48565b6001600160e01b0319909216602092830291909101909101528051636eb1769f60e11b908290600290811062001972576200197262003d48565b6001600160e01b031990921660209283029190910190910152805163095ea7b360e01b9082906003908110620019ac57620019ac62003d48565b6001600160e01b031990921660209283029190910190910152805163a9059cbb60e01b9082906004908110620019e657620019e662003d48565b6001600160e01b03199092166020928302919091019091015280516323b872dd60e01b908290600590811062001a205762001a2062003d48565b6001600160e01b0319909216602092830291909101909101528051633950935160e01b908290600690811062001a5a5762001a5a62003d48565b6001600160e01b031990921660209283029190910190910152805163a457c2d760e01b908290600790811062001a945762001a9462003d48565b6001600160e01b03199092166020928302919091019091015280516306fdde0360e01b908290600890811062001ace5762001ace62003d48565b6001600160e01b03199092166020928302919091019091015280516395d89b4160e01b908290600990811062001b085762001b0862003d48565b6001600160e01b031990921660209283029190910190910152805163313ce56760e01b908290600a90811062001b425762001b4262003d48565b6001600160e01b0319909216602092830291909101909101528051633644e51560e01b908290600b90811062001b7c5762001b7c62003d48565b6001600160e01b0319909216602092830291909101909101528051623f675f60e91b908290600c90811062001bb55762001bb562003d48565b6001600160e01b031990921660209283029190910190910152805163d505accf60e01b908290600d90811062001bef5762001bef62003d48565b6001600160e01b03199092166020928302919091019091015280516340c10f1960e01b908290600e90811062001c295762001c2962003d48565b6001600160e01b0319909216602092830291909101909101528051631780542160e31b908290600f90811062001c635762001c6362003d48565b6001600160e01b0319909216602092830291909101909101528051637f51bb1f60e01b908290601090811062001c9d5762001c9d62003d48565b6001600160e01b031990921660209283029190910190910152805163c47f002760e01b908290601190811062001cd75762001cd762003d48565b6001600160e01b0319909216602092830291909101909101528051635c26412360e11b908290601290811062001d115762001d1162003d48565b6001600160e01b0319909216602092830291909101909101528051633d09cad560e11b908290601390811062001d4b5762001d4b62003d48565b6001600160e01b0319909216602092830291909101909101528051633cae3f5f60e11b908290601490811062001d855762001d8562003d48565b6001600160e01b0319909216602092830291909101909101528051633aa1d1d560e11b908290601590811062001dbf5762001dbf62003d48565b6001600160e01b031990921660209283029190910190910152805163019cc55360e51b908290601690811062001df95762001df962003d48565b6001600160e01b03199092166020928302919091019091015280516316c0896d60e31b908290601790811062001e335762001e3362003d48565b6001600160e01b031990921660209283029190910190910152805163612881a360e11b908290601890811062001e6d5762001e6d62003d48565b6001600160e01b0319909216602092830291909101909101528051636078c0f960e01b908290601990811062001ea75762001ea762003d48565b6001600160e01b0319909216602092830291909101909101528051631ec70d6760e21b908290601a90811062001ee15762001ee162003d48565b6001600160e01b0319909216602092830291909101909101528051634d78e9ad60e11b908290601b90811062001f1b5762001f1b62003d48565b6001600160e01b0319909216602092830291909101909101528051636addb66360e01b908290601c90811062001f555762001f5562003d48565b6001600160e01b03199092166020928302919091019091015280516311c565df60e01b908290601d90811062001f8f5762001f8f62003d48565b6001600160e01b03199092166020928302919091019091015280516318f60b6960e01b908290601e90811062001fc95762001fc962003d48565b6001600160e01b03199092166020928302919091019091015280516311557f7960e11b908290601f90811062002003576200200362003d48565b6001600160e01b0319909216602092830291909101820152815163997d0feb60e01b918391811062002039576200203962003d48565b6001600160e01b031990921660209283029190910190910152805163029d58c160e11b908290602190811062002073576200207362003d48565b6001600160e01b0319909216602092830291909101909101528051631e59818360e31b9082906022908110620020ad57620020ad62003d48565b6001600160e01b031990921660209283029190910190910152805163f84354f160e01b9082906023908110620020e757620020e762003d48565b6001600160e01b031990921660209283029190910190910152805163045a6e8360e51b908290602490811062002121576200212162003d48565b6001600160e01b031990921660209283029190910190910152805163011424b960e51b90829060259081106200215b576200215b62003d48565b6001600160e01b0319909216602092830291909101909101528051634549b03960e01b908290602690811062002195576200219562003d48565b6001600160e01b0319909216602092830291909101909101528051632d83811960e01b9082906027908110620021cf57620021cf62003d48565b6001600160e01b03199092166020928302919091019091015280516313114a9d60e01b908290602890811062002209576200220962003d48565b6001600160e01b031990921660209283029190910190910152919050565b60408051601880825261032082019092526060916000919060208201610300803683370190505090506301ffc9a760e01b816000815181106200226e576200226e62003d48565b6001600160e01b03199092166020928302919091019091015280516370a0823160e01b9082906001908110620022a857620022a862003d48565b6001600160e01b03199092166020928302919091019091015280516331a9108f60e11b9082906002908110620022e257620022e262003d48565b6001600160e01b03199092166020928302919091019091015280516323b872dd60e01b90829060039081106200231c576200231c62003d48565b6001600160e01b031990921660209283029190910190910152805163095ea7b360e01b908290600490811062002356576200235662003d48565b6001600160e01b031990921660209283029190910190910152805163020604bf60e21b908290600590811062002390576200239062003d48565b6001600160e01b031990921660209283029190910190910152805163a22cb46560e01b9082906006908110620023ca57620023ca62003d48565b6001600160e01b031990921660209283029190910190910152805163e985e9c560e01b908290600790811062002404576200240462003d48565b6001600160e01b03199092166020928302919091019091015280516318160ddd60e01b90829060089081106200243e576200243e62003d48565b6001600160e01b0319909216602092830291909101909101528051632f745c5960e01b908290600990811062002478576200247862003d48565b6001600160e01b0319909216602092830291909101909101528051634f6ccce760e01b908290600a908110620024b257620024b262003d48565b6001600160e01b03199092166020928302919091019091015280516306fdde0360e01b908290600b908110620024ec57620024ec62003d48565b6001600160e01b03199092166020928302919091019091015280516395d89b4160e01b908290600c90811062002526576200252662003d48565b6001600160e01b031990921660209283029190910190910152805163c87b56dd60e01b908290600d90811062002560576200256062003d48565b6001600160e01b0319909216602092830291909101909101528051634bb4ee0760e11b908290600e9081106200259a576200259a62003d48565b6001600160e01b0319909216602092830291909101909101528051637600c26f60e11b908290600f908110620025d457620025d462003d48565b6001600160e01b0319909216602092830291909101909101528051636fe49ad960e01b90829060109081106200260e576200260e62003d48565b6001600160e01b0319909216602092830291909101909101528051632bfbbc4f60e11b908290601190811062002648576200264862003d48565b6001600160e01b031990921660209283029190910190910152805163318c2e2160e11b908290601290811062002682576200268262003d48565b6001600160e01b031990921660209283029190910190910152805163b7b1140160e01b9082906013908110620026bc57620026bc62003d48565b6001600160e01b031990921660209283029190910190910152805163a09b654560e01b9082906014908110620026f657620026f662003d48565b6001600160e01b03199092166020928302919091019091015280516337ef227760e11b908290601590811062002730576200273062003d48565b6001600160e01b0319909216602092830291909101909101528051636addb66360e01b90829060169081106200276a576200276a62003d48565b6001600160e01b0319909216602092830291909101909101528051631850e64b60e11b908290601790811062002209576200220962003d48565b60408051601a80825261036082019092526060916000919060208201610340803683370190505090506301ffc9a760e01b81600081518110620027eb57620027eb62003d48565b6001600160e01b0319909216602092830291909101909101528051627eeac760e11b908290600190811062002824576200282462003d48565b6001600160e01b03199092166020928302919091019091015280516313849cfd60e21b90829060029081106200285e576200285e62003d48565b6001600160e01b031990921660209283029190910190910152805163e985e9c560e01b908290600390811062002898576200289862003d48565b6001600160e01b031990921660209283029190910190910152805163a22cb46560e01b9082906004908110620028d257620028d262003d48565b6001600160e01b0319909216602092830291909101909101528051637921219560e11b90829060059081106200290c576200290c62003d48565b6001600160e01b0319909216602092830291909101909101528051631759616b60e11b908290600690811062002946576200294662003d48565b6001600160e01b031990921660209283029190910190910152805163bd85b03960e01b908290600790811062002980576200298062003d48565b6001600160e01b03199092166020928302919091019091015280516313ba55df60e01b9082906008908110620029ba57620029ba62003d48565b6001600160e01b0319909216602092830291909101909101528051636dcfd84160e01b9082906009908110620029f457620029f462003d48565b6001600160e01b03199092166020928302919091019091015280516385bff2e760e01b908290600a90811062002a2e5762002a2e62003d48565b6001600160e01b03199092166020928302919091019091015280516303a24d0760e21b908290600b90811062002a685762002a6862003d48565b6001600160e01b0319909216602092830291909101909101528051624a84cb60e01b908290600c90811062002aa15762002aa162003d48565b6001600160e01b0319909216602092830291909101909101528051636d487de160e01b908290600d90811062002adb5762002adb62003d48565b6001600160e01b03199092166020928302919091019091015280516307e10c0d60e01b908290600e90811062002b155762002b1562003d48565b6001600160e01b031990921660209283029190910190910152805163eeecf93f60e01b908290600f90811062002b4f5762002b4f62003d48565b6001600160e01b0319909216602092830291909101909101528051632bfbbc4f60e11b908290601090811062002b895762002b8962003d48565b6001600160e01b0319909216602092830291909101909101528051630582268f60e51b908290601190811062002bc35762002bc362003d48565b6001600160e01b031990921660209283029190910190910152805163ddc97a4160e01b908290601290811062002bfd5762002bfd62003d48565b6001600160e01b0319909216602092830291909101909101528051636addb66360e01b908290601390811062002c375762002c3762003d48565b6001600160e01b03199092166020928302919091019091015280516321a7dd6560e21b908290601490811062002c715762002c7162003d48565b6001600160e01b0319909216602092830291909101909101528051631fa3f33160e11b908290601590811062002cab5762002cab62003d48565b6001600160e01b031990921660209283029190910190910152805163fd94616360e01b908290601690811062002ce55762002ce562003d48565b6001600160e01b0319909216602092830291909101909101528051634f558e7960e01b908290601790811062002d1f5762002d1f62003d48565b6001600160e01b0319909216602092830291909101909101528051631969630160e21b908290601890811062002d595762002d5962003d48565b6001600160e01b0319909216602092830291909101909101528051631850e64b60e11b908290601990811062002209576200220962003d48565b60408051600780825261010082019092526060916020820160e0803683370190505090506391d1485460e01b8160008151811062002dd55762002dd562003d48565b6001600160e01b031990921660209283029190910190910152805163248a9ca360e01b908290600190811062002e0f5762002e0f62003d48565b6001600160e01b0319909216602092830291909101909101528051632f2ff15d60e01b908290600290811062002e495762002e4962003d48565b6001600160e01b031990921660209283029190910190910152805163d547741f60e01b908290600390811062002e835762002e8362003d48565b6001600160e01b0319909216602092830291909101909101528051638bb9c5bf60e01b908290600490811062002ebd5762002ebd62003d48565b6001600160e01b0319909216602092830291909101909101528051632404341f60e21b908290600590811062002ef75762002ef762003d48565b6001600160e01b031990921660209283029190910190910152805163ca15c87360e01b908290600690811062002f315762002f3162003d48565b6001600160e01b03199092166020928302919091019091015290565b60408051600380825260808201909252606091602082018380368337019050509050635c975abb60e01b8160008151811062002f8d5762002f8d62003d48565b6001600160e01b0319909216602092830291909101909101528051638456cb5960e01b908290600190811062002fc75762002fc762003d48565b6001600160e01b0319909216602092830291909101909101528051631fa5d41d60e11b908290600290811062002f315762002f3162003d48565b60408051600480825260a082019092526060916020820160808036833701905050905063adfca15e60e01b8160008151811062003042576200304262003d48565b6001600160e01b03199092166020928302919091019091015280516366ffd66360e11b90829060019081106200307c576200307c62003d48565b6001600160e01b03199092166020928302919091019091015280516314bbdacb60e21b9082906002908110620030b657620030b662003d48565b6001600160e01b0319909216602092830291909101909101528051637a0ed62760e01b908290600390811062002f315762002f3162003d48565b6040805160028082526060808301845292602083019080368337019050509050635c60da1b60e01b816000815181106200312e576200312e62003d48565b6001600160e01b0319909216602092830291909101909101528051636bc26a1360e11b908290600190811062002f315762002f3162003d48565b61120b806200479b83390190565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715620031b157620031b162003176565b60405290565b604051608081016001600160401b0381118282101715620031b157620031b162003176565b604051606081016001600160401b0381118282101715620031b157620031b162003176565b60405161014081016001600160401b0381118282101715620031b157620031b162003176565b60405161010081016001600160401b0381118282101715620031b157620031b162003176565b60405160a081016001600160401b0381118282101715620031b157620031b162003176565b60405160e081016001600160401b0381118282101715620031b157620031b162003176565b60405161012081016001600160401b0381118282101715620031b157620031b162003176565b604051601f8201601f191681016001600160401b0381118282101715620032e857620032e862003176565b604052919050565b60006001600160401b038211156200330c576200330c62003176565b50601f01601f191660200190565b6000620033316200332b84620032f0565b620032bd565b90508281528383830111156200334657600080fd5b828260208301376000602084830101529392505050565b600082601f8301126200336f57600080fd5b62000154838335602085016200331a565b803560ff811681146200339257600080fd5b919050565b6001600160a01b0381168114620033ad57600080fd5b50565b8035620033928162003397565b8015158114620033ad57600080fd5b80356200339281620033bd565b600060408284031215620033ec57600080fd5b620033f66200318c565b90508135815260208201356200340c81620033bd565b602082015292915050565b600061010082840312156200342b57600080fd5b62003435620031b7565b9050620034438383620033d9565b8152620034548360408401620033d9565b6020820152620034688360808401620033d9565b60408201526200347c8360c08401620033d9565b606082015292915050565b6000608082840312156200349a57600080fd5b620034a4620031b7565b90508135620034b38162003397565b81526020820135620034c58162003397565b80602083015250604082013560408201526060820135606082015292915050565b600060608284031215620034f957600080fd5b62003503620031dc565b905081356001600160401b03808211156200351d57600080fd5b9083019061028082860312156200353357600080fd5b6200353d62003201565b8235828111156200354d57600080fd5b6200355b878286016200335d565b8252506020830135828111156200357157600080fd5b6200357f878286016200335d565b6020830152506040830135828111156200359857600080fd5b620035a6878286016200335d565b604083015250620035ba6060840162003380565b60608201526080830135608082015260a083013560a0820152620035e160c08401620033b0565b60c0820152620035f460e08401620033b0565b60e082015261010091506200360c8683850162003417565b828201526200362086610200850162003487565b61012082015283525062003639905060208301620033b0565b60208201526200364c60408301620033b0565b604082015292915050565b6000602082840312156200366a57600080fd5b81356001600160401b038111156200368157600080fd5b6200368f84828501620034e6565b949350505050565b6001600160a01b03169052565b6001600160a01b0391909116815260200190565b600060808284031215620036cb57600080fd5b620036d5620031b7565b9050813581526020820135620034c58162003397565b600060e08284031215620036fe57600080fd5b62003708620031b7565b905081356001600160401b03808211156200372257600080fd5b9083019061010082860312156200373857600080fd5b6200374262003227565b8235828111156200375257600080fd5b62003760878286016200335d565b8252506020830135828111156200377657600080fd5b62003784878286016200335d565b6020830152506040830135828111156200379d57600080fd5b620037ab878286016200335d565b604083015250606083013582811115620037c457600080fd5b620037d2878286016200335d565b60608301525060808301356080820152620037f060a08401620033cc565b60a08201526200380360c08401620033cc565b60c08201526200381660e08401620033b0565b60e08201528352506200382f90508360208401620036b8565b60208201526200384260a08301620033b0565b60408201526200347c60c08301620033b0565b6000608082840312156200386857600080fd5b62003872620031b7565b90508135620038818162003397565b8152602082810135908201526040808301359082015260608201356001600160401b03811115620038b157600080fd5b8201601f81018413620038c357600080fd5b620038d4848235602084016200331a565b60608301525092915050565b60008060408385031215620038f457600080fd5b82356001600160401b03808211156200390c57600080fd5b6200391a86838701620036eb565b935060208501359150808211156200393157600080fd5b50620039408582860162003855565b9150509250929050565b600080604083850312156200395e57600080fd5b82356001600160401b03808211156200397657600080fd5b6200391a86838701620034e6565b6000606082840312156200399757600080fd5b620039a1620031dc565b90508135620039b08162003397565b80825250602082013560208201526040820135604082015292915050565b60006001600160401b03821115620039ea57620039ea62003176565b5060051b60200190565b600082601f83011262003a0657600080fd5b8135602062003a196200332b83620039ce565b82815260059290921b8401810191818101908684111562003a3957600080fd5b8286015b8481101562003aec5780356001600160401b038082111562003a5f5760008081fd5b9088019060a0828b03601f190181131562003a7a5760008081fd5b62003a846200324d565b87840135815260408085013589830152606080860135828401526080915062003aaf82870162003380565b9083015291840135918383111562003ac75760008081fd5b62003ad78d8a858801016200335d565b90820152865250505091830191830162003a3d565b509695505050505050565b600060e0828403121562003b0a57600080fd5b62003b146200324d565b905081356001600160401b038082111562003b2e57600080fd5b9083019060e0828603121562003b4357600080fd5b62003b4d62003272565b82358281111562003b5d57600080fd5b62003b6b878286016200335d565b82525060208301358281111562003b8157600080fd5b62003b8f878286016200335d565b60208301525060408301358281111562003ba857600080fd5b62003bb6878286016200335d565b60408301525060608301358281111562003bcf57600080fd5b62003bdd878286016200335d565b60608301525062003bf160808401620033cc565b608082015262003c0460a08401620033cc565b60a082015262003c1760c08401620033b0565b60c0820152835262003c2d856020860162003984565b6020840152608084013591508082111562003c4757600080fd5b5062003c5684828501620039f4565b60408301525062003c6a60a08301620033b0565b606082015262003c7d60c08301620033b0565b608082015292915050565b60006020828403121562003c9b57600080fd5b81356001600160401b0381111562003cb257600080fd5b6200368f8482850162003af7565b6000806040838503121562003cd457600080fd5b82356001600160401b038082111562003cec57600080fd5b6200391a8683870162003af7565b60006020828403121562003d0d57600080fd5b81356001600160401b0381111562003d2457600080fd5b6200368f84828501620036eb565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60008151808452602080850194506020840160005b8381101562003d9757815163ffffffff168752958201959082019060010162003d73565b509495945050505050565b60208152815160208201526000602083015160c0604084015262003dca60e084018262003d5e565b90506040840151601f1984830301606085015262003de9828262003d5e565b915050606084015160018060a01b0380821660808601528060808701511660a08601528060a08701511660c086015250508091505092915050565b60006020828403121562003e3757600080fd5b5051919050565b60005b8381101562003e5b57818101518382015260200162003e41565b50506000910152565b6000815180845262003e7e81602086016020860162003e3e565b601f01601f19169290920160200192915050565b60208152600062000154602083018462003e64565b9182526001600160a01b0316602082015260400190565b600060018060a01b0380861683526060602084015284516060840152602085015161010080608086015262003ef861016086018362003d5e565b91506040870151605f198684030160a087015262003f17838262003d5e565b9250508260608801511660c0860152608087015160e086015260a0870151925062003f458186018462003697565b5060c086015161012085015260e086015161014085015283810360408501526200036c818662003e64565b60609190911b6001600160601b031916815260140190565b600082601f83011262003f9a57600080fd5b815162003fab6200332b82620032f0565b81815284602083860101111562003fc157600080fd5b6200368f82602083016020870162003e3e565b8051620033928162003397565b80516200339281620033bd565b600082601f8301126200400057600080fd5b81516020620040136200332b83620039ce565b82815260059290921b840181019181810190868411156200403357600080fd5b8286015b8481101562003aec5780516001600160401b0380821115620040595760008081fd5b908801906040828b03601f1901811315620040745760008081fd5b6200407e6200318c565b8784015183811115620040915760008081fd5b620040a18d8a8388010162003f88565b8252509201518683015250835291830191830162004037565b600060208284031215620040cd57600080fd5b81516001600160401b0380821115620040e557600080fd5b908301906101208286031215620040fb57600080fd5b6200410562003297565b8251828111156200411557600080fd5b620041238782860162003f88565b825250602083015160208201526200413e6040840162003fd4565b6040820152620041516060840162003fd4565b6060820152608083015160808201526200416e60a0840162003fd4565b60a082015260c083015160c08201526200418b60e0840162003fe1565b60e08201526101008084015183811115620041a557600080fd5b620041b38882870162003fee565b918301919091525095945050505050565b600082825180855260208086019550808260051b84010181860160005b848110156200422957601f198684030189528151604081518186526200420a8287018262003e64565b92870151958701959095525098840198925090830190600101620041e1565b5090979650505050505050565b60208152600082516101208060208501526200425761014085018362003e64565b915060208501516040850152604085015162004277606086018262003697565b5060608501516200428c608086018262003697565b50608085015160a085015260a0850151620042ab60c086018262003697565b5060c085015160e085015260e0850151610100620042cc8187018315159052565b860151858403601f1901838701529050620042e88382620041c4565b9695505050505050565b60208152600082516101008060208501526200431361012085018362003e64565b91506020850151601f198086850301604087015262004333848362003e64565b9350604087015191508086850301606087015262004352848362003e64565b935060608701519150808685030160808701525062004372838262003e64565b925050608085015160a085015260a08501516200439360c086018215159052565b5060c085015180151560e08601525060e0850151620043b58286018262003697565b5090949350505050565b6020815281516020820152602082015160408201526040820151606082015260ff60608301511660808201526000608083015160a0808401526200368f60c084018262003e64565b805182526020908101511515910152565b6200442582825162004407565b602081015162004439604084018262004407565b5060408101516200444e608084018262004407565b5060608101516200446360c084018262004407565b505050565b60208152600082516102806020840152620044886102a084018262003e64565b90506020840151601f1980858403016040860152620044a8838362003e64565b9250604086015191508085840301606086015250620044c8828262003e64565b9150506060840151620044e0608085018260ff169052565b50608084015160a084015260a084015160c084015260c08401516200450960e085018262003697565b5060e0840151610100620045208186018362003697565b8501519050610120620045368582018362004418565b85015180516001600160a01b039081166102208701526020820151166102408601526040810151610260860152606081015161028086015290505b509392505050565b60038110620033ad57634e487b7160e01b600052602160045260246000fd5b60006060808301606084528087518083526080925060808601915060808160051b8701016020808b016000805b858110156200465c578a8503607f19018752825180516001600160a01b03168652848101518a870190620045f98162004579565b878701526040918201519187018b90528151908190529085019083908a8801905b80831015620046465783516001600160e01b03191682529287019260019290920191908701906200461a565b50988601989650505091830191600101620045c5565b5050506200466d8189018b62003697565b50868103604088015262004682818962003e64565b9a9950505050505050505050565b81516001600160a01b0390811682526020808401518216908301526040808401519091169082015260608083015190820152608082015160a0820190620046d78162004579565b8060808401525092915050565b602081526000825160e060208401526200470361010084018262003e64565b90506020840151601f198085840301604086015262004723838362003e64565b9250604086015191508085840301606086015262004742838362003e64565b925060608601519150808584030160808601525062004762828262003e64565b9150506080840151151560a084015260a08401516200478560c085018215159052565b5060c08401516200457160e08501826200369756fe608060405260405161120b38038061120b83398101604081905261002291610dc2565b61002b82610136565b604080516001808252818301909252600091816020015b604080516060808201835260008083526020830152918101919091528152602001906001900390816100425750506040805160018082528183019092529192506000919060208083019080368337019050509050631f931c1c60e01b816000815181106100b1576100b1610df5565b6001600160e01b031990921660209283029190910182015260408051606081019091526001600160a01b038516815290810160008152602001828152508260008151811061010157610101610df5565b602002602001018190525061012d8260006040518060200160405280600081525061019660201b60201c565b505050506110e0565b60006101406103b4565b6004810180546001600160a01b038581166001600160a01b031983168117909355604051939450169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60005b83518110156103695760008482815181106101b6576101b6610df5565b6020026020010151602001519050600060028111156101d7576101d7610e0b565b8160028111156101e9576101e9610e0b565b0361023d5761023885838151811061020357610203610df5565b60200260200101516000015186848151811061022157610221610df5565b6020026020010151604001516103d860201b60201c565b610360565b600181600281111561025157610251610e0b565b036102a05761023885838151811061026b5761026b610df5565b60200260200101516000015186848151811061028957610289610df5565b60200260200101516040015161055560201b60201c565b60028160028111156102b4576102b4610e0b565b03610303576102388583815181106102ce576102ce610df5565b6020026020010151600001518684815181106102ec576102ec610df5565b6020026020010151604001516106db60201b60201c565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b60648201526084015b60405180910390fd5b50600101610199565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb67383838360405161039d93929190610e71565b60405180910390a16103af82826107f2565b505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c90565b60008151116103f95760405162461bcd60e51b815260040161035790610f74565b60006104036103b4565b90506001600160a01b03831661042b5760405162461bcd60e51b815260040161035790610fbf565b6001600160a01b0383166000908152600182016020526040812054906001600160601b03821690036104615761046182856108b8565b60005b835181101561054e57600084828151811061048157610481610df5565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b031680156105275760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f60448201527f6e207468617420616c72656164792065786973747300000000000000000000006064820152608401610357565b6105338583868a610922565b8361053d81611021565b945050600190920191506104649050565b5050505050565b60008151116105765760405162461bcd60e51b815260040161035790610f74565b60006105806103b4565b90506001600160a01b0383166105a85760405162461bcd60e51b815260040161035790610fbf565b6001600160a01b0383166000908152600182016020526040812054906001600160601b03821690036105de576105de82856108b8565b60005b835181101561054e5760008482815181106105fe576105fe610df5565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b0390811690871681036106a95760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e00000000000000006064820152608401610357565b6106b48582846109c2565b6106c08583868a610922565b836106ca81611021565b945050600190920191506105e19050565b60008151116106fc5760405162461bcd60e51b815260040161035790610f74565b60006107066103b4565b90506001600160a01b038316156107855760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f7665206661636574206164647260448201527f657373206d7573742062652061646472657373283029000000000000000000006064820152608401610357565b60005b82518110156107ec5760008382815181106107a5576107a5610df5565b6020908102919091018101516001600160e01b031981166000908152918590526040909120549091506001600160a01b03166107e28482846109c2565b5050600101610788565b50505050565b6001600160a01b038216610804575050565b610826826040518060600160405280602881526020016111bf60289139610d85565b600080836001600160a01b031683604051610841919061104f565b600060405180830381855af49150503d806000811461087c576040519150601f19603f3d011682016040523d82523d6000602084013e610881565b606091505b5091509150816107ec5780511561089b5780518082602001fd5b838360405163192105d760e01b815260040161035792919061106b565b6108da816040518060600160405280602481526020016111e760249139610d85565b6002820180546001600160a01b0390921660008181526001948501602090815260408220860185905594840183559182529290200180546001600160a01b0319169091179055565b6001600160e01b0319831660008181526020868152604080832080546001600160601b03909716600160a01b026001600160a01b0397881617815594909516808352600180890183529583208054968701815583528183206008870401805460e09890981c60046007909816979097026101000a96870263ffffffff9097021990971695909517909555529290915281546001600160a01b031916179055565b6001600160a01b038216610a3e5760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e27742065786973740000000000000000006064820152608401610357565b306001600160a01b03831603610aad5760405162461bcd60e51b815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201526d3a30b1363290333ab731ba34b7b760911b6064820152608401610357565b6001600160e01b03198116600090815260208481526040808320546001600160a01b0386168452600180880190935290832054600160a01b9091046001600160601b03169291610afc91611097565b9050808214610bee576001600160a01b03841660009081526001860160205260408120805483908110610b3157610b31610df5565b600091825260208083206008830401546001600160a01b038916845260018a019091526040909220805460079092166004026101000a90920460e01b925082919085908110610b8257610b82610df5565b600091825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b03199290921682528690526040902080546001600160a01b0316600160a01b6001600160601b038516021790555b6001600160a01b03841660009081526001860160205260409020805480610c1757610c176110b0565b60008281526020808220600860001990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b0319851682528690526040812081905581900361054e576002850154600090610c7a90600190611097565b6001600160a01b0386166000908152600180890160205260409091200154909150808214610d29576000876002018381548110610cb957610cb9610df5565b6000918252602090912001546002890180546001600160a01b039092169250829184908110610cea57610cea610df5565b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152600189810190925260409020018190555b86600201805480610d3c57610d3c6110b0565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0388168252600189810190915260408220015550505050505050565b813b81816107ec5760405162461bcd60e51b815260040161035791906110c6565b80516001600160a01b0381168114610dbd57600080fd5b919050565b60008060408385031215610dd557600080fd5b610dde83610da6565b9150610dec60208401610da6565b90509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b60005b83811015610e3c578181015183820152602001610e24565b50506000910152565b60008151808452610e5d816020860160208601610e21565b601f01601f19169290920160200192915050565b60006060808301606084528087518083526080925060808601915060808160051b8701016020808b0160005b84811015610f4457898403607f19018652815180516001600160a01b03168552838101518986019060038110610ee357634e487b7160e01b600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b80831015610f2f5783516001600160e01b0319168252928601926001929092019190860190610f05565b50978501979550505090820190600101610e9d565b50506001600160a01b038a16908801528681036040880152610f668189610e45565b9a9950505050505050505050565b6020808252602b908201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660408201526a1858d95d081d1bc818dd5d60aa1b606082015260800190565b6020808252602c908201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260408201526b65206164647265737328302960a01b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b60006001600160601b038281166002600160601b031981016110455761104561100b565b6001019392505050565b60008251611061818460208701610e21565b9190910192915050565b6001600160a01b038316815260406020820181905260009061108f90830184610e45565b949350505050565b818103818111156110aa576110aa61100b565b92915050565b634e487b7160e01b600052603160045260246000fd5b6020815260006110d96020830184610e45565b9392505050565b60d1806110ee6000396000f3fe608060405236600a57005b600080356001600160e01b03191681527fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c602081905260409091205481906001600160a01b03168060a15760405162461bcd60e51b815260206004820181905260248201527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f74206578697374604482015260640160405180910390fd5b3660008037600080366000845af43d6000803e80801560bf573d6000f35b3d6000fdfea164736f6c6343000817000a4c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a204e657720666163657420686173206e6f20636f6465ca16e7727e34eddfd016efc2c74be18308b7e9d9c361f0e67d4167ec00bcb635d7d8b7014b7ed36eb085c9e3e427b642d74cab75ecefda8a757042e63ec59919a164736f6c6343000817000a

Deployed Bytecode

0x6080604052600436106200005c5760003560e01c80636791a805146200006157806394ed410e14620000905780639f65bd5314620000b5578063b205911314620000da578063cb4a55d914620000f1578063ded782941462000116575b600080fd5b620000786200007236600462003657565b6200012d565b604051620000879190620036a4565b60405180910390f35b3480156200009d57600080fd5b5062000078620000af366004620038e0565b6200015b565b348015620000c257600080fd5b5062000078620000d43660046200394a565b6200017a565b62000078620000eb36600462003c88565b62000199565b348015620000fe57600080fd5b50620000786200011036600462003cc0565b620001c0565b620000786200012736600462003cfa565b620001df565b6000806200014660008460200151856040015162000206565b905062000154838262000377565b9392505050565b60006200016a60018362000804565b62000154838360400151620009fd565b60006200018960008362000804565b6200015483836040015162000377565b600080620001b260028460600151856080015162000206565b905062000154838262000e0b565b6000620001cf60028362000804565b6200015483836040015162000e0b565b600080620001f860018460400151856060015162000206565b9050620001548382620009fd565b6040805160018082528183019092526000918291906020808301908036833701905050905084600281111562000240576200024062003d32565b8160008151811062000256576200025662003d48565b63ffffffff9290921660209283029190910190910152604080516001808252818301909252600091816020016020820280368337019050509050600181600081518110620002a857620002a862003d48565b63ffffffff9092166020928302919091018201526040805160c081018252600080516020620059a683398151915281529182018490528181018390526001600160a01b038088166060840152336080840152861660a083015251635d048b2560e11b8152309063ba09164a9034906200032690859060040162003da2565b60206040518083038185885af115801562000345573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906200036c919062003e24565b979650505050505050565b6000806200038462001187565b905062000390620011ab565b9150620003a28285600001516200127b565b6010810154604051636bc26a1360e11b81526001600160a01b038481169263d784d42692620003d89290911690600401620036a4565b600060405180830381600087803b158015620003f357600080fd5b505af115801562000408573d6000803e3d6000fd5b505085515160405163c47f002760e01b81528593506001600160a01b038416925063c47f0027916200043d9160040162003e92565b600060405180830381600087803b1580156200045857600080fd5b505af11580156200046d573d6000803e3d6000fd5b5050865160200151604051635c26412360e11b81526001600160a01b038516935063b84c82469250620004a4919060040162003e92565b600060405180830381600087803b158015620004bf57600080fd5b505af1158015620004d4573d6000803e3d6000fd5b5050865160600151604051633d09cad560e11b815260ff90911660048201526001600160a01b0384169250637a1395aa9150602401600060405180830381600087803b1580156200052457600080fd5b505af115801562000539573d6000803e3d6000fd5b5050865160800151159150620005cc905057845160c08101516080909101516040516340c10f1960e01b81526001600160a01b038416926340c10f199262000597926004016001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015620005b257600080fd5b505af1158015620005c7573d6000803e3d6000fd5b505050505b604051636078c0f960e01b81526001600160a01b03821690636078c0f990620005fa903090600401620036a4565b600060405180830381600087803b1580156200061557600080fd5b505af11580156200062a573d6000803e3d6000fd5b5050506005830154604051636078c0f960e01b81526001600160a01b038085169350636078c0f9926200066392911690600401620036a4565b600060405180830381600087803b1580156200067e57600080fd5b505af115801562000693573d6000803e3d6000fd5b505050600583015460405163019cc55360e51b81526001600160a01b038085169350633398aa6092620006cc92911690600401620036a4565b600060405180830381600087803b158015620006e757600080fd5b505af1158015620006fc573d6000803e3d6000fd5b5050506005830154604051632f2ff15d60e01b81526001600160a01b039091169150632f2ff15d9062000756907f0e512f22a4a66880dbe62f43c3840e18a3b81e1a4c1c40bba7dc19b0503e51a990879060040162003ea7565b600060405180830381600087803b1580156200077157600080fd5b505af115801562000786573d6000803e3d6000fd5b5050505060006040518060a00160405280856001600160a01b03168152602001876000015160e001516001600160a01b0316815260200187602001516001600160a01b0316815260200186815260200160006002811115620007ec57620007ec62003d32565b90529050620007fb81620013a7565b50505092915050565b604080516001808252818301909252600091602080830190803683370190505090508260028111156200083b576200083b62003d32565b8160008151811062000851576200085162003d48565b63ffffffff9290921660209283029190910190910152604080516001808252818301909252600091816020016020820280368337019050509050600181600081518110620008a357620008a362003d48565b602002602001019063ffffffff16908163ffffffff16815250506000604051806101000160405280600080516020620059a68339815191528152602001848152602001838152602001336001600160a01b03168152602001306001600160a01b031663564b81ef6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200093a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000960919062003e24565b815260200185600001516001600160a01b031681526020018560200151815260200185604001518152509050306001600160a01b031663b459f7ca338387606001516040518463ffffffff1660e01b8152600401620009c29392919062003ebe565b600060405180830381600087803b158015620009dd57600080fd5b505af1158015620009f2573d6000803e3d6000fd5b505050505050505050565b600062000a09620011ab565b905062000a1b81846000015162001518565b600062000a2762001187565b6011810154604051636bc26a1360e11b81529192506001600160a01b038085169263d784d4269262000a5e921690600401620036a4565b600060405180830381600087803b15801562000a7957600080fd5b505af115801562000a8e573d6000803e3d6000fd5b50600092506001915062000a9f9050565b60405190808252806020026020018201604052801562000ae757816020015b60408051808201909152606081526000602082015281526020019060019003908162000abe5790505b5060408051608081018252600b9181019182526a115490cdcc8c48135a5b9d60aa1b60608201529081526020878101515190820152815191925090829060009062000b365762000b3662003d48565b6020026020010181905250600060405180610120016040528087600001516000015181526020018560405160200162000b70919062003f70565b60408051601f1981840301815291815281516020928301208352895160e001516001600160a01b03908116848401528a83018051909301511683820152905160609081015190830152516323cb241360e11b8152600080516020620059a683398151915260048201526080909101903090634796482690602401600060405180830381865afa15801562000c08573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000c329190810190620040ba565b60a001516001600160a01b031681526020018760200151604001518152602001600015158152602001838152509050306001600160a01b031663f5616c1f826040518263ffffffff1660e01b815260040162000c8f919062004236565b600060405180830381600087803b15801562000caa57600080fd5b505af115801562000cbf573d6000803e3d6000fd5b50508751604051636fe49ad960e01b81526001600160a01b0388169350636fe49ad9925062000cf29190600401620042f2565b600060405180830381600087803b15801562000d0d57600080fd5b505af115801562000d22573d6000803e3d6000fd5b5050604051632f2ff15d60e01b8152309250632f2ff15d915062000d5c90600080516020620059c683398151915290889060040162003ea7565b600060405180830381600087803b15801562000d7757600080fd5b505af115801562000d8c573d6000803e3d6000fd5b5050505060006040518060a00160405280866001600160a01b03168152602001886000015160e001516001600160a01b0316815260200188604001516001600160a01b031681526020018781526020016001600281111562000df25762000df262003d32565b9052905062000e0181620013a7565b5050505092915050565b600062000e17620011ab565b905062000e2981846000015162001608565b600062000e3562001187565b6012810154604051636bc26a1360e11b81529192506001600160a01b038085169263d784d4269262000e6c921690600401620036a4565b600060405180830381600087803b15801562000e8757600080fd5b505af115801562000e9c573d6000803e3d6000fd5b505050506060600060405180610120016040528087600001516000015181526020018560405160200162000ed1919062003f70565b60408051808303601f19018152918152815160209283012083526001600160a01b0388811684840152918a018051519092168382015290518101516060830152516323cb241360e11b8152600080516020620059a683398151915260048201526080909101903090634796482690602401600060405180830381865afa15801562000f60573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000f8a9190810190620040ba565b60a001516001600160a01b031681526020018760200151602001518152602001600015158152602001838152509050306001600160a01b031663f5616c1f826040518263ffffffff1660e01b815260040162000fe7919062004236565b600060405180830381600087803b1580156200100257600080fd5b505af115801562001017573d6000803e3d6000fd5b5050604051632f2ff15d60e01b8152309250632f2ff15d91506200105190600080516020620059c683398151915290889060040162003ea7565b600060405180830381600087803b1580156200106c57600080fd5b505af115801562001081573d6000803e3d6000fd5b5050505060005b8660400151518110156200112557846001600160a01b03166307e10c0d88604001518381518110620010be57620010be62003d48565b60200260200101516040518263ffffffff1660e01b8152600401620010e49190620043bf565b600060405180830381600087803b158015620010ff57600080fd5b505af115801562001114573d6000803e3d6000fd5b505060019092019150620010889050565b5060006040518060a00160405280866001600160a01b03168152602001886000015160c001516001600160a01b0316815260200188606001516001600160a01b0316815260200187815260200160028081111562000df25762000df262003d32565b7fae91e73249036d298733b3485b49b39bcb9229df52016e2810a03f18355028f690565b6307e4c70760e21b60009081527fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c60208181526040805180820182527f9f0ce991cd9c4f6eaf19f214129f7a5c88ce0f46a01a0f164d4f0d44366a92a8546001600160a01b038116808352600160a01b9091046001600160601b0316938201939093529051909130916200123f9062003168565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562001273573d6000803e3d6000fd5b509250505090565b60006200128762001187565b9050600062001295620016f8565b90506000620012a3620018b7565b6040805160608101909152600a8501546001600160a01b0316815290915060208101600081526020018281525082600081518110620012e657620012e662003d48565b602002602001018190525060008460405160240162001306919062004468565b60408051601f198184030181529181526020820180516001600160e01b0316634e06b2e160e11b179052600b86015490516307e4c70760e21b81529192506001600160a01b0380891692631f931c1c926200136b928892911690869060040162004598565b600060405180830381600087803b1580156200138657600080fd5b505af11580156200139b573d6000803e3d6000fd5b50505050505050505050565b6000620013b362001187565b905080600101600083608001516002811115620013d457620013d462003d32565b6002811115620013e857620013e862003d32565b81526020808201929092526040908101600090812085840180516001600160a01b0390811684529185528383208751815460018101835591855286852090910180549184166001600160a01b0319928316179055905187518316845260028088019096529383208054949092169316929092179091556080840151839281111562001477576200147762003d32565b60028111156200148b576200148b62003d32565b81526020808201929092526040908101600090812085518154600181018355918352939091200180546001600160a01b0319166001600160a01b0390931692909217909155600382015490517f5bb644ee2a83060962b095d7d1eb91687997dbc60b60ea2a63eba7cd42c16fb6906200150690859062004690565b60405180910390a24360039091015550565b60006200152462001187565b9050600062001532620016f8565b905060006200154062002227565b6040805160608101909152600c8501546001600160a01b031681529091506020810160008152602001828152508260008151811062001583576200158362003d48565b6020026020010181905250600084604051602401620015a39190620042f2565b60408051601f198184030181529181526020820180516001600160e01b03166345d4de7b60e01b179052600d86015490516307e4c70760e21b81529192506001600160a01b0380891692631f931c1c926200136b928892911690869060040162004598565b60006200161462001187565b9050600062001622620016f8565b9050600062001630620027a4565b6040805160608101909152600e8501546001600160a01b031681529091506020810160008152602001828152508260008151811062001673576200167362003d48565b6020026020010181905250600084604051602401620016939190620046e4565b60408051601f198184030181529181526020820180516001600160e01b031663c952bb1960e01b179052600f86015490516307e4c70760e21b81529192506001600160a01b0380891692631f931c1c926200136b928892911690869060040162004598565b606060006200170662001187565b60408051600580825260c08201909252919250816020015b604080516060808201835260008083526020830152918101919091528152602001906001900390816200171e57905050915060006200175c62002d93565b604080516060810190915260068401546001600160a01b03168152909150602081016000815260200182815250836001815181106200179f576200179f62003d48565b6020026020010181905250620017b462002f4d565b604080516060810190915260078401546001600160a01b0316815290915060208101600081526020018281525083600281518110620017f757620017f762003d48565b60200260200101819052506200180c62003001565b604080516060810190915260088401546001600160a01b03168152909150602081016000815260200182815250836003815181106200184f576200184f62003d48565b602002602001018190525062001864620030f0565b604080516060810190915260098401546001600160a01b0316815290915060208101600081526020018281525083600481518110620018a757620018a762003d48565b6020026020010181905250505090565b60408051602980825261054082019092526060916000919060208201610520803683370190505090506318160ddd60e01b81600081518110620018fe57620018fe62003d48565b6001600160e01b03199092166020928302919091019091015280516370a0823160e01b908290600190811062001938576200193862003d48565b6001600160e01b0319909216602092830291909101909101528051636eb1769f60e11b908290600290811062001972576200197262003d48565b6001600160e01b031990921660209283029190910190910152805163095ea7b360e01b9082906003908110620019ac57620019ac62003d48565b6001600160e01b031990921660209283029190910190910152805163a9059cbb60e01b9082906004908110620019e657620019e662003d48565b6001600160e01b03199092166020928302919091019091015280516323b872dd60e01b908290600590811062001a205762001a2062003d48565b6001600160e01b0319909216602092830291909101909101528051633950935160e01b908290600690811062001a5a5762001a5a62003d48565b6001600160e01b031990921660209283029190910190910152805163a457c2d760e01b908290600790811062001a945762001a9462003d48565b6001600160e01b03199092166020928302919091019091015280516306fdde0360e01b908290600890811062001ace5762001ace62003d48565b6001600160e01b03199092166020928302919091019091015280516395d89b4160e01b908290600990811062001b085762001b0862003d48565b6001600160e01b031990921660209283029190910190910152805163313ce56760e01b908290600a90811062001b425762001b4262003d48565b6001600160e01b0319909216602092830291909101909101528051633644e51560e01b908290600b90811062001b7c5762001b7c62003d48565b6001600160e01b0319909216602092830291909101909101528051623f675f60e91b908290600c90811062001bb55762001bb562003d48565b6001600160e01b031990921660209283029190910190910152805163d505accf60e01b908290600d90811062001bef5762001bef62003d48565b6001600160e01b03199092166020928302919091019091015280516340c10f1960e01b908290600e90811062001c295762001c2962003d48565b6001600160e01b0319909216602092830291909101909101528051631780542160e31b908290600f90811062001c635762001c6362003d48565b6001600160e01b0319909216602092830291909101909101528051637f51bb1f60e01b908290601090811062001c9d5762001c9d62003d48565b6001600160e01b031990921660209283029190910190910152805163c47f002760e01b908290601190811062001cd75762001cd762003d48565b6001600160e01b0319909216602092830291909101909101528051635c26412360e11b908290601290811062001d115762001d1162003d48565b6001600160e01b0319909216602092830291909101909101528051633d09cad560e11b908290601390811062001d4b5762001d4b62003d48565b6001600160e01b0319909216602092830291909101909101528051633cae3f5f60e11b908290601490811062001d855762001d8562003d48565b6001600160e01b0319909216602092830291909101909101528051633aa1d1d560e11b908290601590811062001dbf5762001dbf62003d48565b6001600160e01b031990921660209283029190910190910152805163019cc55360e51b908290601690811062001df95762001df962003d48565b6001600160e01b03199092166020928302919091019091015280516316c0896d60e31b908290601790811062001e335762001e3362003d48565b6001600160e01b031990921660209283029190910190910152805163612881a360e11b908290601890811062001e6d5762001e6d62003d48565b6001600160e01b0319909216602092830291909101909101528051636078c0f960e01b908290601990811062001ea75762001ea762003d48565b6001600160e01b0319909216602092830291909101909101528051631ec70d6760e21b908290601a90811062001ee15762001ee162003d48565b6001600160e01b0319909216602092830291909101909101528051634d78e9ad60e11b908290601b90811062001f1b5762001f1b62003d48565b6001600160e01b0319909216602092830291909101909101528051636addb66360e01b908290601c90811062001f555762001f5562003d48565b6001600160e01b03199092166020928302919091019091015280516311c565df60e01b908290601d90811062001f8f5762001f8f62003d48565b6001600160e01b03199092166020928302919091019091015280516318f60b6960e01b908290601e90811062001fc95762001fc962003d48565b6001600160e01b03199092166020928302919091019091015280516311557f7960e11b908290601f90811062002003576200200362003d48565b6001600160e01b0319909216602092830291909101820152815163997d0feb60e01b918391811062002039576200203962003d48565b6001600160e01b031990921660209283029190910190910152805163029d58c160e11b908290602190811062002073576200207362003d48565b6001600160e01b0319909216602092830291909101909101528051631e59818360e31b9082906022908110620020ad57620020ad62003d48565b6001600160e01b031990921660209283029190910190910152805163f84354f160e01b9082906023908110620020e757620020e762003d48565b6001600160e01b031990921660209283029190910190910152805163045a6e8360e51b908290602490811062002121576200212162003d48565b6001600160e01b031990921660209283029190910190910152805163011424b960e51b90829060259081106200215b576200215b62003d48565b6001600160e01b0319909216602092830291909101909101528051634549b03960e01b908290602690811062002195576200219562003d48565b6001600160e01b0319909216602092830291909101909101528051632d83811960e01b9082906027908110620021cf57620021cf62003d48565b6001600160e01b03199092166020928302919091019091015280516313114a9d60e01b908290602890811062002209576200220962003d48565b6001600160e01b031990921660209283029190910190910152919050565b60408051601880825261032082019092526060916000919060208201610300803683370190505090506301ffc9a760e01b816000815181106200226e576200226e62003d48565b6001600160e01b03199092166020928302919091019091015280516370a0823160e01b9082906001908110620022a857620022a862003d48565b6001600160e01b03199092166020928302919091019091015280516331a9108f60e11b9082906002908110620022e257620022e262003d48565b6001600160e01b03199092166020928302919091019091015280516323b872dd60e01b90829060039081106200231c576200231c62003d48565b6001600160e01b031990921660209283029190910190910152805163095ea7b360e01b908290600490811062002356576200235662003d48565b6001600160e01b031990921660209283029190910190910152805163020604bf60e21b908290600590811062002390576200239062003d48565b6001600160e01b031990921660209283029190910190910152805163a22cb46560e01b9082906006908110620023ca57620023ca62003d48565b6001600160e01b031990921660209283029190910190910152805163e985e9c560e01b908290600790811062002404576200240462003d48565b6001600160e01b03199092166020928302919091019091015280516318160ddd60e01b90829060089081106200243e576200243e62003d48565b6001600160e01b0319909216602092830291909101909101528051632f745c5960e01b908290600990811062002478576200247862003d48565b6001600160e01b0319909216602092830291909101909101528051634f6ccce760e01b908290600a908110620024b257620024b262003d48565b6001600160e01b03199092166020928302919091019091015280516306fdde0360e01b908290600b908110620024ec57620024ec62003d48565b6001600160e01b03199092166020928302919091019091015280516395d89b4160e01b908290600c90811062002526576200252662003d48565b6001600160e01b031990921660209283029190910190910152805163c87b56dd60e01b908290600d90811062002560576200256062003d48565b6001600160e01b0319909216602092830291909101909101528051634bb4ee0760e11b908290600e9081106200259a576200259a62003d48565b6001600160e01b0319909216602092830291909101909101528051637600c26f60e11b908290600f908110620025d457620025d462003d48565b6001600160e01b0319909216602092830291909101909101528051636fe49ad960e01b90829060109081106200260e576200260e62003d48565b6001600160e01b0319909216602092830291909101909101528051632bfbbc4f60e11b908290601190811062002648576200264862003d48565b6001600160e01b031990921660209283029190910190910152805163318c2e2160e11b908290601290811062002682576200268262003d48565b6001600160e01b031990921660209283029190910190910152805163b7b1140160e01b9082906013908110620026bc57620026bc62003d48565b6001600160e01b031990921660209283029190910190910152805163a09b654560e01b9082906014908110620026f657620026f662003d48565b6001600160e01b03199092166020928302919091019091015280516337ef227760e11b908290601590811062002730576200273062003d48565b6001600160e01b0319909216602092830291909101909101528051636addb66360e01b90829060169081106200276a576200276a62003d48565b6001600160e01b0319909216602092830291909101909101528051631850e64b60e11b908290601790811062002209576200220962003d48565b60408051601a80825261036082019092526060916000919060208201610340803683370190505090506301ffc9a760e01b81600081518110620027eb57620027eb62003d48565b6001600160e01b0319909216602092830291909101909101528051627eeac760e11b908290600190811062002824576200282462003d48565b6001600160e01b03199092166020928302919091019091015280516313849cfd60e21b90829060029081106200285e576200285e62003d48565b6001600160e01b031990921660209283029190910190910152805163e985e9c560e01b908290600390811062002898576200289862003d48565b6001600160e01b031990921660209283029190910190910152805163a22cb46560e01b9082906004908110620028d257620028d262003d48565b6001600160e01b0319909216602092830291909101909101528051637921219560e11b90829060059081106200290c576200290c62003d48565b6001600160e01b0319909216602092830291909101909101528051631759616b60e11b908290600690811062002946576200294662003d48565b6001600160e01b031990921660209283029190910190910152805163bd85b03960e01b908290600790811062002980576200298062003d48565b6001600160e01b03199092166020928302919091019091015280516313ba55df60e01b9082906008908110620029ba57620029ba62003d48565b6001600160e01b0319909216602092830291909101909101528051636dcfd84160e01b9082906009908110620029f457620029f462003d48565b6001600160e01b03199092166020928302919091019091015280516385bff2e760e01b908290600a90811062002a2e5762002a2e62003d48565b6001600160e01b03199092166020928302919091019091015280516303a24d0760e21b908290600b90811062002a685762002a6862003d48565b6001600160e01b0319909216602092830291909101909101528051624a84cb60e01b908290600c90811062002aa15762002aa162003d48565b6001600160e01b0319909216602092830291909101909101528051636d487de160e01b908290600d90811062002adb5762002adb62003d48565b6001600160e01b03199092166020928302919091019091015280516307e10c0d60e01b908290600e90811062002b155762002b1562003d48565b6001600160e01b031990921660209283029190910190910152805163eeecf93f60e01b908290600f90811062002b4f5762002b4f62003d48565b6001600160e01b0319909216602092830291909101909101528051632bfbbc4f60e11b908290601090811062002b895762002b8962003d48565b6001600160e01b0319909216602092830291909101909101528051630582268f60e51b908290601190811062002bc35762002bc362003d48565b6001600160e01b031990921660209283029190910190910152805163ddc97a4160e01b908290601290811062002bfd5762002bfd62003d48565b6001600160e01b0319909216602092830291909101909101528051636addb66360e01b908290601390811062002c375762002c3762003d48565b6001600160e01b03199092166020928302919091019091015280516321a7dd6560e21b908290601490811062002c715762002c7162003d48565b6001600160e01b0319909216602092830291909101909101528051631fa3f33160e11b908290601590811062002cab5762002cab62003d48565b6001600160e01b031990921660209283029190910190910152805163fd94616360e01b908290601690811062002ce55762002ce562003d48565b6001600160e01b0319909216602092830291909101909101528051634f558e7960e01b908290601790811062002d1f5762002d1f62003d48565b6001600160e01b0319909216602092830291909101909101528051631969630160e21b908290601890811062002d595762002d5962003d48565b6001600160e01b0319909216602092830291909101909101528051631850e64b60e11b908290601990811062002209576200220962003d48565b60408051600780825261010082019092526060916020820160e0803683370190505090506391d1485460e01b8160008151811062002dd55762002dd562003d48565b6001600160e01b031990921660209283029190910190910152805163248a9ca360e01b908290600190811062002e0f5762002e0f62003d48565b6001600160e01b0319909216602092830291909101909101528051632f2ff15d60e01b908290600290811062002e495762002e4962003d48565b6001600160e01b031990921660209283029190910190910152805163d547741f60e01b908290600390811062002e835762002e8362003d48565b6001600160e01b0319909216602092830291909101909101528051638bb9c5bf60e01b908290600490811062002ebd5762002ebd62003d48565b6001600160e01b0319909216602092830291909101909101528051632404341f60e21b908290600590811062002ef75762002ef762003d48565b6001600160e01b031990921660209283029190910190910152805163ca15c87360e01b908290600690811062002f315762002f3162003d48565b6001600160e01b03199092166020928302919091019091015290565b60408051600380825260808201909252606091602082018380368337019050509050635c975abb60e01b8160008151811062002f8d5762002f8d62003d48565b6001600160e01b0319909216602092830291909101909101528051638456cb5960e01b908290600190811062002fc75762002fc762003d48565b6001600160e01b0319909216602092830291909101909101528051631fa5d41d60e11b908290600290811062002f315762002f3162003d48565b60408051600480825260a082019092526060916020820160808036833701905050905063adfca15e60e01b8160008151811062003042576200304262003d48565b6001600160e01b03199092166020928302919091019091015280516366ffd66360e11b90829060019081106200307c576200307c62003d48565b6001600160e01b03199092166020928302919091019091015280516314bbdacb60e21b9082906002908110620030b657620030b662003d48565b6001600160e01b0319909216602092830291909101909101528051637a0ed62760e01b908290600390811062002f315762002f3162003d48565b6040805160028082526060808301845292602083019080368337019050509050635c60da1b60e01b816000815181106200312e576200312e62003d48565b6001600160e01b0319909216602092830291909101909101528051636bc26a1360e11b908290600190811062002f315762002f3162003d48565b61120b806200479b83390190565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715620031b157620031b162003176565b60405290565b604051608081016001600160401b0381118282101715620031b157620031b162003176565b604051606081016001600160401b0381118282101715620031b157620031b162003176565b60405161014081016001600160401b0381118282101715620031b157620031b162003176565b60405161010081016001600160401b0381118282101715620031b157620031b162003176565b60405160a081016001600160401b0381118282101715620031b157620031b162003176565b60405160e081016001600160401b0381118282101715620031b157620031b162003176565b60405161012081016001600160401b0381118282101715620031b157620031b162003176565b604051601f8201601f191681016001600160401b0381118282101715620032e857620032e862003176565b604052919050565b60006001600160401b038211156200330c576200330c62003176565b50601f01601f191660200190565b6000620033316200332b84620032f0565b620032bd565b90508281528383830111156200334657600080fd5b828260208301376000602084830101529392505050565b600082601f8301126200336f57600080fd5b62000154838335602085016200331a565b803560ff811681146200339257600080fd5b919050565b6001600160a01b0381168114620033ad57600080fd5b50565b8035620033928162003397565b8015158114620033ad57600080fd5b80356200339281620033bd565b600060408284031215620033ec57600080fd5b620033f66200318c565b90508135815260208201356200340c81620033bd565b602082015292915050565b600061010082840312156200342b57600080fd5b62003435620031b7565b9050620034438383620033d9565b8152620034548360408401620033d9565b6020820152620034688360808401620033d9565b60408201526200347c8360c08401620033d9565b606082015292915050565b6000608082840312156200349a57600080fd5b620034a4620031b7565b90508135620034b38162003397565b81526020820135620034c58162003397565b80602083015250604082013560408201526060820135606082015292915050565b600060608284031215620034f957600080fd5b62003503620031dc565b905081356001600160401b03808211156200351d57600080fd5b9083019061028082860312156200353357600080fd5b6200353d62003201565b8235828111156200354d57600080fd5b6200355b878286016200335d565b8252506020830135828111156200357157600080fd5b6200357f878286016200335d565b6020830152506040830135828111156200359857600080fd5b620035a6878286016200335d565b604083015250620035ba6060840162003380565b60608201526080830135608082015260a083013560a0820152620035e160c08401620033b0565b60c0820152620035f460e08401620033b0565b60e082015261010091506200360c8683850162003417565b828201526200362086610200850162003487565b61012082015283525062003639905060208301620033b0565b60208201526200364c60408301620033b0565b604082015292915050565b6000602082840312156200366a57600080fd5b81356001600160401b038111156200368157600080fd5b6200368f84828501620034e6565b949350505050565b6001600160a01b03169052565b6001600160a01b0391909116815260200190565b600060808284031215620036cb57600080fd5b620036d5620031b7565b9050813581526020820135620034c58162003397565b600060e08284031215620036fe57600080fd5b62003708620031b7565b905081356001600160401b03808211156200372257600080fd5b9083019061010082860312156200373857600080fd5b6200374262003227565b8235828111156200375257600080fd5b62003760878286016200335d565b8252506020830135828111156200377657600080fd5b62003784878286016200335d565b6020830152506040830135828111156200379d57600080fd5b620037ab878286016200335d565b604083015250606083013582811115620037c457600080fd5b620037d2878286016200335d565b60608301525060808301356080820152620037f060a08401620033cc565b60a08201526200380360c08401620033cc565b60c08201526200381660e08401620033b0565b60e08201528352506200382f90508360208401620036b8565b60208201526200384260a08301620033b0565b60408201526200347c60c08301620033b0565b6000608082840312156200386857600080fd5b62003872620031b7565b90508135620038818162003397565b8152602082810135908201526040808301359082015260608201356001600160401b03811115620038b157600080fd5b8201601f81018413620038c357600080fd5b620038d4848235602084016200331a565b60608301525092915050565b60008060408385031215620038f457600080fd5b82356001600160401b03808211156200390c57600080fd5b6200391a86838701620036eb565b935060208501359150808211156200393157600080fd5b50620039408582860162003855565b9150509250929050565b600080604083850312156200395e57600080fd5b82356001600160401b03808211156200397657600080fd5b6200391a86838701620034e6565b6000606082840312156200399757600080fd5b620039a1620031dc565b90508135620039b08162003397565b80825250602082013560208201526040820135604082015292915050565b60006001600160401b03821115620039ea57620039ea62003176565b5060051b60200190565b600082601f83011262003a0657600080fd5b8135602062003a196200332b83620039ce565b82815260059290921b8401810191818101908684111562003a3957600080fd5b8286015b8481101562003aec5780356001600160401b038082111562003a5f5760008081fd5b9088019060a0828b03601f190181131562003a7a5760008081fd5b62003a846200324d565b87840135815260408085013589830152606080860135828401526080915062003aaf82870162003380565b9083015291840135918383111562003ac75760008081fd5b62003ad78d8a858801016200335d565b90820152865250505091830191830162003a3d565b509695505050505050565b600060e0828403121562003b0a57600080fd5b62003b146200324d565b905081356001600160401b038082111562003b2e57600080fd5b9083019060e0828603121562003b4357600080fd5b62003b4d62003272565b82358281111562003b5d57600080fd5b62003b6b878286016200335d565b82525060208301358281111562003b8157600080fd5b62003b8f878286016200335d565b60208301525060408301358281111562003ba857600080fd5b62003bb6878286016200335d565b60408301525060608301358281111562003bcf57600080fd5b62003bdd878286016200335d565b60608301525062003bf160808401620033cc565b608082015262003c0460a08401620033cc565b60a082015262003c1760c08401620033b0565b60c0820152835262003c2d856020860162003984565b6020840152608084013591508082111562003c4757600080fd5b5062003c5684828501620039f4565b60408301525062003c6a60a08301620033b0565b606082015262003c7d60c08301620033b0565b608082015292915050565b60006020828403121562003c9b57600080fd5b81356001600160401b0381111562003cb257600080fd5b6200368f8482850162003af7565b6000806040838503121562003cd457600080fd5b82356001600160401b038082111562003cec57600080fd5b6200391a8683870162003af7565b60006020828403121562003d0d57600080fd5b81356001600160401b0381111562003d2457600080fd5b6200368f84828501620036eb565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60008151808452602080850194506020840160005b8381101562003d9757815163ffffffff168752958201959082019060010162003d73565b509495945050505050565b60208152815160208201526000602083015160c0604084015262003dca60e084018262003d5e565b90506040840151601f1984830301606085015262003de9828262003d5e565b915050606084015160018060a01b0380821660808601528060808701511660a08601528060a08701511660c086015250508091505092915050565b60006020828403121562003e3757600080fd5b5051919050565b60005b8381101562003e5b57818101518382015260200162003e41565b50506000910152565b6000815180845262003e7e81602086016020860162003e3e565b601f01601f19169290920160200192915050565b60208152600062000154602083018462003e64565b9182526001600160a01b0316602082015260400190565b600060018060a01b0380861683526060602084015284516060840152602085015161010080608086015262003ef861016086018362003d5e565b91506040870151605f198684030160a087015262003f17838262003d5e565b9250508260608801511660c0860152608087015160e086015260a0870151925062003f458186018462003697565b5060c086015161012085015260e086015161014085015283810360408501526200036c818662003e64565b60609190911b6001600160601b031916815260140190565b600082601f83011262003f9a57600080fd5b815162003fab6200332b82620032f0565b81815284602083860101111562003fc157600080fd5b6200368f82602083016020870162003e3e565b8051620033928162003397565b80516200339281620033bd565b600082601f8301126200400057600080fd5b81516020620040136200332b83620039ce565b82815260059290921b840181019181810190868411156200403357600080fd5b8286015b8481101562003aec5780516001600160401b0380821115620040595760008081fd5b908801906040828b03601f1901811315620040745760008081fd5b6200407e6200318c565b8784015183811115620040915760008081fd5b620040a18d8a8388010162003f88565b8252509201518683015250835291830191830162004037565b600060208284031215620040cd57600080fd5b81516001600160401b0380821115620040e557600080fd5b908301906101208286031215620040fb57600080fd5b6200410562003297565b8251828111156200411557600080fd5b620041238782860162003f88565b825250602083015160208201526200413e6040840162003fd4565b6040820152620041516060840162003fd4565b6060820152608083015160808201526200416e60a0840162003fd4565b60a082015260c083015160c08201526200418b60e0840162003fe1565b60e08201526101008084015183811115620041a557600080fd5b620041b38882870162003fee565b918301919091525095945050505050565b600082825180855260208086019550808260051b84010181860160005b848110156200422957601f198684030189528151604081518186526200420a8287018262003e64565b92870151958701959095525098840198925090830190600101620041e1565b5090979650505050505050565b60208152600082516101208060208501526200425761014085018362003e64565b915060208501516040850152604085015162004277606086018262003697565b5060608501516200428c608086018262003697565b50608085015160a085015260a0850151620042ab60c086018262003697565b5060c085015160e085015260e0850151610100620042cc8187018315159052565b860151858403601f1901838701529050620042e88382620041c4565b9695505050505050565b60208152600082516101008060208501526200431361012085018362003e64565b91506020850151601f198086850301604087015262004333848362003e64565b9350604087015191508086850301606087015262004352848362003e64565b935060608701519150808685030160808701525062004372838262003e64565b925050608085015160a085015260a08501516200439360c086018215159052565b5060c085015180151560e08601525060e0850151620043b58286018262003697565b5090949350505050565b6020815281516020820152602082015160408201526040820151606082015260ff60608301511660808201526000608083015160a0808401526200368f60c084018262003e64565b805182526020908101511515910152565b6200442582825162004407565b602081015162004439604084018262004407565b5060408101516200444e608084018262004407565b5060608101516200446360c084018262004407565b505050565b60208152600082516102806020840152620044886102a084018262003e64565b90506020840151601f1980858403016040860152620044a8838362003e64565b9250604086015191508085840301606086015250620044c8828262003e64565b9150506060840151620044e0608085018260ff169052565b50608084015160a084015260a084015160c084015260c08401516200450960e085018262003697565b5060e0840151610100620045208186018362003697565b8501519050610120620045368582018362004418565b85015180516001600160a01b039081166102208701526020820151166102408601526040810151610260860152606081015161028086015290505b509392505050565b60038110620033ad57634e487b7160e01b600052602160045260246000fd5b60006060808301606084528087518083526080925060808601915060808160051b8701016020808b016000805b858110156200465c578a8503607f19018752825180516001600160a01b03168652848101518a870190620045f98162004579565b878701526040918201519187018b90528151908190529085019083908a8801905b80831015620046465783516001600160e01b03191682529287019260019290920191908701906200461a565b50988601989650505091830191600101620045c5565b5050506200466d8189018b62003697565b50868103604088015262004682818962003e64565b9a9950505050505050505050565b81516001600160a01b0390811682526020808401518216908301526040808401519091169082015260608083015190820152608082015160a0820190620046d78162004579565b8060808401525092915050565b602081526000825160e060208401526200470361010084018262003e64565b90506020840151601f198085840301604086015262004723838362003e64565b9250604086015191508085840301606086015262004742838362003e64565b925060608601519150808584030160808601525062004762828262003e64565b9150506080840151151560a084015260a08401516200478560c085018215159052565b5060c08401516200457160e08501826200369756fe608060405260405161120b38038061120b83398101604081905261002291610dc2565b61002b82610136565b604080516001808252818301909252600091816020015b604080516060808201835260008083526020830152918101919091528152602001906001900390816100425750506040805160018082528183019092529192506000919060208083019080368337019050509050631f931c1c60e01b816000815181106100b1576100b1610df5565b6001600160e01b031990921660209283029190910182015260408051606081019091526001600160a01b038516815290810160008152602001828152508260008151811061010157610101610df5565b602002602001018190525061012d8260006040518060200160405280600081525061019660201b60201c565b505050506110e0565b60006101406103b4565b6004810180546001600160a01b038581166001600160a01b031983168117909355604051939450169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60005b83518110156103695760008482815181106101b6576101b6610df5565b6020026020010151602001519050600060028111156101d7576101d7610e0b565b8160028111156101e9576101e9610e0b565b0361023d5761023885838151811061020357610203610df5565b60200260200101516000015186848151811061022157610221610df5565b6020026020010151604001516103d860201b60201c565b610360565b600181600281111561025157610251610e0b565b036102a05761023885838151811061026b5761026b610df5565b60200260200101516000015186848151811061028957610289610df5565b60200260200101516040015161055560201b60201c565b60028160028111156102b4576102b4610e0b565b03610303576102388583815181106102ce576102ce610df5565b6020026020010151600001518684815181106102ec576102ec610df5565b6020026020010151604001516106db60201b60201c565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b60648201526084015b60405180910390fd5b50600101610199565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb67383838360405161039d93929190610e71565b60405180910390a16103af82826107f2565b505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c90565b60008151116103f95760405162461bcd60e51b815260040161035790610f74565b60006104036103b4565b90506001600160a01b03831661042b5760405162461bcd60e51b815260040161035790610fbf565b6001600160a01b0383166000908152600182016020526040812054906001600160601b03821690036104615761046182856108b8565b60005b835181101561054e57600084828151811061048157610481610df5565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b031680156105275760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f60448201527f6e207468617420616c72656164792065786973747300000000000000000000006064820152608401610357565b6105338583868a610922565b8361053d81611021565b945050600190920191506104649050565b5050505050565b60008151116105765760405162461bcd60e51b815260040161035790610f74565b60006105806103b4565b90506001600160a01b0383166105a85760405162461bcd60e51b815260040161035790610fbf565b6001600160a01b0383166000908152600182016020526040812054906001600160601b03821690036105de576105de82856108b8565b60005b835181101561054e5760008482815181106105fe576105fe610df5565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b0390811690871681036106a95760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e00000000000000006064820152608401610357565b6106b48582846109c2565b6106c08583868a610922565b836106ca81611021565b945050600190920191506105e19050565b60008151116106fc5760405162461bcd60e51b815260040161035790610f74565b60006107066103b4565b90506001600160a01b038316156107855760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f7665206661636574206164647260448201527f657373206d7573742062652061646472657373283029000000000000000000006064820152608401610357565b60005b82518110156107ec5760008382815181106107a5576107a5610df5565b6020908102919091018101516001600160e01b031981166000908152918590526040909120549091506001600160a01b03166107e28482846109c2565b5050600101610788565b50505050565b6001600160a01b038216610804575050565b610826826040518060600160405280602881526020016111bf60289139610d85565b600080836001600160a01b031683604051610841919061104f565b600060405180830381855af49150503d806000811461087c576040519150601f19603f3d011682016040523d82523d6000602084013e610881565b606091505b5091509150816107ec5780511561089b5780518082602001fd5b838360405163192105d760e01b815260040161035792919061106b565b6108da816040518060600160405280602481526020016111e760249139610d85565b6002820180546001600160a01b0390921660008181526001948501602090815260408220860185905594840183559182529290200180546001600160a01b0319169091179055565b6001600160e01b0319831660008181526020868152604080832080546001600160601b03909716600160a01b026001600160a01b0397881617815594909516808352600180890183529583208054968701815583528183206008870401805460e09890981c60046007909816979097026101000a96870263ffffffff9097021990971695909517909555529290915281546001600160a01b031916179055565b6001600160a01b038216610a3e5760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e27742065786973740000000000000000006064820152608401610357565b306001600160a01b03831603610aad5760405162461bcd60e51b815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201526d3a30b1363290333ab731ba34b7b760911b6064820152608401610357565b6001600160e01b03198116600090815260208481526040808320546001600160a01b0386168452600180880190935290832054600160a01b9091046001600160601b03169291610afc91611097565b9050808214610bee576001600160a01b03841660009081526001860160205260408120805483908110610b3157610b31610df5565b600091825260208083206008830401546001600160a01b038916845260018a019091526040909220805460079092166004026101000a90920460e01b925082919085908110610b8257610b82610df5565b600091825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b03199290921682528690526040902080546001600160a01b0316600160a01b6001600160601b038516021790555b6001600160a01b03841660009081526001860160205260409020805480610c1757610c176110b0565b60008281526020808220600860001990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b0319851682528690526040812081905581900361054e576002850154600090610c7a90600190611097565b6001600160a01b0386166000908152600180890160205260409091200154909150808214610d29576000876002018381548110610cb957610cb9610df5565b6000918252602090912001546002890180546001600160a01b039092169250829184908110610cea57610cea610df5565b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152600189810190925260409020018190555b86600201805480610d3c57610d3c6110b0565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0388168252600189810190915260408220015550505050505050565b813b81816107ec5760405162461bcd60e51b815260040161035791906110c6565b80516001600160a01b0381168114610dbd57600080fd5b919050565b60008060408385031215610dd557600080fd5b610dde83610da6565b9150610dec60208401610da6565b90509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b60005b83811015610e3c578181015183820152602001610e24565b50506000910152565b60008151808452610e5d816020860160208601610e21565b601f01601f19169290920160200192915050565b60006060808301606084528087518083526080925060808601915060808160051b8701016020808b0160005b84811015610f4457898403607f19018652815180516001600160a01b03168552838101518986019060038110610ee357634e487b7160e01b600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b80831015610f2f5783516001600160e01b0319168252928601926001929092019190860190610f05565b50978501979550505090820190600101610e9d565b50506001600160a01b038a16908801528681036040880152610f668189610e45565b9a9950505050505050505050565b6020808252602b908201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660408201526a1858d95d081d1bc818dd5d60aa1b606082015260800190565b6020808252602c908201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260408201526b65206164647265737328302960a01b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b60006001600160601b038281166002600160601b031981016110455761104561100b565b6001019392505050565b60008251611061818460208701610e21565b9190910192915050565b6001600160a01b038316815260406020820181905260009061108f90830184610e45565b949350505050565b818103818111156110aa576110aa61100b565b92915050565b634e487b7160e01b600052603160045260246000fd5b6020815260006110d96020830184610e45565b9392505050565b60d1806110ee6000396000f3fe608060405236600a57005b600080356001600160e01b03191681527fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c602081905260409091205481906001600160a01b03168060a15760405162461bcd60e51b815260206004820181905260248201527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f74206578697374604482015260640160405180910390fd5b3660008037600080366000845af43d6000803e80801560bf573d6000f35b3d6000fdfea164736f6c6343000817000a4c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a204e657720666163657420686173206e6f20636f6465ca16e7727e34eddfd016efc2c74be18308b7e9d9c361f0e67d4167ec00bcb635d7d8b7014b7ed36eb085c9e3e427b642d74cab75ecefda8a757042e63ec59919a164736f6c6343000817000a

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

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