Sepolia Testnet

Token

Silks Horse V2 (SILKS_HORSE_V2)
ERC-721

Overview

Max Total Supply

433 SILKS_HORSE_V2

Holders

30

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-
Balance
83 SILKS_HORSE_V2
0xadc1280cd6459e3480a79664bc54c5e6e5136012
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
SilksHorseDiamond

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
No with 200 runs

Other Settings:
paris EvmVersion
File 1 of 51 : SilksHorseDiamond.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

// Importing necessary libraries and contracts
import { AccessControlInternal } from "@solidstate/contracts/access/access_control/AccessControlInternal.sol";
import { AccessControlStorage } from "@solidstate/contracts/access/access_control/AccessControlStorage.sol";
import { ERC2981 } from "@solidstate/contracts/token/common/ERC2981/ERC2981.sol";
import { ERC2981Storage } from "@solidstate/contracts/token/common/ERC2981/ERC2981Storage.sol";
import { ERC721MetadataStorage } from "@solidstate/contracts/token/ERC721/metadata/ERC721MetadataStorage.sol";
import { PausableInternal } from "@solidstate/contracts/security/pausable/PausableInternal.sol";
import { SolidStateDiamond } from "@solidstate/contracts/proxy/diamond/SolidStateDiamond.sol";

// Import custom library
import "./libraries/LibSilksHorseDiamond.sol";

/**
 * @title SilksHorseDiamond
 * @dev A Solidity smart contract representing a Diamond upgradeable NFT (ERC721) with additional features.
 */
contract SilksHorseDiamond is
    AccessControlInternal,
    ERC2981,
    PausableInternal,
    SolidStateDiamond
{
    using AccessControlStorage for AccessControlStorage.Layout;
    
    /**
     * @dev Constructor for initializing the SilksHorseDiamond contract.
     * @param _contractOwner The address of the contract owner.
     * @param _tokenName The name of the NFT token.
     * @param _tokenSymbol The symbol of the NFT token.
     * @param _tokenBaseURI The base URI for metadata of NFTs.
     * @param _royaltyReceiver The address that receives royalties from NFT sales.
     * @param _royaltyBasePoints The base points (0-10000) for calculating royalties.
     * @param _seasonInfos Array of season info objects to use for initialization
     * @param _payoutTiers Array of pay out tier objects to use for initialization
     */
    constructor(
        address _contractOwner,
        string memory _tokenName,
        string memory _tokenSymbol,
        string memory _tokenBaseURI,
        uint256 _startTokenId,
        address _royaltyReceiver,
        uint16 _royaltyBasePoints,
        uint256 _maxHorsesPerWallet,
        SeasonInfo[] memory _seasonInfos,
        PayoutTier[] memory _payoutTiers
    )
    SolidStateDiamond()
    {
        // Setting metadata for the NFT
        ERC721MetadataStorage.layout().name = _tokenName;
        ERC721MetadataStorage.layout().symbol = _tokenSymbol;
        ERC721MetadataStorage.layout().baseURI = _tokenBaseURI;
        
        // Setting default royalty information
        ERC2981Storage.layout().defaultRoyaltyReceiver = _royaltyReceiver;
        ERC2981Storage.layout().defaultRoyaltyBPS = _royaltyBasePoints;
        
        // Setting the contract owner and pausing the contract initially
        _setOwner(_contractOwner);
        _pause();
        
        // Granting roles to the contract owner
        _grantRole(AccessControlStorage.DEFAULT_ADMIN_ROLE, _contractOwner);
        
        // Defining and granting admin roles for the contract
        _setRoleAdmin(CONTRACT_ADMIN_ROLE, AccessControlStorage.DEFAULT_ADMIN_ROLE);
        _grantRole(CONTRACT_ADMIN_ROLE, _contractOwner);
        
        // Defining and granting admin roles for minting NFTs
        _setRoleAdmin(MINT_ADMIN_ROLE, AccessControlStorage.DEFAULT_ADMIN_ROLE);
        _grantRole(MINT_ADMIN_ROLE, _contractOwner);
    
        LibSilksHorseDiamond.Layout storage lsh = LibSilksHorseDiamond.layout();
        lsh.nextAvailableTokenId = _startTokenId;
        lsh.maxHorsesPerWallet = _maxHorsesPerWallet;
        for (uint256 i = 0; i < _seasonInfos.length; i++){
            lsh.seasonInfos[_seasonInfos[i].seasonId] = _seasonInfos[i];
        }
        
        for (uint256 i = 0; i < _payoutTiers.length; i++){
            lsh.payoutTiers[_payoutTiers[i].tierId] = _payoutTiers[i];
        }
    }
}

File 2 of 51 : AccessControlInternal.sol
// 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 3 of 51 : 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
        }
    }
}

File 4 of 51 : 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
    );
}

File 5 of 51 : IOwnable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IERC173 } from '../../interfaces/IERC173.sol';
import { IOwnableInternal } from './IOwnableInternal.sol';

interface IOwnable is IOwnableInternal, IERC173 {}

File 6 of 51 : IOwnableInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

interface IOwnableInternal is IERC173Internal {
    error Ownable__NotOwner();
    error Ownable__NotTransitiveOwner();
}

File 7 of 51 : ISafeOwnable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IOwnable } from './IOwnable.sol';
import { ISafeOwnableInternal } from './ISafeOwnableInternal.sol';

interface ISafeOwnable is ISafeOwnableInternal, IOwnable {
    /**
     * @notice get the nominated owner who has permission to call acceptOwnership
     */
    function nomineeOwner() external view returns (address);

    /**
     * @notice accept transfer of contract ownership
     */
    function acceptOwnership() external;
}

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

pragma solidity ^0.8.8;

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

interface ISafeOwnableInternal is IOwnableInternal {
    error SafeOwnable__NotNomineeOwner();
}

File 9 of 51 : Ownable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IERC173 } from '../../interfaces/IERC173.sol';
import { IOwnable } from './IOwnable.sol';
import { OwnableInternal } from './OwnableInternal.sol';

/**
 * @title Ownership access control based on ERC173
 */
abstract contract Ownable is IOwnable, OwnableInternal {
    /**
     * @inheritdoc IERC173
     */
    function owner() public view virtual returns (address) {
        return _owner();
    }

    /**
     * @inheritdoc IERC173
     */
    function transferOwnership(address account) public virtual onlyOwner {
        _transferOwnership(account);
    }
}

File 10 of 51 : OwnableInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IERC173 } from '../../interfaces/IERC173.sol';
import { AddressUtils } from '../../utils/AddressUtils.sol';
import { IOwnableInternal } from './IOwnableInternal.sol';
import { OwnableStorage } from './OwnableStorage.sol';

abstract contract OwnableInternal is IOwnableInternal {
    using AddressUtils for address;

    modifier onlyOwner() {
        if (msg.sender != _owner()) revert Ownable__NotOwner();
        _;
    }

    modifier onlyTransitiveOwner() {
        if (msg.sender != _transitiveOwner())
            revert Ownable__NotTransitiveOwner();
        _;
    }

    function _owner() internal view virtual returns (address) {
        return OwnableStorage.layout().owner;
    }

    function _transitiveOwner() internal view virtual returns (address owner) {
        owner = _owner();

        while (owner.isContract()) {
            try IERC173(owner).owner() returns (address transitiveOwner) {
                owner = transitiveOwner;
            } catch {
                break;
            }
        }
    }

    function _transferOwnership(address account) internal virtual {
        _setOwner(account);
    }

    function _setOwner(address account) internal virtual {
        OwnableStorage.Layout storage l = OwnableStorage.layout();
        emit OwnershipTransferred(l.owner, account);
        l.owner = account;
    }
}

File 11 of 51 : OwnableStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

library OwnableStorage {
    struct Layout {
        address owner;
    }

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

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

File 12 of 51 : SafeOwnable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { Ownable } from './Ownable.sol';
import { ISafeOwnable } from './ISafeOwnable.sol';
import { OwnableInternal } from './OwnableInternal.sol';
import { SafeOwnableInternal } from './SafeOwnableInternal.sol';

/**
 * @title Ownership access control based on ERC173 with ownership transfer safety check
 */
abstract contract SafeOwnable is ISafeOwnable, Ownable, SafeOwnableInternal {
    /**
     * @inheritdoc ISafeOwnable
     */
    function nomineeOwner() public view virtual returns (address) {
        return _nomineeOwner();
    }

    /**
     * @inheritdoc ISafeOwnable
     */
    function acceptOwnership() public virtual onlyNomineeOwner {
        _acceptOwnership();
    }

    function _transferOwnership(
        address account
    ) internal virtual override(OwnableInternal, SafeOwnableInternal) {
        super._transferOwnership(account);
    }
}

File 13 of 51 : SafeOwnableInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { ISafeOwnableInternal } from './ISafeOwnableInternal.sol';
import { OwnableInternal } from './OwnableInternal.sol';
import { SafeOwnableStorage } from './SafeOwnableStorage.sol';

abstract contract SafeOwnableInternal is ISafeOwnableInternal, OwnableInternal {
    modifier onlyNomineeOwner() {
        if (msg.sender != _nomineeOwner())
            revert SafeOwnable__NotNomineeOwner();
        _;
    }

    /**
     * @notice get the nominated owner who has permission to call acceptOwnership
     */
    function _nomineeOwner() internal view virtual returns (address) {
        return SafeOwnableStorage.layout().nomineeOwner;
    }

    /**
     * @notice accept transfer of contract ownership
     */
    function _acceptOwnership() internal virtual {
        _setOwner(msg.sender);
        delete SafeOwnableStorage.layout().nomineeOwner;
    }

    /**
     * @notice grant permission to given address to claim contract ownership
     */
    function _transferOwnership(address account) internal virtual override {
        _setNomineeOwner(account);
    }

    /**
     * @notice set nominee owner
     */
    function _setNomineeOwner(address account) internal virtual {
        SafeOwnableStorage.layout().nomineeOwner = account;
    }
}

File 14 of 51 : SafeOwnableStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

library SafeOwnableStorage {
    struct Layout {
        address nomineeOwner;
    }

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

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

File 15 of 51 : EnumerableSet.sol
// 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;
        }
    }
}

File 16 of 51 : IERC165.sol
// 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 17 of 51 : IERC165Internal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

}

File 18 of 51 : IERC173.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

/**
 * @title Contract ownership standard interface
 * @dev see https://eips.ethereum.org/EIPS/eip-173
 */
interface IERC173 is IERC173Internal {
    /**
     * @notice get the ERC173 contract owner
     * @return contract owner
     */
    function owner() external view returns (address);

    /**
     * @notice transfer contract ownership to new account
     * @param account address of new owner
     */
    function transferOwnership(address account) external;
}

File 19 of 51 : IERC173Internal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

/**
 * @title Partial ERC173 interface needed by internal functions
 */
interface IERC173Internal {
    event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
    );
}

File 20 of 51 : IERC2981.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

/**
 * @title ERC2981 interface
 * @dev see https://eips.ethereum.org/EIPS/eip-2981
 */
interface IERC2981 is IERC2981Internal, IERC165 {
    /**
     * @notice called with the sale price to determine how much royalty is owed and to whom
     * @param tokenId the ERC721 or ERC1155 token id to query for royalty information
     * @param salePrice the sale price of the given asset
     * @return receiever rightful recipient of royalty
     * @return royaltyAmount amount of royalty owed
     */
    function royaltyInfo(
        uint256 tokenId,
        uint256 salePrice
    ) external view returns (address receiever, uint256 royaltyAmount);
}

File 21 of 51 : IERC2981Internal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

/**
 * @title ERC2981 interface
 */
interface IERC2981Internal {

}

File 22 of 51 : ERC165Base.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IERC165 } from '../../../interfaces/IERC165.sol';
import { IERC165Base } from './IERC165Base.sol';
import { ERC165BaseInternal } from './ERC165BaseInternal.sol';
import { ERC165BaseStorage } from './ERC165BaseStorage.sol';

/**
 * @title ERC165 implementation
 */
abstract contract ERC165Base is IERC165Base, ERC165BaseInternal {
    /**
     * @inheritdoc IERC165
     */
    function supportsInterface(bytes4 interfaceId) public view returns (bool) {
        return _supportsInterface(interfaceId);
    }
}

File 23 of 51 : ERC165BaseInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IERC165BaseInternal } from './IERC165BaseInternal.sol';
import { ERC165BaseStorage } from './ERC165BaseStorage.sol';

/**
 * @title ERC165 implementation
 */
abstract contract ERC165BaseInternal is IERC165BaseInternal {
    /**
     * @notice indicates whether an interface is already supported based on the interfaceId
     * @param interfaceId id of interface to check
     * @return bool indicating whether interface is supported
     */
    function _supportsInterface(
        bytes4 interfaceId
    ) internal view virtual returns (bool) {
        return ERC165BaseStorage.layout().supportedInterfaces[interfaceId];
    }

    /**
     * @notice sets status of interface support
     * @param interfaceId id of interface to set status for
     * @param status boolean indicating whether interface will be set as supported
     */
    function _setSupportsInterface(
        bytes4 interfaceId,
        bool status
    ) internal virtual {
        if (interfaceId == 0xffffffff) revert ERC165Base__InvalidInterfaceId();
        ERC165BaseStorage.layout().supportedInterfaces[interfaceId] = status;
    }
}

File 24 of 51 : ERC165BaseStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

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

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

File 25 of 51 : IERC165Base.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC165 } from '../../../interfaces/IERC165.sol';
import { IERC165BaseInternal } from './IERC165BaseInternal.sol';

interface IERC165Base is IERC165, IERC165BaseInternal {}

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

pragma solidity ^0.8.0;

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

interface IERC165BaseInternal is IERC165Internal {
    error ERC165Base__InvalidInterfaceId();
}

File 27 of 51 : DiamondBase.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { Proxy } from '../../Proxy.sol';
import { IDiamondBase } from './IDiamondBase.sol';
import { DiamondBaseStorage } from './DiamondBaseStorage.sol';

/**
 * @title EIP-2535 "Diamond" proxy base contract
 * @dev see https://eips.ethereum.org/EIPS/eip-2535
 */
abstract contract DiamondBase is IDiamondBase, Proxy {
    /**
     * @inheritdoc Proxy
     */
    function _getImplementation()
        internal
        view
        virtual
        override
        returns (address implementation)
    {
        // inline storage layout retrieval uses less gas
        DiamondBaseStorage.Layout storage l;
        bytes32 slot = DiamondBaseStorage.STORAGE_SLOT;
        assembly {
            l.slot := slot
        }

        implementation = address(bytes20(l.facets[msg.sig]));
    }
}

File 28 of 51 : DiamondBaseStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

/**
 * @dev derived from https://github.com/mudgen/diamond-2 (MIT license)
 */
library DiamondBaseStorage {
    struct Layout {
        // function selector => (facet address, selector slot position)
        mapping(bytes4 => bytes32) facets;
        // total number of selectors registered
        uint16 selectorCount;
        // array of selector slots with 8 selectors per slot
        mapping(uint256 => bytes32) selectorSlots;
        address fallbackAddress;
    }

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

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

File 29 of 51 : IDiamondBase.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

interface IDiamondBase is IProxy {}

File 30 of 51 : DiamondFallback.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { OwnableInternal } from '../../../access/ownable/OwnableInternal.sol';
import { DiamondBase } from '../base/DiamondBase.sol';
import { DiamondBaseStorage } from '../base/DiamondBaseStorage.sol';
import { IDiamondFallback } from './IDiamondFallback.sol';

/**
 * @title Fallback feature for EIP-2535 "Diamond" proxy
 */
abstract contract DiamondFallback is
    IDiamondFallback,
    OwnableInternal,
    DiamondBase
{
    /**
     * @inheritdoc IDiamondFallback
     */
    function getFallbackAddress()
        external
        view
        returns (address fallbackAddress)
    {
        fallbackAddress = _getFallbackAddress();
    }

    /**
     * @inheritdoc IDiamondFallback
     */
    function setFallbackAddress(address fallbackAddress) external onlyOwner {
        _setFallbackAddress(fallbackAddress);
    }

    /**
     * @inheritdoc DiamondBase
     * @notice query custom fallback address is no implementation is found
     */
    function _getImplementation()
        internal
        view
        virtual
        override
        returns (address implementation)
    {
        implementation = super._getImplementation();

        if (implementation == address(0)) {
            implementation = _getFallbackAddress();
        }
    }

    /**
     * @notice query the address of the fallback implementation
     * @return fallbackAddress address of fallback implementation
     */
    function _getFallbackAddress()
        internal
        view
        virtual
        returns (address fallbackAddress)
    {
        fallbackAddress = DiamondBaseStorage.layout().fallbackAddress;
    }

    /**
     * @notice set the address of the fallback implementation
     * @param fallbackAddress address of fallback implementation
     */
    function _setFallbackAddress(address fallbackAddress) internal virtual {
        DiamondBaseStorage.layout().fallbackAddress = fallbackAddress;
    }
}

File 31 of 51 : IDiamondFallback.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

interface IDiamondFallback is IDiamondBase {
    /**
     * @notice query the address of the fallback implementation
     * @return fallbackAddress address of fallback implementation
     */
    function getFallbackAddress()
        external
        view
        returns (address fallbackAddress);

    /**
     * @notice set the address of the fallback implementation
     * @param fallbackAddress address of fallback implementation
     */
    function setFallbackAddress(address fallbackAddress) external;
}

File 32 of 51 : ISolidStateDiamond.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { ISafeOwnable } from '../../access/ownable/ISafeOwnable.sol';
import { IERC165 } from '../../interfaces/IERC165.sol';
import { IDiamondBase } from './base/IDiamondBase.sol';
import { IDiamondFallback } from './fallback/IDiamondFallback.sol';
import { IDiamondReadable } from './readable/IDiamondReadable.sol';
import { IDiamondWritable } from './writable/IDiamondWritable.sol';

interface ISolidStateDiamond is
    IDiamondBase,
    IDiamondFallback,
    IDiamondReadable,
    IDiamondWritable,
    ISafeOwnable,
    IERC165
{
    receive() external payable;
}

File 33 of 51 : DiamondReadable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { DiamondBaseStorage } from '../base/DiamondBaseStorage.sol';
import { IDiamondReadable } from './IDiamondReadable.sol';

/**
 * @title EIP-2535 "Diamond" proxy introspection contract
 * @dev derived from https://github.com/mudgen/diamond-2 (MIT license)
 */
abstract contract DiamondReadable is IDiamondReadable {
    /**
     * @inheritdoc IDiamondReadable
     */
    function facets() external view returns (Facet[] memory diamondFacets) {
        DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout();

        diamondFacets = new Facet[](l.selectorCount);

        uint8[] memory numFacetSelectors = new uint8[](l.selectorCount);
        uint256 numFacets;
        uint256 selectorIndex;

        // loop through function selectors
        for (uint256 slotIndex; selectorIndex < l.selectorCount; slotIndex++) {
            bytes32 slot = l.selectorSlots[slotIndex];

            for (
                uint256 selectorSlotIndex;
                selectorSlotIndex < 8;
                selectorSlotIndex++
            ) {
                selectorIndex++;

                if (selectorIndex > l.selectorCount) {
                    break;
                }

                bytes4 selector = bytes4(slot << (selectorSlotIndex << 5));
                address facet = address(bytes20(l.facets[selector]));

                bool continueLoop;

                for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) {
                    if (diamondFacets[facetIndex].target == facet) {
                        diamondFacets[facetIndex].selectors[
                            numFacetSelectors[facetIndex]
                        ] = selector;
                        // probably will never have more than 256 functions from one facet contract
                        require(numFacetSelectors[facetIndex] < 255);
                        numFacetSelectors[facetIndex]++;
                        continueLoop = true;
                        break;
                    }
                }

                if (continueLoop) {
                    continue;
                }

                diamondFacets[numFacets].target = facet;
                diamondFacets[numFacets].selectors = new bytes4[](
                    l.selectorCount
                );
                diamondFacets[numFacets].selectors[0] = selector;
                numFacetSelectors[numFacets] = 1;
                numFacets++;
            }
        }

        for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) {
            uint256 numSelectors = numFacetSelectors[facetIndex];
            bytes4[] memory selectors = diamondFacets[facetIndex].selectors;

            // setting the number of selectors
            assembly {
                mstore(selectors, numSelectors)
            }
        }

        // setting the number of facets
        assembly {
            mstore(diamondFacets, numFacets)
        }
    }

    /**
     * @inheritdoc IDiamondReadable
     */
    function facetFunctionSelectors(
        address facet
    ) external view returns (bytes4[] memory selectors) {
        DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout();

        selectors = new bytes4[](l.selectorCount);

        uint256 numSelectors;
        uint256 selectorIndex;

        // loop through function selectors
        for (uint256 slotIndex; selectorIndex < l.selectorCount; slotIndex++) {
            bytes32 slot = l.selectorSlots[slotIndex];

            for (
                uint256 selectorSlotIndex;
                selectorSlotIndex < 8;
                selectorSlotIndex++
            ) {
                selectorIndex++;

                if (selectorIndex > l.selectorCount) {
                    break;
                }

                bytes4 selector = bytes4(slot << (selectorSlotIndex << 5));

                if (facet == address(bytes20(l.facets[selector]))) {
                    selectors[numSelectors] = selector;
                    numSelectors++;
                }
            }
        }

        // set the number of selectors in the array
        assembly {
            mstore(selectors, numSelectors)
        }
    }

    /**
     * @inheritdoc IDiamondReadable
     */
    function facetAddresses()
        external
        view
        returns (address[] memory addresses)
    {
        DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout();

        addresses = new address[](l.selectorCount);
        uint256 numFacets;
        uint256 selectorIndex;

        for (uint256 slotIndex; selectorIndex < l.selectorCount; slotIndex++) {
            bytes32 slot = l.selectorSlots[slotIndex];

            for (
                uint256 selectorSlotIndex;
                selectorSlotIndex < 8;
                selectorSlotIndex++
            ) {
                selectorIndex++;

                if (selectorIndex > l.selectorCount) {
                    break;
                }

                bytes4 selector = bytes4(slot << (selectorSlotIndex << 5));
                address facet = address(bytes20(l.facets[selector]));

                bool continueLoop;

                for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) {
                    if (facet == addresses[facetIndex]) {
                        continueLoop = true;
                        break;
                    }
                }

                if (continueLoop) {
                    continue;
                }

                addresses[numFacets] = facet;
                numFacets++;
            }
        }

        // set the number of facet addresses in the array
        assembly {
            mstore(addresses, numFacets)
        }
    }

    /**
     * @inheritdoc IDiamondReadable
     */
    function facetAddress(
        bytes4 selector
    ) external view returns (address facet) {
        facet = address(bytes20(DiamondBaseStorage.layout().facets[selector]));
    }
}

File 34 of 51 : IDiamondReadable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

/**
 * @title Diamond proxy introspection interface
 * @dev see https://eips.ethereum.org/EIPS/eip-2535
 */
interface IDiamondReadable {
    struct Facet {
        address target;
        bytes4[] selectors;
    }

    /**
     * @notice get all facets and their selectors
     * @return diamondFacets array of structured facet data
     */
    function facets() external view returns (Facet[] memory diamondFacets);

    /**
     * @notice get all selectors for given facet address
     * @param facet address of facet to query
     * @return selectors array of function selectors
     */
    function facetFunctionSelectors(
        address facet
    ) external view returns (bytes4[] memory selectors);

    /**
     * @notice get addresses of all facets used by diamond
     * @return addresses array of facet addresses
     */
    function facetAddresses()
        external
        view
        returns (address[] memory addresses);

    /**
     * @notice get the address of the facet associated with given selector
     * @param selector function selector to query
     * @return facet facet address (zero address if not found)
     */
    function facetAddress(
        bytes4 selector
    ) external view returns (address facet);
}

File 35 of 51 : SolidStateDiamond.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IOwnable, Ownable, OwnableInternal } from '../../access/ownable/Ownable.sol';
import { ISafeOwnable, SafeOwnable } from '../../access/ownable/SafeOwnable.sol';
import { IERC165 } from '../../interfaces/IERC165.sol';
import { IERC173 } from '../../interfaces/IERC173.sol';
import { ERC165Base, ERC165BaseStorage } from '../../introspection/ERC165/base/ERC165Base.sol';
import { DiamondBase } from './base/DiamondBase.sol';
import { DiamondFallback, IDiamondFallback } from './fallback/DiamondFallback.sol';
import { DiamondReadable, IDiamondReadable } from './readable/DiamondReadable.sol';
import { DiamondWritable, IDiamondWritable } from './writable/DiamondWritable.sol';
import { ISolidStateDiamond } from './ISolidStateDiamond.sol';

/**
 * @title SolidState "Diamond" proxy reference implementation
 */
abstract contract SolidStateDiamond is
    ISolidStateDiamond,
    DiamondBase,
    DiamondFallback,
    DiamondReadable,
    DiamondWritable,
    SafeOwnable,
    ERC165Base
{
    constructor() {
        bytes4[] memory selectors = new bytes4[](12);
        uint256 selectorIndex;

        // register DiamondFallback

        selectors[selectorIndex++] = IDiamondFallback
            .getFallbackAddress
            .selector;
        selectors[selectorIndex++] = IDiamondFallback
            .setFallbackAddress
            .selector;

        _setSupportsInterface(type(IDiamondFallback).interfaceId, true);

        // register DiamondWritable

        selectors[selectorIndex++] = IDiamondWritable.diamondCut.selector;

        _setSupportsInterface(type(IDiamondWritable).interfaceId, true);

        // register DiamondReadable

        selectors[selectorIndex++] = IDiamondReadable.facets.selector;
        selectors[selectorIndex++] = IDiamondReadable
            .facetFunctionSelectors
            .selector;
        selectors[selectorIndex++] = IDiamondReadable.facetAddresses.selector;
        selectors[selectorIndex++] = IDiamondReadable.facetAddress.selector;

        _setSupportsInterface(type(IDiamondReadable).interfaceId, true);

        // register ERC165

        selectors[selectorIndex++] = IERC165.supportsInterface.selector;

        _setSupportsInterface(type(IERC165).interfaceId, true);

        // register SafeOwnable

        selectors[selectorIndex++] = Ownable.owner.selector;
        selectors[selectorIndex++] = SafeOwnable.nomineeOwner.selector;
        selectors[selectorIndex++] = Ownable.transferOwnership.selector;
        selectors[selectorIndex++] = SafeOwnable.acceptOwnership.selector;

        _setSupportsInterface(type(IERC173).interfaceId, true);

        // diamond cut

        FacetCut[] memory facetCuts = new FacetCut[](1);

        facetCuts[0] = FacetCut({
            target: address(this),
            action: FacetCutAction.ADD,
            selectors: selectors
        });

        _diamondCut(facetCuts, address(0), '');

        // set owner

        _setOwner(msg.sender);
    }

    receive() external payable {}

    function _transferOwnership(
        address account
    ) internal virtual override(OwnableInternal, SafeOwnable) {
        super._transferOwnership(account);
    }

    /**
     * @inheritdoc DiamondFallback
     */
    function _getImplementation()
        internal
        view
        override(DiamondBase, DiamondFallback)
        returns (address implementation)
    {
        implementation = super._getImplementation();
    }
}

File 36 of 51 : DiamondWritable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { OwnableInternal } from '../../../access/ownable/OwnableInternal.sol';
import { IDiamondWritable } from './IDiamondWritable.sol';
import { DiamondWritableInternal } from './DiamondWritableInternal.sol';

/**
 * @title EIP-2535 "Diamond" proxy update contract
 */
abstract contract DiamondWritable is
    IDiamondWritable,
    DiamondWritableInternal,
    OwnableInternal
{
    /**
     * @inheritdoc IDiamondWritable
     */
    function diamondCut(
        FacetCut[] calldata facetCuts,
        address target,
        bytes calldata data
    ) external onlyOwner {
        _diamondCut(facetCuts, target, data);
    }
}

File 37 of 51 : DiamondWritableInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { AddressUtils } from '../../../utils/AddressUtils.sol';
import { DiamondBaseStorage } from '../base/DiamondBaseStorage.sol';
import { IDiamondWritableInternal } from './IDiamondWritableInternal.sol';

abstract contract DiamondWritableInternal is IDiamondWritableInternal {
    using AddressUtils for address;

    bytes32 private constant CLEAR_ADDRESS_MASK =
        bytes32(uint256(0xffffffffffffffffffffffff));
    bytes32 private constant CLEAR_SELECTOR_MASK =
        bytes32(uint256(0xffffffff << 224));

    /**
     * @notice update functions callable on Diamond proxy
     * @param facetCuts array of structured Diamond facet update data
     * @param target optional recipient of initialization delegatecall
     * @param data optional initialization call data
     */
    function _diamondCut(
        FacetCut[] memory facetCuts,
        address target,
        bytes memory data
    ) internal virtual {
        DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout();

        unchecked {
            uint256 originalSelectorCount = l.selectorCount;
            uint256 selectorCount = originalSelectorCount;
            bytes32 selectorSlot;

            // Check if last selector slot is not full
            if (selectorCount & 7 > 0) {
                // get last selectorSlot
                selectorSlot = l.selectorSlots[selectorCount >> 3];
            }

            for (uint256 i; i < facetCuts.length; i++) {
                FacetCut memory facetCut = facetCuts[i];
                FacetCutAction action = facetCut.action;

                if (facetCut.selectors.length == 0)
                    revert DiamondWritable__SelectorNotSpecified();

                if (action == FacetCutAction.ADD) {
                    (selectorCount, selectorSlot) = _addFacetSelectors(
                        l,
                        selectorCount,
                        selectorSlot,
                        facetCut
                    );
                } else if (action == FacetCutAction.REPLACE) {
                    _replaceFacetSelectors(l, facetCut);
                } else if (action == FacetCutAction.REMOVE) {
                    (selectorCount, selectorSlot) = _removeFacetSelectors(
                        l,
                        selectorCount,
                        selectorSlot,
                        facetCut
                    );
                }
            }

            if (selectorCount != originalSelectorCount) {
                l.selectorCount = uint16(selectorCount);
            }

            // If last selector slot is not full
            if (selectorCount & 7 > 0) {
                l.selectorSlots[selectorCount >> 3] = selectorSlot;
            }

            emit DiamondCut(facetCuts, target, data);
            _initialize(target, data);
        }
    }

    function _addFacetSelectors(
        DiamondBaseStorage.Layout storage l,
        uint256 selectorCount,
        bytes32 selectorSlot,
        FacetCut memory facetCut
    ) internal returns (uint256, bytes32) {
        unchecked {
            if (
                facetCut.target != address(this) &&
                !facetCut.target.isContract()
            ) revert DiamondWritable__TargetHasNoCode();

            for (uint256 i; i < facetCut.selectors.length; i++) {
                bytes4 selector = facetCut.selectors[i];
                bytes32 oldFacet = l.facets[selector];

                if (address(bytes20(oldFacet)) != address(0))
                    revert DiamondWritable__SelectorAlreadyAdded();

                // add facet for selector
                l.facets[selector] =
                    bytes20(facetCut.target) |
                    bytes32(selectorCount);
                uint256 selectorInSlotPosition = (selectorCount & 7) << 5;

                // clear selector position in slot and add selector
                selectorSlot =
                    (selectorSlot &
                        ~(CLEAR_SELECTOR_MASK >> selectorInSlotPosition)) |
                    (bytes32(selector) >> selectorInSlotPosition);

                // if slot is full then write it to storage
                if (selectorInSlotPosition == 224) {
                    l.selectorSlots[selectorCount >> 3] = selectorSlot;
                    selectorSlot = 0;
                }

                selectorCount++;
            }

            return (selectorCount, selectorSlot);
        }
    }

    function _removeFacetSelectors(
        DiamondBaseStorage.Layout storage l,
        uint256 selectorCount,
        bytes32 selectorSlot,
        FacetCut memory facetCut
    ) internal returns (uint256, bytes32) {
        unchecked {
            if (facetCut.target != address(0))
                revert DiamondWritable__RemoveTargetNotZeroAddress();

            uint256 selectorSlotCount = selectorCount >> 3;
            uint256 selectorInSlotIndex = selectorCount & 7;

            for (uint256 i; i < facetCut.selectors.length; i++) {
                bytes4 selector = facetCut.selectors[i];
                bytes32 oldFacet = l.facets[selector];

                if (address(bytes20(oldFacet)) == address(0))
                    revert DiamondWritable__SelectorNotFound();

                if (address(bytes20(oldFacet)) == address(this))
                    revert DiamondWritable__SelectorIsImmutable();

                if (selectorSlot == 0) {
                    selectorSlotCount--;
                    selectorSlot = l.selectorSlots[selectorSlotCount];
                    selectorInSlotIndex = 7;
                } else {
                    selectorInSlotIndex--;
                }

                bytes4 lastSelector;
                uint256 oldSelectorsSlotCount;
                uint256 oldSelectorInSlotPosition;

                // adding a block here prevents stack too deep error
                {
                    // replace selector with last selector in l.facets
                    lastSelector = bytes4(
                        selectorSlot << (selectorInSlotIndex << 5)
                    );

                    if (lastSelector != selector) {
                        // update last selector slot position info
                        l.facets[lastSelector] =
                            (oldFacet & CLEAR_ADDRESS_MASK) |
                            bytes20(l.facets[lastSelector]);
                    }

                    delete l.facets[selector];
                    uint256 oldSelectorCount = uint16(uint256(oldFacet));
                    oldSelectorsSlotCount = oldSelectorCount >> 3;
                    oldSelectorInSlotPosition = (oldSelectorCount & 7) << 5;
                }

                if (oldSelectorsSlotCount != selectorSlotCount) {
                    bytes32 oldSelectorSlot = l.selectorSlots[
                        oldSelectorsSlotCount
                    ];

                    // clears the selector we are deleting and puts the last selector in its place.
                    oldSelectorSlot =
                        (oldSelectorSlot &
                            ~(CLEAR_SELECTOR_MASK >>
                                oldSelectorInSlotPosition)) |
                        (bytes32(lastSelector) >> oldSelectorInSlotPosition);

                    // update storage with the modified slot
                    l.selectorSlots[oldSelectorsSlotCount] = oldSelectorSlot;
                } else {
                    // clears the selector we are deleting and puts the last selector in its place.
                    selectorSlot =
                        (selectorSlot &
                            ~(CLEAR_SELECTOR_MASK >>
                                oldSelectorInSlotPosition)) |
                        (bytes32(lastSelector) >> oldSelectorInSlotPosition);
                }

                if (selectorInSlotIndex == 0) {
                    delete l.selectorSlots[selectorSlotCount];
                    selectorSlot = 0;
                }
            }

            selectorCount = (selectorSlotCount << 3) | selectorInSlotIndex;

            return (selectorCount, selectorSlot);
        }
    }

    function _replaceFacetSelectors(
        DiamondBaseStorage.Layout storage l,
        FacetCut memory facetCut
    ) internal {
        unchecked {
            if (!facetCut.target.isContract())
                revert DiamondWritable__TargetHasNoCode();

            for (uint256 i; i < facetCut.selectors.length; i++) {
                bytes4 selector = facetCut.selectors[i];
                bytes32 oldFacet = l.facets[selector];
                address oldFacetAddress = address(bytes20(oldFacet));

                if (oldFacetAddress == address(0))
                    revert DiamondWritable__SelectorNotFound();
                if (oldFacetAddress == address(this))
                    revert DiamondWritable__SelectorIsImmutable();
                if (oldFacetAddress == facetCut.target)
                    revert DiamondWritable__ReplaceTargetIsIdentical();

                // replace old facet address
                l.facets[selector] =
                    (oldFacet & CLEAR_ADDRESS_MASK) |
                    bytes20(facetCut.target);
            }
        }
    }

    function _initialize(address target, bytes memory data) private {
        if ((target == address(0)) != (data.length == 0))
            revert DiamondWritable__InvalidInitializationParameters();

        if (target != address(0)) {
            if (target != address(this)) {
                if (!target.isContract())
                    revert DiamondWritable__TargetHasNoCode();
            }

            (bool success, ) = target.delegatecall(data);

            if (!success) {
                assembly {
                    returndatacopy(0, 0, returndatasize())
                    revert(0, returndatasize())
                }
            }
        }
    }
}

File 38 of 51 : IDiamondWritable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

/**
 * @title Diamond proxy upgrade interface
 * @dev see https://eips.ethereum.org/EIPS/eip-2535
 */
interface IDiamondWritable is IDiamondWritableInternal {
    /**
     * @notice update diamond facets and optionally execute arbitrary initialization function
     * @param facetCuts array of structured Diamond facet update data
     * @param target optional target of initialization delegatecall
     * @param data optional initialization function call data
     */
    function diamondCut(
        FacetCut[] calldata facetCuts,
        address target,
        bytes calldata data
    ) external;
}

File 39 of 51 : IDiamondWritableInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

interface IDiamondWritableInternal {
    enum FacetCutAction {
        ADD,
        REPLACE,
        REMOVE
    }

    event DiamondCut(FacetCut[] facetCuts, address target, bytes data);

    error DiamondWritable__InvalidInitializationParameters();
    error DiamondWritable__RemoveTargetNotZeroAddress();
    error DiamondWritable__ReplaceTargetIsIdentical();
    error DiamondWritable__SelectorAlreadyAdded();
    error DiamondWritable__SelectorIsImmutable();
    error DiamondWritable__SelectorNotFound();
    error DiamondWritable__SelectorNotSpecified();
    error DiamondWritable__TargetHasNoCode();

    struct FacetCut {
        address target;
        FacetCutAction action;
        bytes4[] selectors;
    }
}

File 40 of 51 : IProxy.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

interface IProxy {
    error Proxy__ImplementationIsNotContract();

    fallback() external payable;
}

File 41 of 51 : Proxy.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { AddressUtils } from '../utils/AddressUtils.sol';
import { IProxy } from './IProxy.sol';

/**
 * @title Base proxy contract
 */
abstract contract Proxy is IProxy {
    using AddressUtils for address;

    /**
     * @notice delegate all calls to implementation contract
     * @dev reverts if implementation address contains no code, for compatibility with metamorphic contracts
     * @dev memory location in use by assembly may be unsafe in other contexts
     */
    fallback() external payable virtual {
        address implementation = _getImplementation();

        if (!implementation.isContract())
            revert Proxy__ImplementationIsNotContract();

        assembly {
            calldatacopy(0, 0, calldatasize())
            let result := delegatecall(
                gas(),
                implementation,
                0,
                calldatasize(),
                0,
                0
            )
            returndatacopy(0, 0, returndatasize())

            switch result
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    /**
     * @notice get logic implementation address
     * @return implementation address
     */
    function _getImplementation() internal virtual returns (address);
}

File 42 of 51 : 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 43 of 51 : PausableInternal.sol
// 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 44 of 51 : 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 45 of 51 : ERC2981.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

import { ERC2981Storage } from './ERC2981Storage.sol';
import { ERC2981Internal } from './ERC2981Internal.sol';

/**
 * @title ERC2981 implementation
 */
abstract contract ERC2981 is IERC2981, ERC2981Internal {
    /**
     * @notice inheritdoc IERC2981
     */
    function royaltyInfo(
        uint256 tokenId,
        uint256 salePrice
    ) external view returns (address, uint256) {
        return _royaltyInfo(tokenId, salePrice);
    }
}

File 46 of 51 : ERC2981Internal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { ERC2981Storage } from './ERC2981Storage.sol';
import { IERC2981Internal } from '../../../interfaces/IERC2981Internal.sol';

/**
 * @title ERC2981 internal functions
 */
abstract contract ERC2981Internal is IERC2981Internal {
    /**
     * @notice calculate how much royalty is owed and to whom
     * @dev royalty must be paid in addition to, rather than deducted from, salePrice
     * @param tokenId the ERC721 or ERC1155 token id to query for royalty information
     * @param salePrice the sale price of the given asset
     * @return royaltyReceiver rightful recipient of royalty
     * @return royalty amount of royalty owed
     */
    function _royaltyInfo(
        uint256 tokenId,
        uint256 salePrice
    ) internal view virtual returns (address royaltyReceiver, uint256 royalty) {
        uint256 royaltyBPS = _getRoyaltyBPS(tokenId);

        // intermediate multiplication overflow is theoretically possible here, but
        // not an issue in practice because of practical constraints of salePrice
        return (_getRoyaltyReceiver(tokenId), (royaltyBPS * salePrice) / 10000);
    }

    /**
     * @notice query the royalty rate (denominated in basis points) for given token id
     * @dev implementation supports per-token-id values as well as a global default
     * @param tokenId token whose royalty rate to query
     * @return royaltyBPS royalty rate
     */
    function _getRoyaltyBPS(
        uint256 tokenId
    ) internal view virtual returns (uint16 royaltyBPS) {
        ERC2981Storage.Layout storage l = ERC2981Storage.layout();
        royaltyBPS = l.royaltiesBPS[tokenId];

        if (royaltyBPS == 0) {
            royaltyBPS = l.defaultRoyaltyBPS;
        }
    }

    /**
     * @notice query the royalty receiver for given token id
     * @dev implementation supports per-token-id values as well as a global default
     * @param tokenId token whose royalty receiver to query
     * @return royaltyReceiver royalty receiver
     */
    function _getRoyaltyReceiver(
        uint256 tokenId
    ) internal view virtual returns (address royaltyReceiver) {
        ERC2981Storage.Layout storage l = ERC2981Storage.layout();
        royaltyReceiver = l.royaltyReceivers[tokenId];

        if (royaltyReceiver == address(0)) {
            royaltyReceiver = l.defaultRoyaltyReceiver;
        }
    }
}

File 47 of 51 : ERC2981Storage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

library ERC2981Storage {
    struct Layout {
        // token id -> royalty (denominated in basis points)
        mapping(uint256 => uint16) royaltiesBPS;
        uint16 defaultRoyaltyBPS;
        // token id -> receiver address
        mapping(uint256 => address) royaltyReceivers;
        address defaultRoyaltyReceiver;
    }

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

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

File 48 of 51 : ERC721MetadataStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

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

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

File 49 of 51 : AddressUtils.sol
// 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);
        }
    }
}

File 50 of 51 : UintUtils.sol
// 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);
    }
}

File 51 of 51 : LibSilksHorseDiamond.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

import {EnumerableSet} from "@solidstate/contracts/data/EnumerableSet.sol";

struct SeasonInfo {
    uint256 seasonId;
    string description;
    bool paused;
    bool valid;
}

struct PayoutTier {
    uint256 tierId;
    string description;
    uint256 price;
    uint256 maxPerTx;
    uint256 payoutPct;
    uint256 maxSupply;
    bool paused;
    bool valid;
}

enum MintMethod {
    PURCHASE,
    AIRDROP,
    EXTERNAL_MINT
}

bytes32 constant CONTRACT_ADMIN_ROLE = keccak256("silks.contracts.roles.ContractAdminRole");
bytes32 constant MINT_ADMIN_ROLE = keccak256("silks.contracts.roles.MintAdminRole");

bytes32 constant HORSE_PURCHASING_PAUSED = keccak256('silks.contracts.paused.HorsePurchasing');

error InvalidAddress(address _address);
error InvalidSeason(uint256 _sent);
error InvalidPayoutTier(uint256 _sent);
error InvalidTokenId(uint256 _sent);
error InvalidIntValue(string _reason, uint256 _sent, uint256 _expected);
error InvalidStringValue(string _reason, string _sent, string _expected);
error InvalidExternalMintAddress(address _sender);
error MaxHorsesPerWalletExceeded(address _walletAddress);
error PayoutTierMaxSupplyExceeded(uint256 _payoutTier);
error MintFailed(string _reason, uint256 _seasonId, uint256 _payoutTier, uint256 _quantity, MintMethod _method, address _to);

library LibSilksHorseDiamond {
    bytes32 internal constant STORAGE_SLOT = keccak256('silks.contracts.storage.SilksHorseDiamond');
    
    struct Layout {
        mapping(uint256 => EnumerableSet.UintSet) seasonHorses;
        mapping(uint256 => SeasonInfo) seasonInfos;
        mapping(uint256 => PayoutTier) payoutTiers;
        mapping(uint256 => PayoutTier) horsePayoutTier;
        mapping(uint256 => EnumerableSet.UintSet) payoutTierHorses;
        mapping(uint256 => SeasonInfo) horseSeasonInfo;
        mapping(address => bool) allowedExternalMintAddresses;
        uint256 maxHorsesPerWallet;
        uint256 nextAvailableTokenId;
    }
    
    function layout()
    internal
    pure
    returns (
        Layout storage l
    ) {
        bytes32 slot = STORAGE_SLOT;
        assembly {
            l.slot := slot
        }
    }
}

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

Contract ABI

[{"inputs":[{"internalType":"address","name":"_contractOwner","type":"address"},{"internalType":"string","name":"_tokenName","type":"string"},{"internalType":"string","name":"_tokenSymbol","type":"string"},{"internalType":"string","name":"_tokenBaseURI","type":"string"},{"internalType":"uint256","name":"_startTokenId","type":"uint256"},{"internalType":"address","name":"_royaltyReceiver","type":"address"},{"internalType":"uint16","name":"_royaltyBasePoints","type":"uint16"},{"internalType":"uint256","name":"_maxHorsesPerWallet","type":"uint256"},{"components":[{"internalType":"uint256","name":"seasonId","type":"uint256"},{"internalType":"string","name":"description","type":"string"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"valid","type":"bool"}],"internalType":"struct SeasonInfo[]","name":"_seasonInfos","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"tierId","type":"uint256"},{"internalType":"string","name":"description","type":"string"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"maxPerTx","type":"uint256"},{"internalType":"uint256","name":"payoutPct","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"valid","type":"bool"}],"internalType":"struct PayoutTier[]","name":"_payoutTiers","type":"tuple[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DiamondWritable__InvalidInitializationParameters","type":"error"},{"inputs":[],"name":"DiamondWritable__RemoveTargetNotZeroAddress","type":"error"},{"inputs":[],"name":"DiamondWritable__ReplaceTargetIsIdentical","type":"error"},{"inputs":[],"name":"DiamondWritable__SelectorAlreadyAdded","type":"error"},{"inputs":[],"name":"DiamondWritable__SelectorIsImmutable","type":"error"},{"inputs":[],"name":"DiamondWritable__SelectorNotFound","type":"error"},{"inputs":[],"name":"DiamondWritable__SelectorNotSpecified","type":"error"},{"inputs":[],"name":"DiamondWritable__TargetHasNoCode","type":"error"},{"inputs":[],"name":"ERC165Base__InvalidInterfaceId","type":"error"},{"inputs":[],"name":"Ownable__NotOwner","type":"error"},{"inputs":[],"name":"Ownable__NotTransitiveOwner","type":"error"},{"inputs":[],"name":"Pausable__NotPaused","type":"error"},{"inputs":[],"name":"Pausable__Paused","type":"error"},{"inputs":[],"name":"Proxy__ImplementationIsNotContract","type":"error"},{"inputs":[],"name":"SafeOwnable__NotNomineeOwner","type":"error"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"enum IDiamondWritableInternal.FacetCutAction","name":"action","type":"uint8"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"indexed":false,"internalType":"struct IDiamondWritableInternal.FacetCut[]","name":"facetCuts","type":"tuple[]"},{"indexed":false,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"DiamondCut","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"enum IDiamondWritableInternal.FacetCutAction","name":"action","type":"uint8"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"internalType":"struct IDiamondWritableInternal.FacetCut[]","name":"facetCuts","type":"tuple[]"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"diamondCut","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"facetAddress","outputs":[{"internalType":"address","name":"facet","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"facetAddresses","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"facet","type":"address"}],"name":"facetFunctionSelectors","outputs":[{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"facets","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"internalType":"struct IDiamondReadable.Facet[]","name":"diamondFacets","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackAddress","outputs":[{"internalType":"address","name":"fallbackAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nomineeOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"fallbackAddress","type":"address"}],"name":"setFallbackAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60806040523480156200001157600080fd5b50604051620063de380380620063de8339818101604052810190620000379190620027a0565b6000600c67ffffffffffffffff811115620000575762000056620021e6565b5b604051908082528060200260200182016040528015620000865781602001602082028036833780820191505090505b5090506000632c40805960e01b828280620000a19062002960565b935081518110620000b757620000b6620029ad565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525050639142376560e01b828280620001199062002960565b9350815181106200012f576200012e620029ad565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525050620001ae7fbd02b73c00000000000000000000000000000000000000000000000000000000600162000c3060201b60201c565b631f931c1c60e01b828280620001c49062002960565b935081518110620001da57620001d9620029ad565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525050620002597f1f931c1c00000000000000000000000000000000000000000000000000000000600162000c3060201b60201c565b637a0ed62760e01b8282806200026f9062002960565b935081518110620002855762000284620029ad565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152505063adfca15e60e01b828280620002e79062002960565b935081518110620002fd57620002fc620029ad565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815250506352ef6b2c60e01b8282806200035f9062002960565b935081518110620003755762000374620029ad565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152505063cdffacc660e01b828280620003d79062002960565b935081518110620003ed57620003ec620029ad565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815250506200046c7f48e2b09300000000000000000000000000000000000000000000000000000000600162000c3060201b60201c565b6301ffc9a760e01b828280620004829062002960565b935081518110620004985762000497620029ad565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525050620005177f01ffc9a700000000000000000000000000000000000000000000000000000000600162000c3060201b60201c565b638da5cb5b60e01b8282806200052d9062002960565b935081518110620005435762000542620029ad565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525050638ab5150a60e01b828280620005a59062002960565b935081518110620005bb57620005ba620029ad565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152505063f2fde38b60e01b8282806200061d9062002960565b935081518110620006335762000632620029ad565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815250506379ba509760e01b828280620006959062002960565b935081518110620006ab57620006aa620029ad565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815250506200072a7f7f5828d000000000000000000000000000000000000000000000000000000000600162000c3060201b60201c565b6000600167ffffffffffffffff8111156200074a5762000749620021e6565b5b6040519080825280602002602001820160405280156200078757816020015b6200077362002106565b815260200190600190039081620007695790505b50905060405180606001604052803073ffffffffffffffffffffffffffffffffffffffff16815260200160006002811115620007c857620007c7620029dc565b5b81526020018481525081600081518110620007e857620007e7620029ad565b5b6020026020010181905250620008168160006040518060200160405280600081525062000d0e60201b60201c565b620008273362000f9360201b60201c565b505050886200083b6200106c60201b60201c565b60000190816200084c919062002c4c565b50876200085e6200106c60201b60201c565b60010190816200086f919062002c4c565b5086620008816200106c60201b60201c565b600201908162000892919062002c4c565b5084620008a46200109960201b60201c565b60030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083620008f66200109960201b60201c565b60010160006101000a81548161ffff021916908361ffff160217905550620009248a62000f9360201b60201c565b62000934620010c660201b60201c565b620009496000801b8b6200117560201b60201c565b6200097e7f76493909ee513f9bd866a75497a2b0a2713f973b0c77556dbe5dcc1473dcc0136000801b6200121060201b60201c565b620009b07f76493909ee513f9bd866a75497a2b0a2713f973b0c77556dbe5dcc1473dcc0138b6200117560201b60201c565b620009e57f7dc7a9428f8cc2d7d0a73dfc0f0d4791fa005321ee0ba5d966a60588b12e576c6000801b6200121060201b60201c565b62000a177f7dc7a9428f8cc2d7d0a73dfc0f0d4791fa005321ee0ba5d966a60588b12e576c8b6200117560201b60201c565b600062000a296200128560201b60201c565b905086816008018190555083816007018190555060005b835181101562000b195783818151811062000a605762000a5f620029ad565b5b602002602001015182600101600086848151811062000a845762000a83620029ad565b5b602002602001015160000151815260200190815260200160002060008201518160000155602082015181600101908162000abf919062002c4c565b5060408201518160020160006101000a81548160ff02191690831515021790555060608201518160020160016101000a81548160ff021916908315150217905550905050808062000b109062002960565b91505062000a40565b5060005b825181101562000c1e5782818151811062000b3d5762000b3c620029ad565b5b602002602001015182600201600085848151811062000b615762000b60620029ad565b5b602002602001015160000151815260200190815260200160002060008201518160000155602082015181600101908162000b9c919062002c4c565b5060408201518160020155606082015181600301556080820151816004015560a0820151816005015560c08201518160060160006101000a81548160ff02191690831515021790555060e08201518160060160016101000a81548160ff021916908315150217905550905050808062000c159062002960565b91505062000b1d565b505050505050505050505050620030e6565b63ffffffff60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160362000c90576040517fb0a19dd500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8062000ca1620012b260201b60201c565b6000016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b600062000d20620012df60201b60201c565b905060008160010160009054906101000a900461ffff1661ffff169050600081905060008060078316111562000d6d57836002016000600384901c81526020019081526020016000205490505b60005b875181101562000ee657600088828151811062000d925762000d91620029ad565b5b6020026020010151905060008160200151905060008260400151510362000de5576040517feb6c3aeb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600281111562000dfc5762000dfb620029dc565b5b81600281111562000e125762000e11620029dc565b5b0362000e3a5762000e2c878686856200130c60201b60201c565b809550819650505062000ed6565b6001600281111562000e515762000e50620029dc565b5b81600281111562000e675762000e66620029dc565b5b0362000e855762000e7f8783620015cf60201b60201c565b62000ed5565b60028081111562000e9b5762000e9a620029dc565b5b81600281111562000eb15762000eb0620029dc565b5b0362000ed45762000ecb878686856200189660201b60201c565b80955081965050505b5b5b5050808060010191505062000d70565b5082821462000f0f57818460010160006101000a81548161ffff021916908361ffff1602179055505b600060078316111562000f3b5780846002016000600385901c8152602001908152602001600020819055505b7f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb67387878760405162000f709392919062003023565b60405180910390a162000f8a868662001d8a60201b60201c565b50505050505050565b600062000fa562001f4860201b60201c565b90508173ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6000807f99574a7094154bb123ae6ae102096f0bf9679b85a5cd1e727aaa0ae5f132e6b190508091505090565b6000807ff298352fd56f58214bf2245c2b202523f72fca3199077ce992640958228b281f90508091505090565b620010d662001f7560201b60201c565b156200110e576040517f059519da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016200112062001f9d60201b60201c565b60000160006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258336040516200116b91906200306e565b60405180910390a1565b620011b0816200118a62001fca60201b60201c565b600001600085815260200190815260200160002060000162001ff760201b90919060201c565b503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600062001223836200202f60201b60201c565b9050816200123662001fca60201b60201c565b6000016000858152602001908152602001600020600201819055508181847fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff60405160405180910390a4505050565b6000807fa9766cf30247385bd274fe73461f870e9ad8351016f172911cfa198f44cc28e590508091505090565b6000807ffc606c433378e3a7e0a6a531deac289b66caa1b4aa8554fd4ab2c6f1570f92d890508091505090565b6000807f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc9390508091505090565b6000803073ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff161415801562001378575062001376836000015173ffffffffffffffffffffffffffffffffffffffff166200206060201b60201c565b155b15620013b0576040517ff77172ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b836040015151811015620015bf57600084604001518281518110620013dd57620013dc620029ad565b5b602002602001015190506000886000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020549050600073ffffffffffffffffffffffffffffffffffffffff168160601c73ffffffffffffffffffffffffffffffffffffffff1614620014a9576040517f92474ee200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760001b866000015160601b6bffffffffffffffffffffffff191617896000016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020819055506000600560078a16901b905080837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c817fffffffff0000000000000000000000000000000000000000000000000000000060001b901c19891617975060e08103620015a657878a600201600060038c901c8152602001908152602001600020819055506000801b97505b88806001019950505050508080600101915050620013b3565b5084849150915094509492505050565b620015fa816000015173ffffffffffffffffffffffffffffffffffffffff166200206060201b60201c565b62001631576040517ff77172ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81604001515181101562001891576000826040015182815181106200165e576200165d620029ad565b5b602002602001015190506000846000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002054905060008160601c9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036200172f576040517f6fc4b52e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160362001795576040517fe983573100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846000015173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620017ff576040517f617557e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846000015160601b6bffffffffffffffffffffffff19166bffffffffffffffffffffffff60001b831617866000016000857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002081905550505050808060010191505062001634565b505050565b600080600073ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff161462001904576040517feacd242400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600386901c9050600060078716905060005b85604001515181101562001d6f57600086604001518281518110620019425762001941620029ad565b5b6020026020010151905060008a6000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020549050600073ffffffffffffffffffffffffffffffffffffffff168160601c73ffffffffffffffffffffffffffffffffffffffff160362001a0e576040517f6fc4b52e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168160601c73ffffffffffffffffffffffffffffffffffffffff160362001a77576040517fe983573100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000801b890362001aad578480600190039550508a60020160008681526020019081526020016000205498506007935062001ab7565b8380600190039450505b6000806000600587901b8c901b9250847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161462001bda578d6000016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020546bffffffffffffffffffffffff19166bffffffffffffffffffffffff60001b8516178e6000016000857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020819055505b8d6000016000867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020016000206000905560008460001c61ffff169050600381901c9250600560078216901b91505087821462001ce25760008e600201600084815260200190815260200160002054905081847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c827fffffffff0000000000000000000000000000000000000000000000000000000060001b901c198216179050808f6002016000858152602001908152602001600020819055505062001d33565b80837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c817fffffffff0000000000000000000000000000000000000000000000000000000060001b901c198d16179b505b6000870362001d5c578d6002016000898152602001908152602001600020600090556000801b9b505b5050505050808060010191505062001918565b5080600383901b179650868693509350505094509492505050565b60008151141515600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415151462001dfb576040517f26df4ccd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161462001f44573073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161462001ec35762001e8b8273ffffffffffffffffffffffffffffffffffffffff166200206060201b60201c565b62001ec2576040517ff77172ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b60008273ffffffffffffffffffffffffffffffffffffffff168260405162001eec9190620030cd565b600060405180830381855af49150503d806000811462001f29576040519150601f19603f3d011682016040523d82523d6000602084013e62001f2e565b606091505b505090508062001f42573d6000803e3d6000fd5b505b5050565b6000807f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f67168046090508091505090565b600062001f8762001f9d60201b60201c565b60000160009054906101000a900460ff16905090565b6000807f68721c0bbf2c02a4d65000340d1370666be06a630022208d4baa9bd7a4b6fea890508091505090565b6000807fd3889cc5458b268d0544e5534672df1296288ca3f93cbd39bd6f497a5c62281190508091505090565b600062002027836000018373ffffffffffffffffffffffffffffffffffffffff1660001b6200207360201b60201c565b905092915050565b60006200204162001fca60201b60201c565b6000016000838152602001908152602001600020600201549050919050565b600080823b905060008111915050919050565b6000620020878383620020e360201b60201c565b620020dd5782600001829080600181540180825580915050600190039060005260206000200160009091909190915055826000018054905083600101600084815260200190815260200160002081905550600190505b92915050565b600080836001016000848152602001908152602001600020541415905092915050565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160006002811115620021455762002144620029dc565b5b8152602001606081525090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620021938262002166565b9050919050565b620021a58162002186565b8114620021b157600080fd5b50565b600081519050620021c5816200219a565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200222082620021d5565b810181811067ffffffffffffffff82111715620022425762002241620021e6565b5b80604052505050565b60006200225762002152565b905062002265828262002215565b919050565b600067ffffffffffffffff821115620022885762002287620021e6565b5b6200229382620021d5565b9050602081019050919050565b60005b83811015620022c0578082015181840152602081019050620022a3565b60008484015250505050565b6000620022e3620022dd846200226a565b6200224b565b905082815260208101848484011115620023025762002301620021d0565b5b6200230f848285620022a0565b509392505050565b600082601f8301126200232f576200232e620021cb565b5b815162002341848260208601620022cc565b91505092915050565b6000819050919050565b6200235f816200234a565b81146200236b57600080fd5b50565b6000815190506200237f8162002354565b92915050565b600061ffff82169050919050565b6200239e8162002385565b8114620023aa57600080fd5b50565b600081519050620023be8162002393565b92915050565b600067ffffffffffffffff821115620023e257620023e1620021e6565b5b602082029050602081019050919050565b600080fd5b600080fd5b600080fd5b60008115159050919050565b620024198162002402565b81146200242557600080fd5b50565b60008151905062002439816200240e565b92915050565b600060808284031215620024585762002457620023f8565b5b6200246460806200224b565b9050600062002476848285016200236e565b600083015250602082015167ffffffffffffffff8111156200249d576200249c620023fd565b5b620024ab8482850162002317565b6020830152506040620024c18482850162002428565b6040830152506060620024d78482850162002428565b60608301525092915050565b6000620024fa620024f484620023c4565b6200224b565b9050808382526020820190506020840283018581111562002520576200251f620023f3565b5b835b818110156200256e57805167ffffffffffffffff811115620025495762002548620021cb565b5b8086016200255889826200243f565b8552602085019450505060208101905062002522565b5050509392505050565b600082601f83011262002590576200258f620021cb565b5b8151620025a2848260208601620024e3565b91505092915050565b600067ffffffffffffffff821115620025c957620025c8620021e6565b5b602082029050602081019050919050565b60006101008284031215620025f457620025f3620023f8565b5b620026016101006200224b565b9050600062002613848285016200236e565b600083015250602082015167ffffffffffffffff8111156200263a5762002639620023fd565b5b620026488482850162002317565b60208301525060406200265e848285016200236e565b604083015250606062002674848285016200236e565b60608301525060806200268a848285016200236e565b60808301525060a0620026a0848285016200236e565b60a08301525060c0620026b68482850162002428565b60c08301525060e0620026cc8482850162002428565b60e08301525092915050565b6000620026ef620026e984620025ab565b6200224b565b90508083825260208201905060208402830185811115620027155762002714620023f3565b5b835b818110156200276357805167ffffffffffffffff8111156200273e576200273d620021cb565b5b8086016200274d8982620025da565b8552602085019450505060208101905062002717565b5050509392505050565b600082601f830112620027855762002784620021cb565b5b815162002797848260208601620026d8565b91505092915050565b6000806000806000806000806000806101408b8d031215620027c757620027c66200215c565b5b6000620027d78d828e01620021b4565b9a505060208b015167ffffffffffffffff811115620027fb57620027fa62002161565b5b620028098d828e0162002317565b99505060408b015167ffffffffffffffff8111156200282d576200282c62002161565b5b6200283b8d828e0162002317565b98505060608b015167ffffffffffffffff8111156200285f576200285e62002161565b5b6200286d8d828e0162002317565b9750506080620028808d828e016200236e565b96505060a0620028938d828e01620021b4565b95505060c0620028a68d828e01620023ad565b94505060e0620028b98d828e016200236e565b9350506101008b015167ffffffffffffffff811115620028de57620028dd62002161565b5b620028ec8d828e0162002578565b9250506101208b015167ffffffffffffffff81111562002911576200291062002161565b5b6200291f8d828e016200276d565b9150509295989b9194979a5092959850565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006200296d826200234a565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620029a257620029a162002931565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168062002a5e57607f821691505b60208210810362002a745762002a7362002a16565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b60006008830262002ade7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262002a9f565b62002aea868362002a9f565b95508019841693508086168417925050509392505050565b6000819050919050565b600062002b2d62002b2762002b21846200234a565b62002b02565b6200234a565b9050919050565b6000819050919050565b62002b498362002b0c565b62002b6162002b588262002b34565b84845462002aac565b825550505050565b600090565b62002b7862002b69565b62002b8581848462002b3e565b505050565b5b8181101562002bad5762002ba160008262002b6e565b60018101905062002b8b565b5050565b601f82111562002bfc5762002bc68162002a7a565b62002bd18462002a8f565b8101602085101562002be1578190505b62002bf962002bf08562002a8f565b83018262002b8a565b50505b505050565b600082821c905092915050565b600062002c216000198460080262002c01565b1980831691505092915050565b600062002c3c838362002c0e565b9150826002028217905092915050565b62002c578262002a0b565b67ffffffffffffffff81111562002c735762002c72620021e6565b5b62002c7f825462002a45565b62002c8c82828562002bb1565b600060209050601f83116001811462002cc4576000841562002caf578287015190505b62002cbb858262002c2e565b86555062002d2b565b601f19841662002cd48662002a7a565b60005b8281101562002cfe5784890151825560018201915060208501945060208101905062002cd7565b8683101562002d1e578489015162002d1a601f89168262002c0e565b8355505b6001600288020188555050505b505050505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b62002d6a8162002186565b82525050565b6003811062002d845762002d83620029dc565b5b50565b600081905062002d978262002d70565b919050565b600062002da98262002d87565b9050919050565b62002dbb8162002d9c565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b62002e248162002ded565b82525050565b600062002e38838362002e19565b60208301905092915050565b6000602082019050919050565b600062002e5e8262002dc1565b62002e6a818562002dcc565b935062002e778362002ddd565b8060005b8381101562002eae57815162002e92888262002e2a565b975062002e9f8362002e44565b92505060018101905062002e7b565b5085935050505092915050565b600060608301600083015162002ed5600086018262002d5f565b50602083015162002eea602086018262002db0565b506040830151848203604086015262002f04828262002e51565b9150508091505092915050565b600062002f1f838362002ebb565b905092915050565b6000602082019050919050565b600062002f418262002d33565b62002f4d818562002d3e565b93508360208202850162002f618562002d4f565b8060005b8581101562002fa3578484038952815162002f81858262002f11565b945062002f8e8362002f27565b925060208a0199505060018101905062002f65565b50829750879550505050505092915050565b62002fc08162002186565b82525050565b600081519050919050565b600082825260208201905092915050565b600062002fef8262002fc6565b62002ffb818562002fd1565b93506200300d818560208601620022a0565b6200301881620021d5565b840191505092915050565b600060608201905081810360008301526200303f818662002f34565b905062003050602083018562002fb5565b818103604083015262003064818462002fe2565b9050949350505050565b600060208201905062003085600083018462002fb5565b92915050565b600081905092915050565b6000620030a38262002fc6565b620030af81856200308b565b9350620030c1818560208601620022a0565b80840191505092915050565b6000620030db828462003096565b915081905092915050565b6132e880620030f66000396000f3fe6080604052600436106100c65760003560e01c80637a0ed6271161007f578063914237651161005957806391423765146102e6578063adfca15e1461030f578063cdffacc61461034c578063f2fde38b14610389576100cd565b80637a0ed627146102655780638ab5150a146102905780638da5cb5b146102bb576100cd565b806301ffc9a7146101545780631f931c1c146101915780632a55205a146101ba5780632c408059146101f857806352ef6b2c1461022357806379ba50971461024e576100cd565b366100cd57005b60006100d76103b2565b90506100f88173ffffffffffffffffffffffffffffffffffffffff166103c1565b61012e576040517f87c9fc3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3660008037600080366000845af43d6000803e806000811461014f573d6000f35b3d6000fd5b34801561016057600080fd5b5061017b60048036038101906101769190612568565b6103d4565b60405161018891906125b0565b60405180910390f35b34801561019d57600080fd5b506101b860048036038101906101b391906126e4565b6103e6565b005b3480156101c657600080fd5b506101e160048036038101906101dc91906127af565b6104b4565b6040516101ef92919061280d565b60405180910390f35b34801561020457600080fd5b5061020d6104cc565b60405161021a9190612836565b60405180910390f35b34801561022f57600080fd5b506102386104db565b604051610245919061290f565b60405180910390f35b34801561025a57600080fd5b5061026361073c565b005b34801561027157600080fd5b5061027a6107b2565b6040516102879190612aee565b60405180910390f35b34801561029c57600080fd5b506102a5610d13565b6040516102b29190612836565b60405180910390f35b3480156102c757600080fd5b506102d0610d22565b6040516102dd9190612836565b60405180910390f35b3480156102f257600080fd5b5061030d60048036038101906103089190612b10565b610d31565b005b34801561031b57600080fd5b5061033660048036038101906103319190612b10565b610da9565b6040516103439190612bac565b60405180910390f35b34801561035857600080fd5b50610373600480360381019061036e9190612568565b610fc6565b6040516103809190612836565b60405180910390f35b34801561039557600080fd5b506103b060048036038101906103ab9190612b10565b61102d565b005b60006103bc6110a5565b905090565b600080823b905060008111915050919050565b60006103df826110f3565b9050919050565b6103ee611164565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610452576040517f2f7a8ee100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104ad8585906104629190612e7f565b8484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611197565b5050505050565b6000806104c184846113d2565b915091509250929050565b60006104d6611414565b905090565b606060006104e7611447565b90508060010160009054906101000a900461ffff1661ffff1667ffffffffffffffff81111561051957610518612bdf565b5b6040519080825280602002602001820160405280156105475781602001602082028036833780820191505090505b50915060008060005b8360010160009054906101000a900461ffff1661ffff1682101561073257600084600201600083815260200190815260200160002054905060005b600881101561071d57838061059f90612ec3565b9450508560010160009054906101000a900461ffff1661ffff16841161071d576000600582901b83901b90506000876000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020016000205460601c90506000805b8881101561069b578a818151811061064557610644612f0b565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610688576001915061069b565b808061069390612ec3565b91505061062a565b5080156106aa5750505061070a565b818a89815181106106be576106bd612f0b565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050878061070390612ec3565b9850505050505b808061071590612ec3565b91505061058b565b5050808061072a90612ec3565b915050610550565b5081845250505090565b610744611474565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107a8576040517fefd1052d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107b06114a7565b565b606060006107be611447565b90508060010160009054906101000a900461ffff1661ffff1667ffffffffffffffff8111156107f0576107ef612bdf565b5b60405190808252806020026020018201604052801561082957816020015b6108166124cc565b81526020019060019003908161080e5790505b50915060008160010160009054906101000a900461ffff1661ffff1667ffffffffffffffff81111561085e5761085d612bdf565b5b60405190808252806020026020018201604052801561088c5781602001602082028036833780820191505090505b50905060008060005b8460010160009054906101000a900461ffff1661ffff16821015610c9f57600085600201600083815260200190815260200160002054905060005b6008811015610c8a5783806108e490612ec3565b9450508660010160009054906101000a900461ffff1661ffff168411610c8a576000600582901b83901b90506000886000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020016000205460601c90506000805b88811015610adb578273ffffffffffffffffffffffffffffffffffffffff168c82815181106109a1576109a0612f0b565b5b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1603610ac857838c82815181106109dc576109db612f0b565b5b6020026020010151602001518b83815181106109fb576109fa612f0b565b5b602002602001015160ff1681518110610a1757610a16612f0b565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152505060ff8a8281518110610a7857610a77612f0b565b5b602002602001015160ff1610610a8d57600080fd5b898181518110610aa057610a9f612f0b565b5b602002602001018051809190610ab590612f47565b60ff1660ff168152505060019150610adb565b8080610ad390612ec3565b91505061096f565b508015610aea57505050610c77565b818b8981518110610afe57610afd612f0b565b5b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508960010160009054906101000a900461ffff1661ffff1667ffffffffffffffff811115610b6c57610b6b612bdf565b5b604051908082528060200260200182016040528015610b9a5781602001602082028036833780820191505090505b508b8981518110610bae57610bad612f0b565b5b602002602001015160200181905250828b8981518110610bd157610bd0612f0b565b5b602002602001015160200151600081518110610bf057610bef612f0b565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815250506001898981518110610c5157610c50612f0b565b5b602002602001019060ff16908160ff16815250508780610c7090612ec3565b9850505050505b8080610c8290612ec3565b9150506108d0565b50508080610c9790612ec3565b915050610895565b5060005b82811015610d08576000848281518110610cc057610cbf612f0b565b5b602002602001015160ff1690506000878381518110610ce257610ce1612f0b565b5b602002602001015160200151905081815250508080610d0090612ec3565b915050610ca3565b508185525050505090565b6000610d1d611474565b905090565b6000610d2c611164565b905090565b610d39611164565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d9d576040517f2f7a8ee100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610da6816114e0565b50565b60606000610db5611447565b90508060010160009054906101000a900461ffff1661ffff1667ffffffffffffffff811115610de757610de6612bdf565b5b604051908082528060200260200182016040528015610e155781602001602082028036833780820191505090505b50915060008060005b8360010160009054906101000a900461ffff1661ffff16821015610fba57600084600201600083815260200190815260200160002054905060005b6008811015610fa5578380610e6d90612ec3565b9450508560010160009054906101000a900461ffff1661ffff168411610fa5576000600582901b83901b9050866000016000827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020016000205460601c73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1603610f915780888781518110610f3657610f35612f0b565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815250508580610f8d90612ec3565b9650505b508080610f9d90612ec3565b915050610e59565b50508080610fb290612ec3565b915050610e1e565b50818452505050919050565b6000610fd0611447565b6000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020016000205460601c9050919050565b611035611164565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611099576040517f2f7a8ee100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110a28161152d565b50565b60006110af611539565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036110f0576110ed611414565b90505b90565b60006110fd6115e5565b6000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff169050919050565b600061116e611612565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006111a1611447565b905060008160010160009054906101000a900461ffff1661ffff16905060008190506000806007831611156111ed57836002016000600384901c81526020019081526020016000205490505b60005b875181101561133157600088828151811061120e5761120d612f0b565b5b60200260200101519050600081602001519050600082604001515103611260576040517feb6c3aeb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600281111561127457611273612f70565b5b81600281111561128757611286612f70565b5b036112a5576112988786868561163f565b8095508196505050611322565b600160028111156112b9576112b8612f70565b5b8160028111156112cc576112cb612f70565b5b036112e0576112db87836118f1565b611321565b6002808111156112f3576112f2612f70565b5b81600281111561130657611305612f70565b5b036113205761131787868685611ba7565b80955081965050505b5b5b505080806001019150506111f0565b5082821461135957818460010160006101000a81548161ffff021916908361ffff1602179055505b60006007831611156113845780846002016000600385901c8152602001908152602001600020819055505b7f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6738787876040516113b793929190613178565b60405180910390a16113c9868661208d565b50505050505050565b60008060006113e08561223a565b61ffff1690506113ef85612295565b61271085836113fe91906131bd565b611408919061322e565b92509250509250929050565b600061141e611447565b60030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000807f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc9390508091505090565b600061147e61233c565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6114b033612369565b6114b861233c565b60000160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055565b806114e9611447565b60030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6115368161243a565b50565b60008060007f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc93905080915081600001600080357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020016000205460601c9250505090565b6000807ffc606c433378e3a7e0a6a531deac289b66caa1b4aa8554fd4ab2c6f1570f92d890508091505090565b6000807f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f67168046090508091505090565b6000803073ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff16141580156116a257506116a0836000015173ffffffffffffffffffffffffffffffffffffffff166103c1565b155b156116d9576040517ff77172ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8360400151518110156118e15760008460400151828151811061170257611701612f0b565b5b602002602001015190506000886000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020549050600073ffffffffffffffffffffffffffffffffffffffff168160601c73ffffffffffffffffffffffffffffffffffffffff16146117cd576040517f92474ee200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760001b866000015160601b6bffffffffffffffffffffffff191617896000016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020819055506000600560078a16901b905080837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c817fffffffff0000000000000000000000000000000000000000000000000000000060001b901c19891617975060e081036118c957878a600201600060038c901c8152602001908152602001600020819055506000801b97505b888060010199505050505080806001019150506116dc565b5084849150915094509492505050565b611914816000015173ffffffffffffffffffffffffffffffffffffffff166103c1565b61194a576040517ff77172ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b816040015151811015611ba25760008260400151828151811061197357611972612f0b565b5b602002602001015190506000846000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002054905060008160601c9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611a43576040517f6fc4b52e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611aa8576040517fe983573100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846000015173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611b11576040517f617557e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846000015160601b6bffffffffffffffffffffffff19166bffffffffffffffffffffffff60001b831617866000016000857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002081905550505050808060010191505061194d565b505050565b600080600073ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff1614611c14576040517feacd242400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600386901c9050600060078716905060005b85604001515181101561207257600086604001518281518110611c4e57611c4d612f0b565b5b6020026020010151905060008a6000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020549050600073ffffffffffffffffffffffffffffffffffffffff168160601c73ffffffffffffffffffffffffffffffffffffffff1603611d19576040517f6fc4b52e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168160601c73ffffffffffffffffffffffffffffffffffffffff1603611d81576040517fe983573100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000801b8903611db5578480600190039550508a600201600086815260200190815260200160002054985060079350611dbf565b8380600190039450505b6000806000600587901b8c901b9250847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611ee1578d6000016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020546bffffffffffffffffffffffff19166bffffffffffffffffffffffff60001b8516178e6000016000857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020819055505b8d6000016000867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020016000206000905560008460001c61ffff169050600381901c9250600560078216901b915050878214611fe75760008e600201600084815260200190815260200160002054905081847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c827fffffffff0000000000000000000000000000000000000000000000000000000060001b901c198216179050808f60020160008581526020019081526020016000208190555050612038565b80837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c817fffffffff0000000000000000000000000000000000000000000000000000000060001b901c198d16179b505b60008703612060578d6002016000898152602001908152602001600020600090556000801b9b505b50505050508080600101915050611c28565b5080600383901b179650868693509350505094509492505050565b60008151141515600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141515146120fd576040517f26df4ccd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614612236573073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146121ba576121838273ffffffffffffffffffffffffffffffffffffffff166103c1565b6121b9576040517ff77172ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b60008273ffffffffffffffffffffffffffffffffffffffff16826040516121e1919061329b565b600060405180830381855af49150503d806000811461221c576040519150601f19603f3d011682016040523d82523d6000602084013e612221565b606091505b5050905080612234573d6000803e3d6000fd5b505b5050565b600080612245612446565b905080600001600084815260200190815260200160002060009054906101000a900461ffff16915060008261ffff160361228f578060010160009054906101000a900461ffff1691505b50919050565b6000806122a0612446565b905080600201600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169150600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612336578060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505b50919050565b6000807f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce661789090508091505090565b6000612373611612565b90508173ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b61244381612473565b50565b6000807ff298352fd56f58214bf2245c2b202523f72fca3199077ce992640958228b281f90508091505090565b61247c8161247f565b50565b8061248861233c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61254581612510565b811461255057600080fd5b50565b6000813590506125628161253c565b92915050565b60006020828403121561257e5761257d612506565b5b600061258c84828501612553565b91505092915050565b60008115159050919050565b6125aa81612595565b82525050565b60006020820190506125c560008301846125a1565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126125f0576125ef6125cb565b5b8235905067ffffffffffffffff81111561260d5761260c6125d0565b5b602083019150836020820283011115612629576126286125d5565b5b9250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061265b82612630565b9050919050565b61266b81612650565b811461267657600080fd5b50565b60008135905061268881612662565b92915050565b60008083601f8401126126a4576126a36125cb565b5b8235905067ffffffffffffffff8111156126c1576126c06125d0565b5b6020830191508360018202830111156126dd576126dc6125d5565b5b9250929050565b600080600080600060608688031215612700576126ff612506565b5b600086013567ffffffffffffffff81111561271e5761271d61250b565b5b61272a888289016125da565b9550955050602061273d88828901612679565b935050604086013567ffffffffffffffff81111561275e5761275d61250b565b5b61276a8882890161268e565b92509250509295509295909350565b6000819050919050565b61278c81612779565b811461279757600080fd5b50565b6000813590506127a981612783565b92915050565b600080604083850312156127c6576127c5612506565b5b60006127d48582860161279a565b92505060206127e58582860161279a565b9150509250929050565b6127f881612650565b82525050565b61280781612779565b82525050565b600060408201905061282260008301856127ef565b61282f60208301846127fe565b9392505050565b600060208201905061284b60008301846127ef565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61288681612650565b82525050565b6000612898838361287d565b60208301905092915050565b6000602082019050919050565b60006128bc82612851565b6128c6818561285c565b93506128d18361286d565b8060005b838110156129025781516128e9888261288c565b97506128f4836128a4565b9250506001810190506128d5565b5085935050505092915050565b6000602082019050818103600083015261292981846128b1565b905092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61299281612510565b82525050565b60006129a48383612989565b60208301905092915050565b6000602082019050919050565b60006129c88261295d565b6129d28185612968565b93506129dd83612979565b8060005b83811015612a0e5781516129f58882612998565b9750612a00836129b0565b9250506001810190506129e1565b5085935050505092915050565b6000604083016000830151612a33600086018261287d565b5060208301518482036020860152612a4b82826129bd565b9150508091505092915050565b6000612a648383612a1b565b905092915050565b6000602082019050919050565b6000612a8482612931565b612a8e818561293c565b935083602082028501612aa08561294d565b8060005b85811015612adc5784840389528151612abd8582612a58565b9450612ac883612a6c565b925060208a01995050600181019050612aa4565b50829750879550505050505092915050565b60006020820190508181036000830152612b088184612a79565b905092915050565b600060208284031215612b2657612b25612506565b5b6000612b3484828501612679565b91505092915050565b600082825260208201905092915050565b6000612b598261295d565b612b638185612b3d565b9350612b6e83612979565b8060005b83811015612b9f578151612b868882612998565b9750612b91836129b0565b925050600181019050612b72565b5085935050505092915050565b60006020820190508181036000830152612bc68184612b4e565b905092915050565b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612c1782612bce565b810181811067ffffffffffffffff82111715612c3657612c35612bdf565b5b80604052505050565b6000612c496124fc565b9050612c558282612c0e565b919050565b600067ffffffffffffffff821115612c7557612c74612bdf565b5b602082029050602081019050919050565b600080fd5b600080fd5b60038110612c9d57600080fd5b50565b600081359050612caf81612c90565b92915050565b600067ffffffffffffffff821115612cd057612ccf612bdf565b5b602082029050602081019050919050565b6000612cf4612cef84612cb5565b612c3f565b90508083825260208201905060208402830185811115612d1757612d166125d5565b5b835b81811015612d405780612d2c8882612553565b845260208401935050602081019050612d19565b5050509392505050565b600082601f830112612d5f57612d5e6125cb565b5b8135612d6f848260208601612ce1565b91505092915050565b600060608284031215612d8e57612d8d612c86565b5b612d986060612c3f565b90506000612da884828501612679565b6000830152506020612dbc84828501612ca0565b602083015250604082013567ffffffffffffffff811115612de057612ddf612c8b565b5b612dec84828501612d4a565b60408301525092915050565b6000612e0b612e0684612c5a565b612c3f565b90508083825260208201905060208402830185811115612e2e57612e2d6125d5565b5b835b81811015612e7557803567ffffffffffffffff811115612e5357612e526125cb565b5b808601612e608982612d78565b85526020850194505050602081019050612e30565b5050509392505050565b6000612e8c368484612df8565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000612ece82612779565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612f0057612eff612e94565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff82169050919050565b6000612f5282612f3a565b915060ff8203612f6557612f64612e94565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60038110612fdc57612fdb612f70565b5b50565b6000819050612fed82612fcb565b919050565b6000612ffd82612fdf565b9050919050565b61300d81612ff2565b82525050565b600060608301600083015161302b600086018261287d565b50602083015161303e6020860182613004565b506040830151848203604086015261305682826129bd565b9150508091505092915050565b600061306f8383613013565b905092915050565b6000602082019050919050565b600061308f82612f9f565b6130998185612faa565b9350836020820285016130ab85612fbb565b8060005b858110156130e757848403895281516130c88582613063565b94506130d383613077565b925060208a019950506001810190506130af565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613133578082015181840152602081019050613118565b60008484015250505050565b600061314a826130f9565b6131548185613104565b9350613164818560208601613115565b61316d81612bce565b840191505092915050565b600060608201905081810360008301526131928186613084565b90506131a160208301856127ef565b81810360408301526131b3818461313f565b9050949350505050565b60006131c882612779565b91506131d383612779565b92508282026131e181612779565b915082820484148315176131f8576131f7612e94565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061323982612779565b915061324483612779565b925082613254576132536131ff565b5b828204905092915050565b600081905092915050565b6000613275826130f9565b61327f818561325f565b935061328f818560208601613115565b80840191505092915050565b60006132a7828461326a565b91508190509291505056fea2646970667358221220b873d44b7534267ad89dd57fcd9a804e732ba809b24c960573180d6dfe2dee7a64736f6c634300081400330000000000000000000000004ab88e00570b740c1c403034d05954584d6351d10000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000002041000000000000000000000000e1c689334186473db5027b5f9354596ccee546690000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000e53696c6b7320486f727365205632000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e53494c4b535f484f5253455f5632000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002568747470733a2f2f6e66742e6465762e73696c6b732e696f2f6d657461646174612f63312f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000007e8000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001753696c6b73203230323420486f72736520536561736f6e000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000005af3107a400000000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000c3120506374205061796f75740000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106100c65760003560e01c80637a0ed6271161007f578063914237651161005957806391423765146102e6578063adfca15e1461030f578063cdffacc61461034c578063f2fde38b14610389576100cd565b80637a0ed627146102655780638ab5150a146102905780638da5cb5b146102bb576100cd565b806301ffc9a7146101545780631f931c1c146101915780632a55205a146101ba5780632c408059146101f857806352ef6b2c1461022357806379ba50971461024e576100cd565b366100cd57005b60006100d76103b2565b90506100f88173ffffffffffffffffffffffffffffffffffffffff166103c1565b61012e576040517f87c9fc3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3660008037600080366000845af43d6000803e806000811461014f573d6000f35b3d6000fd5b34801561016057600080fd5b5061017b60048036038101906101769190612568565b6103d4565b60405161018891906125b0565b60405180910390f35b34801561019d57600080fd5b506101b860048036038101906101b391906126e4565b6103e6565b005b3480156101c657600080fd5b506101e160048036038101906101dc91906127af565b6104b4565b6040516101ef92919061280d565b60405180910390f35b34801561020457600080fd5b5061020d6104cc565b60405161021a9190612836565b60405180910390f35b34801561022f57600080fd5b506102386104db565b604051610245919061290f565b60405180910390f35b34801561025a57600080fd5b5061026361073c565b005b34801561027157600080fd5b5061027a6107b2565b6040516102879190612aee565b60405180910390f35b34801561029c57600080fd5b506102a5610d13565b6040516102b29190612836565b60405180910390f35b3480156102c757600080fd5b506102d0610d22565b6040516102dd9190612836565b60405180910390f35b3480156102f257600080fd5b5061030d60048036038101906103089190612b10565b610d31565b005b34801561031b57600080fd5b5061033660048036038101906103319190612b10565b610da9565b6040516103439190612bac565b60405180910390f35b34801561035857600080fd5b50610373600480360381019061036e9190612568565b610fc6565b6040516103809190612836565b60405180910390f35b34801561039557600080fd5b506103b060048036038101906103ab9190612b10565b61102d565b005b60006103bc6110a5565b905090565b600080823b905060008111915050919050565b60006103df826110f3565b9050919050565b6103ee611164565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610452576040517f2f7a8ee100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104ad8585906104629190612e7f565b8484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611197565b5050505050565b6000806104c184846113d2565b915091509250929050565b60006104d6611414565b905090565b606060006104e7611447565b90508060010160009054906101000a900461ffff1661ffff1667ffffffffffffffff81111561051957610518612bdf565b5b6040519080825280602002602001820160405280156105475781602001602082028036833780820191505090505b50915060008060005b8360010160009054906101000a900461ffff1661ffff1682101561073257600084600201600083815260200190815260200160002054905060005b600881101561071d57838061059f90612ec3565b9450508560010160009054906101000a900461ffff1661ffff16841161071d576000600582901b83901b90506000876000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020016000205460601c90506000805b8881101561069b578a818151811061064557610644612f0b565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610688576001915061069b565b808061069390612ec3565b91505061062a565b5080156106aa5750505061070a565b818a89815181106106be576106bd612f0b565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050878061070390612ec3565b9850505050505b808061071590612ec3565b91505061058b565b5050808061072a90612ec3565b915050610550565b5081845250505090565b610744611474565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107a8576040517fefd1052d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107b06114a7565b565b606060006107be611447565b90508060010160009054906101000a900461ffff1661ffff1667ffffffffffffffff8111156107f0576107ef612bdf565b5b60405190808252806020026020018201604052801561082957816020015b6108166124cc565b81526020019060019003908161080e5790505b50915060008160010160009054906101000a900461ffff1661ffff1667ffffffffffffffff81111561085e5761085d612bdf565b5b60405190808252806020026020018201604052801561088c5781602001602082028036833780820191505090505b50905060008060005b8460010160009054906101000a900461ffff1661ffff16821015610c9f57600085600201600083815260200190815260200160002054905060005b6008811015610c8a5783806108e490612ec3565b9450508660010160009054906101000a900461ffff1661ffff168411610c8a576000600582901b83901b90506000886000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020016000205460601c90506000805b88811015610adb578273ffffffffffffffffffffffffffffffffffffffff168c82815181106109a1576109a0612f0b565b5b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1603610ac857838c82815181106109dc576109db612f0b565b5b6020026020010151602001518b83815181106109fb576109fa612f0b565b5b602002602001015160ff1681518110610a1757610a16612f0b565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152505060ff8a8281518110610a7857610a77612f0b565b5b602002602001015160ff1610610a8d57600080fd5b898181518110610aa057610a9f612f0b565b5b602002602001018051809190610ab590612f47565b60ff1660ff168152505060019150610adb565b8080610ad390612ec3565b91505061096f565b508015610aea57505050610c77565b818b8981518110610afe57610afd612f0b565b5b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508960010160009054906101000a900461ffff1661ffff1667ffffffffffffffff811115610b6c57610b6b612bdf565b5b604051908082528060200260200182016040528015610b9a5781602001602082028036833780820191505090505b508b8981518110610bae57610bad612f0b565b5b602002602001015160200181905250828b8981518110610bd157610bd0612f0b565b5b602002602001015160200151600081518110610bf057610bef612f0b565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815250506001898981518110610c5157610c50612f0b565b5b602002602001019060ff16908160ff16815250508780610c7090612ec3565b9850505050505b8080610c8290612ec3565b9150506108d0565b50508080610c9790612ec3565b915050610895565b5060005b82811015610d08576000848281518110610cc057610cbf612f0b565b5b602002602001015160ff1690506000878381518110610ce257610ce1612f0b565b5b602002602001015160200151905081815250508080610d0090612ec3565b915050610ca3565b508185525050505090565b6000610d1d611474565b905090565b6000610d2c611164565b905090565b610d39611164565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d9d576040517f2f7a8ee100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610da6816114e0565b50565b60606000610db5611447565b90508060010160009054906101000a900461ffff1661ffff1667ffffffffffffffff811115610de757610de6612bdf565b5b604051908082528060200260200182016040528015610e155781602001602082028036833780820191505090505b50915060008060005b8360010160009054906101000a900461ffff1661ffff16821015610fba57600084600201600083815260200190815260200160002054905060005b6008811015610fa5578380610e6d90612ec3565b9450508560010160009054906101000a900461ffff1661ffff168411610fa5576000600582901b83901b9050866000016000827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020016000205460601c73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1603610f915780888781518110610f3657610f35612f0b565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815250508580610f8d90612ec3565b9650505b508080610f9d90612ec3565b915050610e59565b50508080610fb290612ec3565b915050610e1e565b50818452505050919050565b6000610fd0611447565b6000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020016000205460601c9050919050565b611035611164565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611099576040517f2f7a8ee100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110a28161152d565b50565b60006110af611539565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036110f0576110ed611414565b90505b90565b60006110fd6115e5565b6000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff169050919050565b600061116e611612565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006111a1611447565b905060008160010160009054906101000a900461ffff1661ffff16905060008190506000806007831611156111ed57836002016000600384901c81526020019081526020016000205490505b60005b875181101561133157600088828151811061120e5761120d612f0b565b5b60200260200101519050600081602001519050600082604001515103611260576040517feb6c3aeb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600281111561127457611273612f70565b5b81600281111561128757611286612f70565b5b036112a5576112988786868561163f565b8095508196505050611322565b600160028111156112b9576112b8612f70565b5b8160028111156112cc576112cb612f70565b5b036112e0576112db87836118f1565b611321565b6002808111156112f3576112f2612f70565b5b81600281111561130657611305612f70565b5b036113205761131787868685611ba7565b80955081965050505b5b5b505080806001019150506111f0565b5082821461135957818460010160006101000a81548161ffff021916908361ffff1602179055505b60006007831611156113845780846002016000600385901c8152602001908152602001600020819055505b7f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6738787876040516113b793929190613178565b60405180910390a16113c9868661208d565b50505050505050565b60008060006113e08561223a565b61ffff1690506113ef85612295565b61271085836113fe91906131bd565b611408919061322e565b92509250509250929050565b600061141e611447565b60030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000807f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc9390508091505090565b600061147e61233c565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6114b033612369565b6114b861233c565b60000160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055565b806114e9611447565b60030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6115368161243a565b50565b60008060007f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc93905080915081600001600080357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020016000205460601c9250505090565b6000807ffc606c433378e3a7e0a6a531deac289b66caa1b4aa8554fd4ab2c6f1570f92d890508091505090565b6000807f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f67168046090508091505090565b6000803073ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff16141580156116a257506116a0836000015173ffffffffffffffffffffffffffffffffffffffff166103c1565b155b156116d9576040517ff77172ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8360400151518110156118e15760008460400151828151811061170257611701612f0b565b5b602002602001015190506000886000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020549050600073ffffffffffffffffffffffffffffffffffffffff168160601c73ffffffffffffffffffffffffffffffffffffffff16146117cd576040517f92474ee200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760001b866000015160601b6bffffffffffffffffffffffff191617896000016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020819055506000600560078a16901b905080837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c817fffffffff0000000000000000000000000000000000000000000000000000000060001b901c19891617975060e081036118c957878a600201600060038c901c8152602001908152602001600020819055506000801b97505b888060010199505050505080806001019150506116dc565b5084849150915094509492505050565b611914816000015173ffffffffffffffffffffffffffffffffffffffff166103c1565b61194a576040517ff77172ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b816040015151811015611ba25760008260400151828151811061197357611972612f0b565b5b602002602001015190506000846000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002054905060008160601c9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611a43576040517f6fc4b52e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611aa8576040517fe983573100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846000015173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611b11576040517f617557e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846000015160601b6bffffffffffffffffffffffff19166bffffffffffffffffffffffff60001b831617866000016000857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002081905550505050808060010191505061194d565b505050565b600080600073ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff1614611c14576040517feacd242400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600386901c9050600060078716905060005b85604001515181101561207257600086604001518281518110611c4e57611c4d612f0b565b5b6020026020010151905060008a6000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020549050600073ffffffffffffffffffffffffffffffffffffffff168160601c73ffffffffffffffffffffffffffffffffffffffff1603611d19576040517f6fc4b52e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168160601c73ffffffffffffffffffffffffffffffffffffffff1603611d81576040517fe983573100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000801b8903611db5578480600190039550508a600201600086815260200190815260200160002054985060079350611dbf565b8380600190039450505b6000806000600587901b8c901b9250847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611ee1578d6000016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020546bffffffffffffffffffffffff19166bffffffffffffffffffffffff60001b8516178e6000016000857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020819055505b8d6000016000867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020016000206000905560008460001c61ffff169050600381901c9250600560078216901b915050878214611fe75760008e600201600084815260200190815260200160002054905081847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c827fffffffff0000000000000000000000000000000000000000000000000000000060001b901c198216179050808f60020160008581526020019081526020016000208190555050612038565b80837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c817fffffffff0000000000000000000000000000000000000000000000000000000060001b901c198d16179b505b60008703612060578d6002016000898152602001908152602001600020600090556000801b9b505b50505050508080600101915050611c28565b5080600383901b179650868693509350505094509492505050565b60008151141515600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141515146120fd576040517f26df4ccd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614612236573073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146121ba576121838273ffffffffffffffffffffffffffffffffffffffff166103c1565b6121b9576040517ff77172ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b60008273ffffffffffffffffffffffffffffffffffffffff16826040516121e1919061329b565b600060405180830381855af49150503d806000811461221c576040519150601f19603f3d011682016040523d82523d6000602084013e612221565b606091505b5050905080612234573d6000803e3d6000fd5b505b5050565b600080612245612446565b905080600001600084815260200190815260200160002060009054906101000a900461ffff16915060008261ffff160361228f578060010160009054906101000a900461ffff1691505b50919050565b6000806122a0612446565b905080600201600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169150600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612336578060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505b50919050565b6000807f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce661789090508091505090565b6000612373611612565b90508173ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b61244381612473565b50565b6000807ff298352fd56f58214bf2245c2b202523f72fca3199077ce992640958228b281f90508091505090565b61247c8161247f565b50565b8061248861233c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61254581612510565b811461255057600080fd5b50565b6000813590506125628161253c565b92915050565b60006020828403121561257e5761257d612506565b5b600061258c84828501612553565b91505092915050565b60008115159050919050565b6125aa81612595565b82525050565b60006020820190506125c560008301846125a1565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126125f0576125ef6125cb565b5b8235905067ffffffffffffffff81111561260d5761260c6125d0565b5b602083019150836020820283011115612629576126286125d5565b5b9250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061265b82612630565b9050919050565b61266b81612650565b811461267657600080fd5b50565b60008135905061268881612662565b92915050565b60008083601f8401126126a4576126a36125cb565b5b8235905067ffffffffffffffff8111156126c1576126c06125d0565b5b6020830191508360018202830111156126dd576126dc6125d5565b5b9250929050565b600080600080600060608688031215612700576126ff612506565b5b600086013567ffffffffffffffff81111561271e5761271d61250b565b5b61272a888289016125da565b9550955050602061273d88828901612679565b935050604086013567ffffffffffffffff81111561275e5761275d61250b565b5b61276a8882890161268e565b92509250509295509295909350565b6000819050919050565b61278c81612779565b811461279757600080fd5b50565b6000813590506127a981612783565b92915050565b600080604083850312156127c6576127c5612506565b5b60006127d48582860161279a565b92505060206127e58582860161279a565b9150509250929050565b6127f881612650565b82525050565b61280781612779565b82525050565b600060408201905061282260008301856127ef565b61282f60208301846127fe565b9392505050565b600060208201905061284b60008301846127ef565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61288681612650565b82525050565b6000612898838361287d565b60208301905092915050565b6000602082019050919050565b60006128bc82612851565b6128c6818561285c565b93506128d18361286d565b8060005b838110156129025781516128e9888261288c565b97506128f4836128a4565b9250506001810190506128d5565b5085935050505092915050565b6000602082019050818103600083015261292981846128b1565b905092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61299281612510565b82525050565b60006129a48383612989565b60208301905092915050565b6000602082019050919050565b60006129c88261295d565b6129d28185612968565b93506129dd83612979565b8060005b83811015612a0e5781516129f58882612998565b9750612a00836129b0565b9250506001810190506129e1565b5085935050505092915050565b6000604083016000830151612a33600086018261287d565b5060208301518482036020860152612a4b82826129bd565b9150508091505092915050565b6000612a648383612a1b565b905092915050565b6000602082019050919050565b6000612a8482612931565b612a8e818561293c565b935083602082028501612aa08561294d565b8060005b85811015612adc5784840389528151612abd8582612a58565b9450612ac883612a6c565b925060208a01995050600181019050612aa4565b50829750879550505050505092915050565b60006020820190508181036000830152612b088184612a79565b905092915050565b600060208284031215612b2657612b25612506565b5b6000612b3484828501612679565b91505092915050565b600082825260208201905092915050565b6000612b598261295d565b612b638185612b3d565b9350612b6e83612979565b8060005b83811015612b9f578151612b868882612998565b9750612b91836129b0565b925050600181019050612b72565b5085935050505092915050565b60006020820190508181036000830152612bc68184612b4e565b905092915050565b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612c1782612bce565b810181811067ffffffffffffffff82111715612c3657612c35612bdf565b5b80604052505050565b6000612c496124fc565b9050612c558282612c0e565b919050565b600067ffffffffffffffff821115612c7557612c74612bdf565b5b602082029050602081019050919050565b600080fd5b600080fd5b60038110612c9d57600080fd5b50565b600081359050612caf81612c90565b92915050565b600067ffffffffffffffff821115612cd057612ccf612bdf565b5b602082029050602081019050919050565b6000612cf4612cef84612cb5565b612c3f565b90508083825260208201905060208402830185811115612d1757612d166125d5565b5b835b81811015612d405780612d2c8882612553565b845260208401935050602081019050612d19565b5050509392505050565b600082601f830112612d5f57612d5e6125cb565b5b8135612d6f848260208601612ce1565b91505092915050565b600060608284031215612d8e57612d8d612c86565b5b612d986060612c3f565b90506000612da884828501612679565b6000830152506020612dbc84828501612ca0565b602083015250604082013567ffffffffffffffff811115612de057612ddf612c8b565b5b612dec84828501612d4a565b60408301525092915050565b6000612e0b612e0684612c5a565b612c3f565b90508083825260208201905060208402830185811115612e2e57612e2d6125d5565b5b835b81811015612e7557803567ffffffffffffffff811115612e5357612e526125cb565b5b808601612e608982612d78565b85526020850194505050602081019050612e30565b5050509392505050565b6000612e8c368484612df8565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000612ece82612779565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612f0057612eff612e94565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff82169050919050565b6000612f5282612f3a565b915060ff8203612f6557612f64612e94565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60038110612fdc57612fdb612f70565b5b50565b6000819050612fed82612fcb565b919050565b6000612ffd82612fdf565b9050919050565b61300d81612ff2565b82525050565b600060608301600083015161302b600086018261287d565b50602083015161303e6020860182613004565b506040830151848203604086015261305682826129bd565b9150508091505092915050565b600061306f8383613013565b905092915050565b6000602082019050919050565b600061308f82612f9f565b6130998185612faa565b9350836020820285016130ab85612fbb565b8060005b858110156130e757848403895281516130c88582613063565b94506130d383613077565b925060208a019950506001810190506130af565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613133578082015181840152602081019050613118565b60008484015250505050565b600061314a826130f9565b6131548185613104565b9350613164818560208601613115565b61316d81612bce565b840191505092915050565b600060608201905081810360008301526131928186613084565b90506131a160208301856127ef565b81810360408301526131b3818461313f565b9050949350505050565b60006131c882612779565b91506131d383612779565b92508282026131e181612779565b915082820484148315176131f8576131f7612e94565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061323982612779565b915061324483612779565b925082613254576132536131ff565b5b828204905092915050565b600081905092915050565b6000613275826130f9565b61327f818561325f565b935061328f818560208601613115565b80840191505092915050565b60006132a7828461326a565b91508190509291505056fea2646970667358221220b873d44b7534267ad89dd57fcd9a804e732ba809b24c960573180d6dfe2dee7a64736f6c63430008140033

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

0000000000000000000000004ab88e00570b740c1c403034d05954584d6351d10000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000002041000000000000000000000000e1c689334186473db5027b5f9354596ccee546690000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000e53696c6b7320486f727365205632000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e53494c4b535f484f5253455f5632000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002568747470733a2f2f6e66742e6465762e73696c6b732e696f2f6d657461646174612f63312f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000007e8000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001753696c6b73203230323420486f72736520536561736f6e000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000005af3107a400000000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000c3120506374205061796f75740000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _contractOwner (address): 0x4Ab88E00570B740c1C403034D05954584d6351d1
Arg [1] : _tokenName (string): Silks Horse V2
Arg [2] : _tokenSymbol (string): SILKS_HORSE_V2
Arg [3] : _tokenBaseURI (string): https://nft.dev.silks.io/metadata/c1/
Arg [4] : _startTokenId (uint256): 8257
Arg [5] : _royaltyReceiver (address): 0xE1c689334186473DB5027b5f9354596CCEe54669
Arg [6] : _royaltyBasePoints (uint16): 800
Arg [7] : _maxHorsesPerWallet (uint256): 0
Arg [8] : _seasonInfos (tuple[]): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
Arg [9] : _payoutTiers (tuple[]): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]

-----Encoded View---------------
37 Constructor Arguments found :
Arg [0] : 0000000000000000000000004ab88e00570b740c1c403034d05954584d6351d1
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000180
Arg [3] : 00000000000000000000000000000000000000000000000000000000000001c0
Arg [4] : 0000000000000000000000000000000000000000000000000000000000002041
Arg [5] : 000000000000000000000000e1c689334186473db5027b5f9354596ccee54669
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000320
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000220
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000320
Arg [10] : 000000000000000000000000000000000000000000000000000000000000000e
Arg [11] : 53696c6b7320486f727365205632000000000000000000000000000000000000
Arg [12] : 000000000000000000000000000000000000000000000000000000000000000e
Arg [13] : 53494c4b535f484f5253455f5632000000000000000000000000000000000000
Arg [14] : 0000000000000000000000000000000000000000000000000000000000000025
Arg [15] : 68747470733a2f2f6e66742e6465762e73696c6b732e696f2f6d657461646174
Arg [16] : 612f63312f000000000000000000000000000000000000000000000000000000
Arg [17] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [18] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [19] : 00000000000000000000000000000000000000000000000000000000000007e8
Arg [20] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [21] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [22] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [23] : 0000000000000000000000000000000000000000000000000000000000000017
Arg [24] : 53696c6b73203230323420486f72736520536561736f6e000000000000000000
Arg [25] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [26] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [27] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [28] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [29] : 00000000000000000000000000000000000000000000000000005af3107a4000
Arg [30] : 0000000000000000000000000000000000000000000000000000000000000064
Arg [31] : 0000000000000000000000000000000000000000000000000000000000000064
Arg [32] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [33] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [34] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [35] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [36] : 3120506374205061796f75740000000000000000000000000000000000000000


[ Download: CSV Export  ]
[ Download: CSV Export  ]

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