ETH Price: $3,363.31 (-3.22%)
Gas: 6.27 Gwei

Token

Keepers (KEEPER)
 

Overview

Max Total Supply

500 KEEPER

Holders

219

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
crankshaw.eth
Balance
2 KEEPER
0x71b296ecd7a37140ba9b5749ee3c15993a241747
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

A frontier community

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
KeepersDiamond

Compiler Version
v0.8.18+commit.87f61d96

Optimization Enabled:
Yes with 800 runs

Other Settings:
default evmVersion
File 1 of 57 : KeepersDiamond.sol
// SPDX-License-Identifier: MIT

/*                                                                                                                                                                                                                                                                            
                                       ..';;::::::;;;::::;,'.                                       
                                   .,;;;;;,'....     ....';;;;;;'.                                  
                                ';;;,..                       .';;:,.                               
                             .,;,.                                .';;'                             
                           .,;.                  ...                 .,;.                           
                          .;.                                          .;;.                         
                         ',.                                             ';.                        
                        ''                                                .,.                       
                       .'                                                  .,                       
                      .'.                      .....                        ..                      
                      ..                    .;;,,,;,,;,.                     ..                     
                     ..                    ;c'       .;c'                    ..                     
                     ..                   ;c.          'c.                    .                     
                     .                .',;dl.         .;dl,,'.                ..                    
                     .              ,:;,..:xc:,.    .;:od,.',;;.               .                    
                    .             .:c.     ,c:cc.  ,l:::.     'c'              .                    
                    .             ,l.       .,:docldl;'        ,c.                                  
                                  ,c.        ';ddldxl,.        ,c.                                  
                                  .::.     '::lo' .;oc:;.     .c'                                   
                                   .,:,...;dc::.    '::do...';:.                                    
                                      ':clkd,.        .cxdlc;.                                      
                                    .,;,,,od:;.     .,;ldc,,;;'                                     
                                   ,c,.   .:c:c,   .:::c,    .:c.                                   
                                  'l.       ,;cxc;:do:;.       ;c.                                  
                                  ,c.        .;xkxOkl.         ,c.                                  
                                  .c,      .;:lx:';od::'      .c:                                   
                                   .:;.   .lc;c,   .:::l;   .,c;                                    
                                     .,;;:do;,.      .;cxl;;;,.                                     
                                     ';;;:do;'.      .,cxl;;;,.                                     
                                   .:;.   'oc::'   .;::o:.  .,c;.                                   
                                  .l'      .::ld;.,ld::,      .c;                                   
                                  ;c.        .:xkxOko'         ,c.                                  
                                  .l'      .,;cxc;cdo:;.      .c:                                   
                                   'c;.   .cc;c;   .c::l,    'c;.                                   
                                    .';;,;od:,.     .,;lxc,;;;.                                     
                                        .'l:           .o:..                                        
                                          'l'         .::.                                          
                                           .:;'......,:;.                                           
                                             .,;,,,,,'.                                             
                                                                                                    
                                                                                                    
                                 ..                              ...                                
                                  .''.                        .''..                                 
                                    ',,'.                  ..,,,.    ......                         
                                  ..,;:c;''...        .....'..          ...':c'                     
                               .;:;;'.    ................                 .:Kx.                    
                            .:lc,.                                   ..';:cokd'                     
                           ;xo.                                 ..,:ldkkOOxo,                       
                          ;0l                            ...',:oxO0KXK0xl;.                         
                          ;0x'   ................''',;:lodkOKXNWNX0ko:'.                            
                           ,oxdoccclodxxxkkkOO00KKXXXNWWWWWNK0xoc;..                                
                             .':lloodxkO00KKKKKK0OOOkxdoc:;'..                                      
                                    ................                                                                                                                                                                       
*/

pragma solidity 0.8.18;

import { SolidStateDiamondRevokableUpgradability } from "./SolidStateDiamondRevokableUpgradability.sol";
import { AccessControlInternal } from "@solidstate/contracts/access/access_control/AccessControlInternal.sol";
import { IERC721 } from "@solidstate/contracts/interfaces/IERC721.sol";
import { IERC165 } from "@solidstate/contracts/interfaces/IERC165.sol";
import { IERC2981 } from "@solidstate/contracts/interfaces/IERC2981.sol";
import { IERC721Enumerable } from "@solidstate/contracts/token/ERC721/enumerable/IERC721Enumerable.sol";
import { ERC2981Storage } from "@solidstate/contracts/token/common/ERC2981/ERC2981Storage.sol";
import { KeepersERC721Storage } from "./facets/KeepersERC721/KeepersERC721Storage.sol";
import { ERC721MetadataStorage } from "@solidstate/contracts/token/ERC721/metadata/ERC721MetadataStorage.sol";
import { TermsStorage } from "./facets/Terms/TermsStorage.sol";
import { ConstantsLib } from "./library/ConstantsLib.sol";
import { DiamondWritableInternal } from "@solidstate/contracts/proxy/diamond/writable/DiamondWritableInternal.sol";
import { CANONICAL_CORI_SUBSCRIPTION } from "operator-filter-registry/src/lib/Constants.sol";
import { DiamondOperatorFilter } from "./DiamondOperatorFilter.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

/**
 * @title KeepersDiamond "Diamond" proxy implementation based on SolidState Diamond Reference
 */
contract KeepersDiamond is SolidStateDiamondRevokableUpgradability, AccessControlInternal, DiamondOperatorFilter {
    using Counters for Counters.Counter;

    constructor(string memory name_, string memory symbol_, string memory baseURI_) {
        // ERC165 - note: other interfaces are set in SolidStateDiamondRevokableUpgradability
        _setSupportsInterface(type(IERC721).interfaceId, true);
        _setSupportsInterface(type(IERC721Enumerable).interfaceId, true);
        _setSupportsInterface(type(IERC2981).interfaceId, true);

        // AccessControl
        _grantRole(ConstantsLib.KEEPERS_TERMS_OPERATOR, msg.sender);
        _grantRole(ConstantsLib.KEEPERS_LICENSE_OPERATOR, msg.sender);

        // ERC2981
        ERC2981Storage.layout().defaultRoyaltyBPS = 700; // 7%
        ERC2981Storage.layout().defaultRoyaltyReceiver = msg.sender;

        // mint parameters
        KeepersERC721Storage.layout().maxPerAddress = 10;
        KeepersERC721Storage.layout().numAvailableTokens = uint16(ConstantsLib.MAX_TICKETS);

        // Metadata
        ERC721MetadataStorage.layout().name = name_;
        ERC721MetadataStorage.layout().symbol = symbol_;
        ERC721MetadataStorage.layout().baseURI = baseURI_;

        // Terms version
        TermsStorage.layout().termsVersion.increment(); // Set terms to V1 by default

        // Set up Operator Filter Registry
        __OperatorFilterer_init(CANONICAL_CORI_SUBSCRIPTION);
    }
}

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

pragma solidity ^0.8.0;

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

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

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

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

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

File 3 of 57 : 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);
    }
}

File 4 of 57 : 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 5 of 57 : 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 6 of 57 : 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 7 of 57 : 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 8 of 57 : 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 9 of 57 : ISafeOwnableInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

interface ISafeOwnableInternal is IOwnableInternal {
    error SafeOwnable__NotNomineeOwner();
}

File 10 of 57 : 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 11 of 57 : 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 12 of 57 : 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 13 of 57 : 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 14 of 57 : 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 15 of 57 : 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 16 of 57 : 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 17 of 57 : 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 18 of 57 : IERC165Internal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

}

File 19 of 57 : 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 20 of 57 : 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 21 of 57 : 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 22 of 57 : IERC2981Internal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

}

File 23 of 57 : IERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

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

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

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

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

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

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

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

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

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

File 24 of 57 : IERC721Internal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

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

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

File 25 of 57 : 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 26 of 57 : 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 27 of 57 : 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 28 of 57 : 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 29 of 57 : 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 30 of 57 : 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 31 of 57 : 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 32 of 57 : IDiamondBase.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

interface IDiamondBase is IProxy {}

File 33 of 57 : 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 34 of 57 : 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 35 of 57 : 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 36 of 57 : 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 37 of 57 : 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 38 of 57 : 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 39 of 57 : 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 {
        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 40 of 57 : 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 41 of 57 : 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 42 of 57 : IProxy.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

interface IProxy {
    error Proxy__ImplementationIsNotContract();

    fallback() external payable;
}

File 43 of 57 : 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 44 of 57 : 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 45 of 57 : IERC721Enumerable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

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

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

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

File 46 of 57 : 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 47 of 57 : 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 48 of 57 : 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 49 of 57 : DiamondOperatorFilter.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.18;

import { IOperatorFilterRegistry } from "operator-filter-registry/src/IOperatorFilterRegistry.sol";

/**
 * @dev copied from operator-filter-registry/src/upgradeable/OperatorFiltererUpgradeable.sol
 * @dev some of the control flow was removed to remove unnecessary branches
 */
contract DiamondOperatorFilter {
    IOperatorFilterRegistry constant OPERATOR_FILTER_REGISTRY =
        IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E);

    /// @dev The upgradeable initialize function that should be called when the contract is being upgraded.
    function __OperatorFilterer_init(address subscriptionOrRegistrantToCopy) internal {
        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
            if (!OPERATOR_FILTER_REGISTRY.isRegistered(address(this))) {
                OPERATOR_FILTER_REGISTRY.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy);
            }
        }
    }
}

File 50 of 57 : DiamondWritableRevokable.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.18;

import { OwnableInternal } from "@solidstate/contracts/access/ownable/OwnableInternal.sol";
import { IDiamondWritable } from "@solidstate/contracts/proxy/diamond/writable/IDiamondWritable.sol";
import { DiamondWritableInternal } from "@solidstate/contracts/proxy/diamond/writable/DiamondWritableInternal.sol";
import { DiamondWritableRevokableStorage } from "./DiamondWritableRevokableStorage.sol";

/**
 * @title EIP-2535 "Diamond" proxy update contract with built in revokability
 */
abstract contract DiamondWritableRevokable is IDiamondWritable, DiamondWritableInternal, OwnableInternal {
    error UpgradeabilityRevoked();

    /**
     * @inheritdoc IDiamondWritable
     * @dev also checks to ensure upgradeability has not been revoked
     */
    function diamondCut(FacetCut[] calldata facetCuts, address target, bytes calldata data) external onlyOwner {
        if (DiamondWritableRevokableStorage.layout().isUpgradeabiltyRevoked) revert UpgradeabilityRevoked();
        _diamondCut(facetCuts, target, data);
    }
}

File 51 of 57 : DiamondWritableRevokableStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.18;

library DiamondWritableRevokableStorage {
    bytes32 internal constant STORAGE_SLOT = keccak256("keepers.contracts.storage.diamond.writable.revokable");

    struct Layout {
        bool isUpgradeabiltyRevoked;
    }

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

File 52 of 57 : KeepersERC721Storage.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.18;

library KeepersERC721Storage {
    bytes32 internal constant STORAGE_SLOT = keccak256("keepers.contracts.storage.keepers.erc721.storage");

    // @dev struct which describes a commit
    // @dev use uint128 for tight variable packing
    struct MintCommit {
        uint128 numNFTs;
        uint128 commitBlock;
    }

    struct Layout {
        // @dev keeps track of available tokens for fisher yates shuffle
        mapping(uint256 => uint256) availableTokens;
        // @dev a mapping of user address to their pending commit
        mapping(address => MintCommit) pendingCommits;
        // Mint parameters
        mapping(address => uint256) mintCountPerAddress;
        // the following variables will be tightly packed
        uint16 numAvailableTokens;
        uint16 maxPerAddress;
        uint32 saleStartTimestamp; // max val in 2106
        uint32 saleCompleteTimestamp;
        uint160 numPendingCommitNFTs;
        address withdrawAddress;
        address vaultAddress;
        uint256 maxMintsForSalesTier; // when kept at 0 it is ignored
    }

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

File 53 of 57 : TermsStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.18;

import "@openzeppelin/contracts/utils/Counters.sol";

library TermsStorage {
    using Counters for Counters.Counter;

    bytes32 internal constant STORAGE_SLOT = keccak256("keepers.contracts.storage.terms");

    struct Layout {
        mapping(uint256 => string) termsParts; // mapping of term part number to term part string
        Counters.Counter termsVersion;
    }

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

File 54 of 57 : ConstantsLib.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;

library ConstantsLib {
    // mint params
    uint256 internal constant MINT_PRICE = 0.5 ether;
    uint256 internal constant ALLOWLSIT_MINT_PRICE = 0.25 ether;

    uint256 internal constant MAX_TICKETS = 20000;
    uint256 internal constant MIN_COMMITMENT_BLOCKS = 4;
    uint256 internal constant MAX_COMMITMENT_BLOCKS = 100;
    uint256 internal constant SPECIAL_TICKETS_COUNT = 10;
    uint256 internal constant SPECIAL_TICKET_MINT_ODDS = 1000;

    // access control
    bytes32 internal constant KEEPERS_TERMS_OPERATOR = keccak256("KEEPERS_TERMS_OPERATOR");
    bytes32 internal constant KEEPERS_LICENSE_OPERATOR = keccak256("KEEPERS_LICENSE_OPERATOR");
    bytes32 internal constant KEEPERS_MINT_OPERATOR = keccak256("KEEPERS_MINT_OPERATOR");

    // token states
    uint256 internal constant TOKEN_STATE_UNCONVERTED = 0;
    uint256 internal constant TOKEN_STATE_USER_CONVERTED = 1;
    uint256 internal constant TOKEN_STATE_ADMIN_CONVERTED = 2;

    // room naming
    uint256 internal constant NO_ROOM_NAMING_RIGHTS = 0;
    uint256 internal constant MAX_ROOM_NAME_LENGTH = 40;
    uint256 internal constant MIN_ROOM_ID = 1;

    // traits
    uint256 internal constant MIN_TRAIT_ID = 1;
    uint256 internal constant MAX_TRAIT_ID = 242;

    uint256 internal constant BLACK_BODY_ID = 1;
    uint256 internal constant GLASS_BODY_ID = 10;
    uint256 internal constant MAX_NON_SPECIAL_BODY_ID = 9;

    // rarities
    // bitmap for ultra rare traits 0000001111100000000000111001101110000000000000000100010000001111100000000000000000000000000000000000000000011100000000000000000000100000000000000000000011101010001000000000000000010000000000000000000000000000000000000000000000000000000000001110000000000000
    uint256 internal constant RARITY_ULTRARARE =
        1752737185771013737644568005558321144114900560241663114319964015025618739200;
    // bitmap for rare traits 0011100000000000000111000000000000000000000000000001100111110000000000000000000000000000000000001000000111100000000000000000010010000001000000000000111100010101110000000000001000100100000000000000000000000000000000000101000001000000111111110000000000000000
    uint256 internal constant RARITY_RARE =
        25329712769560669564647724112116350647150594218874243813999282872231118438400;
    // bitmap for uncommon traits 0000010000000100010000000110010000000000000000001010000000000000000000000000000000000000000001010001111000000000000000000000000001010100001111111111000000000000000100001000110111001000000000000000000000000000000000001010111100110111000000000000000000000000
    uint256 internal constant RARITY_UNCOMMON =
        1816763190353297512045086567763279289688669177570068147176572168506815021056;
    // bitmap for common traits 0100000000011011101000000000000001111111111111110000001000000000011111111111111111111111111110100110000000000011111111111111101100001010110000000000000000000000000011110111000000000011111111111111111111111111111111110000000010001000000000000000000000000000
    uint256 internal constant RARITY_COMMON =
        28996831472973116897448113818906002845680828376134306944232972948193012613120;

    // misc
    uint256 internal constant EMPTY_BITMAP = 0;
    string internal constant WHERE_TO_FIND_TERMS =
        "Terms and conditions can be found by calling getTerms() on the Keepers contract.";
}

File 55 of 57 : SolidStateDiamondRevokableUpgradability.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.18;

import { IOwnable, Ownable, OwnableInternal } from "@solidstate/contracts/access/ownable/Ownable.sol";
import { ISafeOwnable, SafeOwnable } from "@solidstate/contracts/access/ownable/SafeOwnable.sol";
import { IERC165 } from "@solidstate/contracts/interfaces/IERC165.sol";
import { IERC173 } from "@solidstate/contracts/interfaces/IERC173.sol";
import { ERC165Base, ERC165BaseStorage } from "@solidstate/contracts/introspection/ERC165/base/ERC165Base.sol";
import { DiamondBase } from "@solidstate/contracts/proxy/diamond/base/DiamondBase.sol";
import { DiamondFallback, IDiamondFallback } from "@solidstate/contracts/proxy/diamond/fallback/DiamondFallback.sol";
import { DiamondReadable, IDiamondReadable } from "@solidstate/contracts/proxy/diamond/readable/DiamondReadable.sol";
import { IDiamondWritable } from "@solidstate/contracts/proxy/diamond/writable/DiamondWritable.sol";
import { DiamondWritableRevokable } from "./facets/DiamondWritableRevokable/DiamondWritableRevokable.sol";
import { ISolidStateDiamond } from "@solidstate/contracts/proxy/diamond/ISolidStateDiamond.sol";

/**
 * @title SolidState "Diamond" proxy reference implementation with DiamondWritableRevokable
 */
abstract contract SolidStateDiamondRevokableUpgradability is
    ISolidStateDiamond,
    DiamondBase,
    DiamondFallback,
    DiamondReadable,
    DiamondWritableRevokable,
    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 56 of 57 : IOperatorFilterRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

interface IOperatorFilterRegistry {
    /**
     * @notice Returns true if operator is not filtered for a given token, either by address or codeHash. Also returns
     *         true if supplied registrant address is not registered.
     */
    function isOperatorAllowed(address registrant, address operator) external view returns (bool);

    /**
     * @notice Registers an address with the registry. May be called by address itself or by EIP-173 owner.
     */
    function register(address registrant) external;

    /**
     * @notice Registers an address with the registry and "subscribes" to another address's filtered operators and codeHashes.
     */
    function registerAndSubscribe(address registrant, address subscription) external;

    /**
     * @notice Registers an address with the registry and copies the filtered operators and codeHashes from another
     *         address without subscribing.
     */
    function registerAndCopyEntries(address registrant, address registrantToCopy) external;

    /**
     * @notice Unregisters an address with the registry and removes its subscription. May be called by address itself or by EIP-173 owner.
     *         Note that this does not remove any filtered addresses or codeHashes.
     *         Also note that any subscriptions to this registrant will still be active and follow the existing filtered addresses and codehashes.
     */
    function unregister(address addr) external;

    /**
     * @notice Update an operator address for a registered address - when filtered is true, the operator is filtered.
     */
    function updateOperator(address registrant, address operator, bool filtered) external;

    /**
     * @notice Update multiple operators for a registered address - when filtered is true, the operators will be filtered. Reverts on duplicates.
     */
    function updateOperators(address registrant, address[] calldata operators, bool filtered) external;

    /**
     * @notice Update a codeHash for a registered address - when filtered is true, the codeHash is filtered.
     */
    function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external;

    /**
     * @notice Update multiple codeHashes for a registered address - when filtered is true, the codeHashes will be filtered. Reverts on duplicates.
     */
    function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external;

    /**
     * @notice Subscribe an address to another registrant's filtered operators and codeHashes. Will remove previous
     *         subscription if present.
     *         Note that accounts with subscriptions may go on to subscribe to other accounts - in this case,
     *         subscriptions will not be forwarded. Instead the former subscription's existing entries will still be
     *         used.
     */
    function subscribe(address registrant, address registrantToSubscribe) external;

    /**
     * @notice Unsubscribe an address from its current subscribed registrant, and optionally copy its filtered operators and codeHashes.
     */
    function unsubscribe(address registrant, bool copyExistingEntries) external;

    /**
     * @notice Get the subscription address of a given registrant, if any.
     */
    function subscriptionOf(address addr) external returns (address registrant);

    /**
     * @notice Get the set of addresses subscribed to a given registrant.
     *         Note that order is not guaranteed as updates are made.
     */
    function subscribers(address registrant) external returns (address[] memory);

    /**
     * @notice Get the subscriber at a given index in the set of addresses subscribed to a given registrant.
     *         Note that order is not guaranteed as updates are made.
     */
    function subscriberAt(address registrant, uint256 index) external returns (address);

    /**
     * @notice Copy filtered operators and codeHashes from a different registrantToCopy to addr.
     */
    function copyEntriesOf(address registrant, address registrantToCopy) external;

    /**
     * @notice Returns true if operator is filtered by a given address or its subscription.
     */
    function isOperatorFiltered(address registrant, address operator) external returns (bool);

    /**
     * @notice Returns true if the hash of an address's code is filtered by a given address or its subscription.
     */
    function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool);

    /**
     * @notice Returns true if a codeHash is filtered by a given address or its subscription.
     */
    function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool);

    /**
     * @notice Returns a list of filtered operators for a given address or its subscription.
     */
    function filteredOperators(address addr) external returns (address[] memory);

    /**
     * @notice Returns the set of filtered codeHashes for a given address or its subscription.
     *         Note that order is not guaranteed as updates are made.
     */
    function filteredCodeHashes(address addr) external returns (bytes32[] memory);

    /**
     * @notice Returns the filtered operator at the given index of the set of filtered operators for a given address or
     *         its subscription.
     *         Note that order is not guaranteed as updates are made.
     */
    function filteredOperatorAt(address registrant, uint256 index) external returns (address);

    /**
     * @notice Returns the filtered codeHash at the given index of the list of filtered codeHashes for a given address or
     *         its subscription.
     *         Note that order is not guaranteed as updates are made.
     */
    function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32);

    /**
     * @notice Returns true if an address has registered
     */
    function isRegistered(address addr) external returns (bool);

    /**
     * @dev Convenience method to compute the code hash of an arbitrary contract
     */
    function codeHashOf(address addr) external returns (bytes32);
}

File 57 of 57 : Constants.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

address constant CANONICAL_OPERATOR_FILTER_REGISTRY_ADDRESS = 0x000000000000AAeB6D7670E522A718067333cd4E;
address constant CANONICAL_CORI_SUBSCRIPTION = 0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6;

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"string","name":"baseURI_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"Proxy__ImplementationIsNotContract","type":"error"},{"inputs":[],"name":"SafeOwnable__NotNomineeOwner","type":"error"},{"inputs":[],"name":"UpgradeabilityRevoked","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":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"},{"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":"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"}]

60806040523480156200001157600080fd5b506040516200354738038062003547833981016040819052620000349162001362565b60408051600c8082526101a0820190925260009160208201610180803683370190505090506000632c40805960e01b82826200007081620013f3565b9350815181106200008557620000856200141b565b6001600160e01b031990921660209283029190910190910152639142376560e01b8282620000b381620013f3565b935081518110620000c857620000c86200141b565b6001600160e01b031990921660209283029190910190910152620000f5632f40adcf60e21b6001620006d8565b6307e4c70760e21b82826200010a81620013f3565b9350815181106200011f576200011f6200141b565b6001600160e01b0319909216602092830291909101909101526200014c6307e4c70760e21b6001620006d8565b637a0ed62760e01b82826200016181620013f3565b9350815181106200017657620001766200141b565b6001600160e01b0319909216602092830291909101909101526356fe50af60e11b8282620001a481620013f3565b935081518110620001b957620001b96200141b565b6001600160e01b0319909216602092830291909101909101526314bbdacb60e21b8282620001e781620013f3565b935081518110620001fc57620001fc6200141b565b6001600160e01b0319909216602092830291909101909101526366ffd66360e11b82826200022a81620013f3565b9350815181106200023f576200023f6200141b565b6001600160e01b0319909216602092830291909101909101526200026c6348e2b09360e01b6001620006d8565b6301ffc9a760e01b82826200028181620013f3565b9350815181106200029657620002966200141b565b6001600160e01b031990921660209283029190910190910152620002c36301ffc9a760e01b6001620006d8565b638da5cb5b60e01b8282620002d881620013f3565b935081518110620002ed57620002ed6200141b565b6001600160e01b03199092166020928302919091019091015263455a8a8560e11b82826200031b81620013f3565b9350815181106200033057620003306200141b565b6001600160e01b03199092166020928302919091019091015263f2fde38b60e01b82826200035e81620013f3565b9350815181106200037357620003736200141b565b6001600160e01b0319909216602092830291909101909101526379ba509760e01b8282620003a181620013f3565b935081518110620003b657620003b66200141b565b6001600160e01b031990921660209283029190910190910152620003e36307f5828d60e41b6001620006d8565b604080516001808252818301909252600091816020015b60408051606080820183526000808352602083015291810191909152815260200190600190039081620003fa579050506040805160608101909152308152909150602081016000815260200184815250816000815181106200046057620004606200141b565b60200260200101819052506200048e816000604051806020016040528060008152506200074a60201b60201c565b620004993362000926565b505050620004b66380ac58cd60e01b6001620006d860201b60201c565b620004ca63780e9d6360e01b6001620006d8565b620004de63152a902d60e11b6001620006d8565b6200050a7f4f355d889785bcc16cc9d90e75bf97878cb8011983020de308d470c8cedf3f21336200099a565b620005367fe3318284dc7df61884a0f44a9db7f6ed140b100c862cbc07f3e8c1de3407f745336200099a565b6102bc6200054e62000a1060201b62000d111760201c565b60010160006101000a81548161ffff021916908361ffff160217905550336200058162000a1060201b62000d111760201c565b60030160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600a620005bf62000a3460201b62000d351760201c565b60030160026101000a81548161ffff021916908361ffff160217905550614e20620005f462000a3460201b62000d351760201c565b60030160006101000a81548161ffff021916908361ffff160217905550826200062762000a5860201b62000d591760201c565b90620006349082620014d5565b50816200064b62000a5860201b62000d591760201c565b600101906200065b9082620014d5565b50806200067262000a5860201b62000d591760201c565b60020190620006829082620014d5565b50620006b06200069c62000a7c60201b62000d7d1760201c565b60010162000aa060201b62000da11760201c565b620006cf733cc6cdda760b79bafa08df41ecfa224f810dceb662000aa9565b5050506200171f565b6001600160e01b03198083169003620007045760405163b0a19dd560e01b815260040160405180910390fd5b806200071a62000ba960201b62000daa1760201c565b6001600160e01b03199390931660009081526020939093526040909220805460ff19169215159290921790915550565b60006200076162000bcd60201b62000dce1760201c565b600181015490915061ffff811690819060009060071615620007955750600381901c60009081526002840160205260409020545b60005b875181101562000894576000888281518110620007b957620007b96200141b565b60200260200101519050600081602001519050816040015151600003620007f35760405163eb6c3aeb60e01b815260040160405180910390fd5b60008160028111156200080a576200080a62001431565b0362000829576200081e8786868562000bf1565b909550935062000889565b600181600281111562000840576200084062001431565b03620008585762000852878362000d50565b62000889565b60028160028111156200086f576200086f62001431565b036200088957620008838786868562000eb6565b90955093505b505060010162000798565b50828214620008b15760018401805461ffff191661ffff84161790555b6007821615620008d457600382901c600090815260028501602052604090208190555b7f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6738787876040516200090993929190620015cf565b60405180910390a16200091d8686620010e2565b50505050505050565b60006200093d620011e360201b62000df21760201c565b80546040519192506001600160a01b03808516929116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a380546001600160a01b0319166001600160a01b0392909216919091179055565b620009d381620009b46200120760201b62000e161760201c565b6000858152602091825260409020919062000e3a6200122b821b17901c565b5060405133906001600160a01b0383169084907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d90600090a45050565b7ff298352fd56f58214bf2245c2b202523f72fca3199077ce992640958228b281f90565b7f7e2d07d64a14e19cbb404a97c70a37424fe26c0b914348bf23e7cf52a012c2eb90565b7f99574a7094154bb123ae6ae102096f0bf9679b85a5cd1e727aaa0ae5f132e6b190565b7f5c326f5dbb0f8295b6973e9519c6a49d522fd1c150da562fee87f19638cabf3090565b80546001019055565b6daaeb6d7670e522a718067333cd4e3b1562000ba65760405163c3c5a54760e01b81523060048201526daaeb6d7670e522a718067333cd4e9063c3c5a547906024016020604051808303816000875af115801562000b0b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000b319190620016d6565b62000ba657604051633e9f1edf60e11b81523060048201526001600160a01b03821660248201526daaeb6d7670e522a718067333cd4e90637d3e3dbe90604401600060405180830381600087803b15801562000b8c57600080fd5b505af115801562000ba1573d6000803e3d6000fd5b505050505b50565b7ffc606c433378e3a7e0a6a531deac289b66caa1b4aa8554fd4ab2c6f1570f92d890565b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc9390565b805160009081906001600160a01b0316301480159062000c31575062000c2f83600001516001600160a01b03166200124b60201b620003061760201c565b155b1562000c5057604051633ddc5cab60e21b815260040160405180910390fd5b60005b83604001515181101562000d435760008460400151828151811062000c7c5762000c7c6200141b565b6020908102919091018101516001600160e01b031981166000908152918a9052604090912054909150606081901c1562000cc957604051634923a77160e11b815260040160405180910390fd5b85516001600160e01b0319838116600081815260208d90526040902060609390931b6001600160601b0319168b1790925560058a901b60e090811692831c91831c1999909916179781900362000d3357600389901c600090815260028b0160205260408120989098555b5050506001958601950162000c53565b5093959294509192505050565b62000d7381600001516001600160a01b03166200124b60201b620003061760201c565b62000d9157604051633ddc5cab60e21b815260040160405180910390fd5b60005b81604001515181101562000eb15760008260400151828151811062000dbd5762000dbd6200141b565b6020908102919091018101516001600160e01b03198116600090815291869052604090912054909150606081901c8062000e0a576040516337e25a9760e11b815260040160405180910390fd5b306001600160a01b0382160362000e345760405163e983573160e01b815260040160405180910390fd5b84600001516001600160a01b0316816001600160a01b03160362000e6b576040516330baabf360e11b815260040160405180910390fd5b5083516001600160e01b031992909216600090815260208690526040902060609290921b6001600160601b0319166001600160601b039190911617905560010162000d94565b505050565b805160009081906001600160a01b03161562000ee557604051633ab3490960e21b815260040160405180910390fd5b600385901c6007861660005b856040015151811015620010ce5760008660400151828151811062000f1a5762000f1a6200141b565b6020908102919091018101516001600160e01b031981166000908152918c9052604090912054909150606081901c62000f66576040516337e25a9760e11b815260040160405180910390fd5b30606082901c0362000f8b5760405163e983573160e01b815260040160405180910390fd5b600089900362000fb957600019909401600081815260028c0160205260409020549850936007935062000fc1565b600019909301925b600584901b89901b6000806001600160e01b03198084169086161462001014576001600160e01b03198316600090815260208f90526040902080546001600160601b0319166001600160601b0386161790555b50506001600160e01b03198316600090815260208d90526040812055611fff600383901c1660e0600584901b168782146200107957600082815260028f016020526040902080546001600160e01b031980841c19909116908516831c1790556200109d565b80836001600160e01b031916901c816001600160e01b031960001b901c198d16179b505b86600003620010bc57600088815260028f01602052604081208190559b505b50506001909301925062000ef1915050565b5060039190911b1796939550929350505050565b8051156001600160a01b03831615146200110f576040516326df4ccd60e01b815260040160405180910390fd5b6001600160a01b03821615620011df576001600160a01b03821630146200116d576200114f826001600160a01b03166200124b60201b620003061760201c565b6200116d57604051633ddc5cab60e21b815260040160405180910390fd5b6000826001600160a01b03168260405162001189919062001701565b600060405180830381855af49150503d8060008114620011c6576040519150601f19603f3d011682016040523d82523d6000602084013e620011cb565b606091505b505090508062000eb1573d6000803e3d6000fd5b5050565b7f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f67168046090565b7fd3889cc5458b268d0544e5534672df1296288ca3f93cbd39bd6f497a5c62281190565b600062001242836001600160a01b03841662001251565b90505b92915050565b3b151590565b600081815260018301602052604081205462001245575081546001808201845560008481526020808220909301849055845493815293810190915260409092205590565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620012c8578181015183820152602001620012ae565b50506000910152565b600082601f830112620012e357600080fd5b81516001600160401b038082111562001300576200130062001295565b604051601f8301601f19908116603f011681019082821181831017156200132b576200132b62001295565b816040528381528660208588010111156200134557600080fd5b62001358846020830160208901620012ab565b9695505050505050565b6000806000606084860312156200137857600080fd5b83516001600160401b03808211156200139057600080fd5b6200139e87838801620012d1565b94506020860151915080821115620013b557600080fd5b620013c387838801620012d1565b93506040860151915080821115620013da57600080fd5b50620013e986828701620012d1565b9150509250925092565b6000600182016200141457634e487b7160e01b600052601160045260246000fd5b5060010190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b600181811c908216806200145c57607f821691505b6020821081036200147d57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000eb157600081815260208120601f850160051c81016020861015620014ac5750805b601f850160051c820191505b81811015620014cd57828155600101620014b8565b505050505050565b81516001600160401b03811115620014f157620014f162001295565b620015098162001502845462001447565b8462001483565b602080601f831160018114620015415760008415620015285750858301515b600019600386901b1c1916600185901b178555620014cd565b600085815260208120601f198616915b82811015620015725788860151825594840194600190910190840162001551565b5085821015620015915787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008151808452620015bb816020860160208601620012ab565b601f01601f19169290920160200192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b84811015620016a457898403607f19018652815180516001600160a01b031685528381015189860190600381106200164057634e487b7160e01b600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b808310156200168e5783516001600160e01b031916825292860192600192909201919086019062001662565b50978501979550505090820190600101620015f8565b50506001600160a01b038a16908801528681036040880152620016c88189620015a1565b9a9950505050505050505050565b600060208284031215620016e957600080fd5b81518015158114620016fa57600080fd5b9392505050565b6000825162001715818460208701620012ab565b9190910192915050565b611e18806200172f6000396000f3fe6080604052600436106100cb5760003560e01c80638ab5150a11610074578063adfca15e1161004e578063adfca15e14610251578063cdffacc61461027e578063f2fde38b146102d7576100d2565b80638ab5150a146102075780638da5cb5b1461021c5780639142376514610231576100d2565b806352ef6b2c116100a557806352ef6b2c146101ae57806379ba5097146101d05780637a0ed627146101e5576100d2565b806301ffc9a71461012c5780631f931c1c146101615780632c40805914610181576100d2565b366100d257005b60006100dc6102f7565b90506001600160a01b0381163b610106576040516321f27f0d60e21b815260040160405180910390fd5b3660008037600080366000845af43d6000803e808015610125573d6000f35b3d6000fd5b005b34801561013857600080fd5b5061014c6101473660046117fb565b61030c565b60405190151581526020015b60405180910390f35b34801561016d57600080fd5b5061012a61017c366004611876565b61034f565b34801561018d57600080fd5b5061019661041c565b6040516001600160a01b039091168152602001610158565b3480156101ba57600080fd5b506101c361044f565b6040516101589190611928565b3480156101dc57600080fd5b5061012a610625565b3480156101f157600080fd5b506101fa610668565b60405161015891906119ba565b34801561021357600080fd5b50610196610ac3565b34801561022857600080fd5b50610196610acd565b34801561023d57600080fd5b5061012a61024c366004611a37565b610ad7565b34801561025d57600080fd5b5061027161026c366004611a37565b610b50565b6040516101589190611a52565b34801561028a57600080fd5b506101966102993660046117fb565b6001600160e01b03191660009081527f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc93602052604090205460601c90565b3480156102e357600080fd5b5061012a6102f2366004611a37565b610ccf565b6000610301610e56565b905090565b3b151590565b6001600160e01b0319811660009081527ffc606c433378e3a7e0a6a531deac289b66caa1b4aa8554fd4ab2c6f1570f92d8602052604081205460ff165b92915050565b610357610ec9565b6001600160a01b0316336001600160a01b03161461038857604051632f7a8ee160e01b815260040160405180910390fd5b7f245a6202ca3febd67bba5bd3d626122408bcacfedfba95bee54d5418459da8505460ff16156103cb5760405163ba5b67b960e01b815260040160405180910390fd5b6104156103d88587611b28565b8484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610efc92505050565b5050505050565b60006103017f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc96546001600160a01b031690565b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc94546060907f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc939061ffff1667ffffffffffffffff8111156104b2576104b2611a94565b6040519080825280602002602001820160405280156104db578160200160208202803683370190505b50915060008060005b600184015461ffff1682101561061d576000818152600285016020526040812054905b6008811015610608578361051a81611c72565b600188015490955061ffff168511905061060857600581901b82901b6001600160e01b0319811660009081526020889052604081205460601c90805b888110156105ab578a818151811061057057610570611c8b565b60200260200101516001600160a01b0316836001600160a01b03160361059957600191506105ab565b806105a381611c72565b915050610556565b5080156105ba575050506105f6565b818a89815181106105cd576105cd611c8b565b6001600160a01b0390921660209283029190910190910152876105ef81611c72565b9850505050505b8061060081611c72565b915050610507565b5050808061061590611c72565b9150506104e4565b505082525090565b61062d6110dc565b6001600160a01b0316336001600160a01b03161461065e5760405163efd1052d60e01b815260040160405180910390fd5b610666611104565b565b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc94546060907f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc939061ffff1667ffffffffffffffff8111156106cb576106cb611a94565b60405190808252806020026020018201604052801561071157816020015b6040805180820190915260008152606060208201528152602001906001900390816106e95790505b50600182015490925060009061ffff1667ffffffffffffffff81111561073957610739611a94565b604051908082528060200260200182016040528015610762578160200160208202803683370190505b50905060008060005b600185015461ffff16821015610a51576000818152600286016020526040812054905b6008811015610a3c57836107a181611c72565b600189015490955061ffff1685119050610a3c57600581901b82901b6001600160e01b0319811660009081526020899052604081205460601c90805b888110156108fa57826001600160a01b03168c828151811061080157610801611c8b565b6020026020010151600001516001600160a01b0316036108e857838c828151811061082e5761082e611c8b565b6020026020010151602001518b838151811061084c5761084c611c8b565b602002602001015160ff168151811061086757610867611c8b565b60200260200101906001600160e01b03191690816001600160e01b0319168152505060ff8a828151811061089d5761089d611c8b565b602002602001015160ff16106108b257600080fd5b8981815181106108c4576108c4611c8b565b6020026020010180518091906108d990611ca1565b60ff16905250600191506108fa565b806108f281611c72565b9150506107dd565b50801561090957505050610a2a565b818b898151811061091c5761091c611c8b565b60209081029190910101516001600160a01b03909116905260018a015461ffff1667ffffffffffffffff81111561095557610955611a94565b60405190808252806020026020018201604052801561097e578160200160208202803683370190505b508b898151811061099157610991611c8b565b602002602001015160200181905250828b89815181106109b3576109b3611c8b565b6020026020010151602001516000815181106109d1576109d1611c8b565b60200260200101906001600160e01b03191690816001600160e01b031916815250506001898981518110610a0757610a07611c8b565b60ff9092166020928302919091019091015287610a2381611c72565b9850505050505b80610a3481611c72565b91505061078e565b50508080610a4990611c72565b91505061076b565b5060005b82811015610ab8576000848281518110610a7157610a71611c8b565b602002602001015160ff1690506000878381518110610a9257610a92611c8b565b602002602001015160200151905081815250508080610ab090611c72565b915050610a55565b508185525050505090565b60006103016110dc565b6000610301610ec9565b610adf610ec9565b6001600160a01b0316336001600160a01b031614610b1057604051632f7a8ee160e01b815260040160405180910390fd5b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc9680546001600160a01b0319166001600160a01b03831617905550565b50565b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc94546060907f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc939061ffff1667ffffffffffffffff811115610bb357610bb3611a94565b604051908082528060200260200182016040528015610bdc578160200160208202803683370190505b50915060008060005b600184015461ffff16821015610cc5576000818152600285016020526040812054905b6008811015610cb05783610c1b81611c72565b600188015490955061ffff1685119050610cb057600581901b82901b6001600160e01b0319811660009081526020889052604090205460601c6001600160a01b038a1603610c9d5780888781518110610c7657610c76611c8b565b6001600160e01b03199092166020928302919091019091015285610c9981611c72565b9650505b5080610ca881611c72565b915050610c08565b50508080610cbd90611c72565b915050610be5565b5050825250919050565b610cd7610ec9565b6001600160a01b0316336001600160a01b031614610d0857604051632f7a8ee160e01b815260040160405180910390fd5b610b4d8161113e565b7ff298352fd56f58214bf2245c2b202523f72fca3199077ce992640958228b281f90565b7f7e2d07d64a14e19cbb404a97c70a37424fe26c0b914348bf23e7cf52a012c2eb90565b7f99574a7094154bb123ae6ae102096f0bf9679b85a5cd1e727aaa0ae5f132e6b190565b7f5c326f5dbb0f8295b6973e9519c6a49d522fd1c150da562fee87f19638cabf3090565b80546001019055565b7ffc606c433378e3a7e0a6a531deac289b66caa1b4aa8554fd4ab2c6f1570f92d890565b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc9390565b7f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f67168046090565b7fd3889cc5458b268d0544e5534672df1296288ca3f93cbd39bd6f497a5c62281190565b6000610e4f836001600160a01b038416611181565b9392505050565b600080356001600160e01b03191681527f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc93602052604090205460601c80610ec657507f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc96546001600160a01b031690565b90565b60007f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f6716804605b546001600160a01b0316919050565b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc94547f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc939061ffff811690819060009060071615610f6b5750600381901c60009081526002840160205260409020545b60005b8751811015611050576000888281518110610f8b57610f8b611c8b565b60200260200101519050600081602001519050816040015151600003610fc45760405163eb6c3aeb60e01b815260040160405180910390fd5b6000816002811115610fd857610fd8611cc0565b03610ff357610fe9878686856111c4565b9095509350611046565b600181600281111561100757611007611cc0565b0361101b576110168783611308565b611046565b600281600281111561102f5761102f611cc0565b036110465761104087868685611458565b90955093505b5050600101610f6e565b5082821461106c5760018401805461ffff191661ffff84161790555b600782161561108e57600382901c600090815260028501602052604090208190555b7f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6738787876040516110c193929190611d26565b60405180910390a16110d38686611680565b50505050505050565b60007f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce6617890610eed565b61110d33611764565b7f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce661789080546001600160a01b0319169055565b7f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce661789080546001600160a01b0319166001600160a01b038316179055610b4d81818181565b6000818152600183016020526040812054610349575081546001808201845560008481526020808220909301849055845493815293810190915260409092205590565b805160009081906001600160a01b031630148015906111ec575082516001600160a01b03163b155b1561120a57604051633ddc5cab60e21b815260040160405180910390fd5b60005b8360400151518110156112fb5760008460400151828151811061123257611232611c8b565b6020908102919091018101516001600160e01b031981166000908152918a9052604090912054909150606081901c1561127e57604051634923a77160e11b815260040160405180910390fd5b85516001600160e01b0319838116600081815260208d90526040902060609390931b6bffffffffffffffffffffffff19168b1790925560058a901b60e090811692831c91831c199990991617978190036112ec57600389901c600090815260028b0160205260408120989098555b5050506001958601950161120d565b5093959294509192505050565b80516001600160a01b03163b61133157604051633ddc5cab60e21b815260040160405180910390fd5b60005b8160400151518110156114535760008260400151828151811061135957611359611c8b565b6020908102919091018101516001600160e01b03198116600090815291869052604090912054909150606081901c806113a5576040516337e25a9760e11b815260040160405180910390fd5b306001600160a01b038216036113ce5760405163e983573160e01b815260040160405180910390fd5b84600001516001600160a01b0316816001600160a01b031603611404576040516330baabf360e11b815260040160405180910390fd5b5083516001600160e01b031992909216600090815260208690526040902060609290921b6bffffffffffffffffffffffff19166bffffffffffffffffffffffff91909116179055600101611334565b505050565b805160009081906001600160a01b03161561148657604051633ab3490960e21b815260040160405180910390fd5b600385901c6007861660005b85604001515181101561166c576000866040015182815181106114b7576114b7611c8b565b6020908102919091018101516001600160e01b031981166000908152918c9052604090912054909150606081901c611502576040516337e25a9760e11b815260040160405180910390fd5b30606082901c036115265760405163e983573160e01b815260040160405180910390fd5b600089900361155257600019909401600081815260028c0160205260409020549850936007935061155a565b600019909301925b600584901b89901b6000806001600160e01b0319808416908616146115b6576001600160e01b03198316600090815260208f90526040902080546bffffffffffffffffffffffff19166bffffffffffffffffffffffff86161790555b50506001600160e01b03198316600090815260208d90526040812055611fff600383901c1660e0600584901b1687821461161957600082815260028f016020526040902080546001600160e01b031980841c19909116908516831c17905561163d565b80836001600160e01b031916901c816001600160e01b031960001b901c198d16179b505b8660000361165b57600088815260028f01602052604081208190559b505b505060019093019250611492915050565b5060039190911b1796939550929350505050565b8051156001600160a01b03831615146116ac576040516326df4ccd60e01b815260040160405180910390fd5b6001600160a01b03821615611760576001600160a01b03821630146116f3576001600160a01b0382163b6116f357604051633ddc5cab60e21b815260040160405180910390fd5b6000826001600160a01b03168260405161170d9190611def565b600060405180830381855af49150503d8060008114611748576040519150601f19603f3d011682016040523d82523d6000602084013e61174d565b606091505b5050905080611453573d6000803e3d6000fd5b5050565b7f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f67168046080546040516001600160a01b038481169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a380546001600160a01b0319166001600160a01b0392909216919091179055565b80356001600160e01b0319811681146117f657600080fd5b919050565b60006020828403121561180d57600080fd5b610e4f826117de565b80356001600160a01b03811681146117f657600080fd5b60008083601f84011261183f57600080fd5b50813567ffffffffffffffff81111561185757600080fd5b60208301915083602082850101111561186f57600080fd5b9250929050565b60008060008060006060868803121561188e57600080fd5b853567ffffffffffffffff808211156118a657600080fd5b818801915088601f8301126118ba57600080fd5b8135818111156118c957600080fd5b8960208260051b85010111156118de57600080fd5b602083019750809650506118f460208901611816565b9450604088013591508082111561190a57600080fd5b506119178882890161182d565b969995985093965092949392505050565b6020808252825182820181905260009190848201906040850190845b818110156119695783516001600160a01b031683529284019291840191600101611944565b50909695505050505050565b600081518084526020808501945080840160005b838110156119af5781516001600160e01b03191687529582019590820190600101611989565b509495945050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611a2957888303603f19018552815180516001600160a01b03168452870151878401879052611a1687850182611975565b95880195935050908601906001016119e1565b509098975050505050505050565b600060208284031215611a4957600080fd5b610e4f82611816565b6020808252825182820181905260009190848201906040850190845b818110156119695783516001600160e01b03191683529284019291840191600101611a6e565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715611acd57611acd611a94565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611afc57611afc611a94565b604052919050565b600067ffffffffffffffff821115611b1e57611b1e611a94565b5060051b60200190565b6000611b3b611b3684611b04565b611ad3565b83815260208082019190600586811b860136811115611b5957600080fd5b865b81811015611c4f57803567ffffffffffffffff80821115611b7c5760008081fd5b818a01915060608236031215611b925760008081fd5b611b9a611aaa565b611ba383611816565b81528683013560038110611bb75760008081fd5b8188015260408381013583811115611bcf5760008081fd5b939093019236601f850112611be657600092508283fd5b83359250611bf6611b3684611b04565b83815292871b84018801928881019036851115611c135760008081fd5b948901945b84861015611c3857611c29866117de565b82529489019490890190611c18565b918301919091525088525050948301948301611b5b565b5092979650505050505050565b634e487b7160e01b600052601160045260246000fd5b600060018201611c8457611c84611c5c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b600060ff821660ff8103611cb757611cb7611c5c565b60010192915050565b634e487b7160e01b600052602160045260246000fd5b60005b83811015611cf1578181015183820152602001611cd9565b50506000910152565b60008151808452611d12816020860160208601611cd6565b601f01601f19169290920160200192915050565b6000606080830181845280875180835260808601915060808160051b87010192506020808a016000805b84811015611dbf57898703607f19018652825180516001600160a01b031688528481015160038110611d9057634e487b7160e01b84526021600452602484fd5b88860152604090810151908801899052611dac89890182611975565b9750509483019491830191600101611d50565b5050506001600160a01b0389169087015250508381036040850152611de48186611cfa565b979650505050505050565b60008251611e01818460208701611cd6565b919091019291505056fea164736f6c6343000812000a000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000074b6565706572730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064b45455045520000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003068747470733a2f2f6b6565706572732d746f6b656e2d6d657461646174612e73332e616d617a6f6e6177732e636f6d2f00000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106100cb5760003560e01c80638ab5150a11610074578063adfca15e1161004e578063adfca15e14610251578063cdffacc61461027e578063f2fde38b146102d7576100d2565b80638ab5150a146102075780638da5cb5b1461021c5780639142376514610231576100d2565b806352ef6b2c116100a557806352ef6b2c146101ae57806379ba5097146101d05780637a0ed627146101e5576100d2565b806301ffc9a71461012c5780631f931c1c146101615780632c40805914610181576100d2565b366100d257005b60006100dc6102f7565b90506001600160a01b0381163b610106576040516321f27f0d60e21b815260040160405180910390fd5b3660008037600080366000845af43d6000803e808015610125573d6000f35b3d6000fd5b005b34801561013857600080fd5b5061014c6101473660046117fb565b61030c565b60405190151581526020015b60405180910390f35b34801561016d57600080fd5b5061012a61017c366004611876565b61034f565b34801561018d57600080fd5b5061019661041c565b6040516001600160a01b039091168152602001610158565b3480156101ba57600080fd5b506101c361044f565b6040516101589190611928565b3480156101dc57600080fd5b5061012a610625565b3480156101f157600080fd5b506101fa610668565b60405161015891906119ba565b34801561021357600080fd5b50610196610ac3565b34801561022857600080fd5b50610196610acd565b34801561023d57600080fd5b5061012a61024c366004611a37565b610ad7565b34801561025d57600080fd5b5061027161026c366004611a37565b610b50565b6040516101589190611a52565b34801561028a57600080fd5b506101966102993660046117fb565b6001600160e01b03191660009081527f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc93602052604090205460601c90565b3480156102e357600080fd5b5061012a6102f2366004611a37565b610ccf565b6000610301610e56565b905090565b3b151590565b6001600160e01b0319811660009081527ffc606c433378e3a7e0a6a531deac289b66caa1b4aa8554fd4ab2c6f1570f92d8602052604081205460ff165b92915050565b610357610ec9565b6001600160a01b0316336001600160a01b03161461038857604051632f7a8ee160e01b815260040160405180910390fd5b7f245a6202ca3febd67bba5bd3d626122408bcacfedfba95bee54d5418459da8505460ff16156103cb5760405163ba5b67b960e01b815260040160405180910390fd5b6104156103d88587611b28565b8484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610efc92505050565b5050505050565b60006103017f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc96546001600160a01b031690565b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc94546060907f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc939061ffff1667ffffffffffffffff8111156104b2576104b2611a94565b6040519080825280602002602001820160405280156104db578160200160208202803683370190505b50915060008060005b600184015461ffff1682101561061d576000818152600285016020526040812054905b6008811015610608578361051a81611c72565b600188015490955061ffff168511905061060857600581901b82901b6001600160e01b0319811660009081526020889052604081205460601c90805b888110156105ab578a818151811061057057610570611c8b565b60200260200101516001600160a01b0316836001600160a01b03160361059957600191506105ab565b806105a381611c72565b915050610556565b5080156105ba575050506105f6565b818a89815181106105cd576105cd611c8b565b6001600160a01b0390921660209283029190910190910152876105ef81611c72565b9850505050505b8061060081611c72565b915050610507565b5050808061061590611c72565b9150506104e4565b505082525090565b61062d6110dc565b6001600160a01b0316336001600160a01b03161461065e5760405163efd1052d60e01b815260040160405180910390fd5b610666611104565b565b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc94546060907f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc939061ffff1667ffffffffffffffff8111156106cb576106cb611a94565b60405190808252806020026020018201604052801561071157816020015b6040805180820190915260008152606060208201528152602001906001900390816106e95790505b50600182015490925060009061ffff1667ffffffffffffffff81111561073957610739611a94565b604051908082528060200260200182016040528015610762578160200160208202803683370190505b50905060008060005b600185015461ffff16821015610a51576000818152600286016020526040812054905b6008811015610a3c57836107a181611c72565b600189015490955061ffff1685119050610a3c57600581901b82901b6001600160e01b0319811660009081526020899052604081205460601c90805b888110156108fa57826001600160a01b03168c828151811061080157610801611c8b565b6020026020010151600001516001600160a01b0316036108e857838c828151811061082e5761082e611c8b565b6020026020010151602001518b838151811061084c5761084c611c8b565b602002602001015160ff168151811061086757610867611c8b565b60200260200101906001600160e01b03191690816001600160e01b0319168152505060ff8a828151811061089d5761089d611c8b565b602002602001015160ff16106108b257600080fd5b8981815181106108c4576108c4611c8b565b6020026020010180518091906108d990611ca1565b60ff16905250600191506108fa565b806108f281611c72565b9150506107dd565b50801561090957505050610a2a565b818b898151811061091c5761091c611c8b565b60209081029190910101516001600160a01b03909116905260018a015461ffff1667ffffffffffffffff81111561095557610955611a94565b60405190808252806020026020018201604052801561097e578160200160208202803683370190505b508b898151811061099157610991611c8b565b602002602001015160200181905250828b89815181106109b3576109b3611c8b565b6020026020010151602001516000815181106109d1576109d1611c8b565b60200260200101906001600160e01b03191690816001600160e01b031916815250506001898981518110610a0757610a07611c8b565b60ff9092166020928302919091019091015287610a2381611c72565b9850505050505b80610a3481611c72565b91505061078e565b50508080610a4990611c72565b91505061076b565b5060005b82811015610ab8576000848281518110610a7157610a71611c8b565b602002602001015160ff1690506000878381518110610a9257610a92611c8b565b602002602001015160200151905081815250508080610ab090611c72565b915050610a55565b508185525050505090565b60006103016110dc565b6000610301610ec9565b610adf610ec9565b6001600160a01b0316336001600160a01b031614610b1057604051632f7a8ee160e01b815260040160405180910390fd5b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc9680546001600160a01b0319166001600160a01b03831617905550565b50565b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc94546060907f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc939061ffff1667ffffffffffffffff811115610bb357610bb3611a94565b604051908082528060200260200182016040528015610bdc578160200160208202803683370190505b50915060008060005b600184015461ffff16821015610cc5576000818152600285016020526040812054905b6008811015610cb05783610c1b81611c72565b600188015490955061ffff1685119050610cb057600581901b82901b6001600160e01b0319811660009081526020889052604090205460601c6001600160a01b038a1603610c9d5780888781518110610c7657610c76611c8b565b6001600160e01b03199092166020928302919091019091015285610c9981611c72565b9650505b5080610ca881611c72565b915050610c08565b50508080610cbd90611c72565b915050610be5565b5050825250919050565b610cd7610ec9565b6001600160a01b0316336001600160a01b031614610d0857604051632f7a8ee160e01b815260040160405180910390fd5b610b4d8161113e565b7ff298352fd56f58214bf2245c2b202523f72fca3199077ce992640958228b281f90565b7f7e2d07d64a14e19cbb404a97c70a37424fe26c0b914348bf23e7cf52a012c2eb90565b7f99574a7094154bb123ae6ae102096f0bf9679b85a5cd1e727aaa0ae5f132e6b190565b7f5c326f5dbb0f8295b6973e9519c6a49d522fd1c150da562fee87f19638cabf3090565b80546001019055565b7ffc606c433378e3a7e0a6a531deac289b66caa1b4aa8554fd4ab2c6f1570f92d890565b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc9390565b7f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f67168046090565b7fd3889cc5458b268d0544e5534672df1296288ca3f93cbd39bd6f497a5c62281190565b6000610e4f836001600160a01b038416611181565b9392505050565b600080356001600160e01b03191681527f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc93602052604090205460601c80610ec657507f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc96546001600160a01b031690565b90565b60007f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f6716804605b546001600160a01b0316919050565b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc94547f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc939061ffff811690819060009060071615610f6b5750600381901c60009081526002840160205260409020545b60005b8751811015611050576000888281518110610f8b57610f8b611c8b565b60200260200101519050600081602001519050816040015151600003610fc45760405163eb6c3aeb60e01b815260040160405180910390fd5b6000816002811115610fd857610fd8611cc0565b03610ff357610fe9878686856111c4565b9095509350611046565b600181600281111561100757611007611cc0565b0361101b576110168783611308565b611046565b600281600281111561102f5761102f611cc0565b036110465761104087868685611458565b90955093505b5050600101610f6e565b5082821461106c5760018401805461ffff191661ffff84161790555b600782161561108e57600382901c600090815260028501602052604090208190555b7f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6738787876040516110c193929190611d26565b60405180910390a16110d38686611680565b50505050505050565b60007f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce6617890610eed565b61110d33611764565b7f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce661789080546001600160a01b0319169055565b7f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce661789080546001600160a01b0319166001600160a01b038316179055610b4d81818181565b6000818152600183016020526040812054610349575081546001808201845560008481526020808220909301849055845493815293810190915260409092205590565b805160009081906001600160a01b031630148015906111ec575082516001600160a01b03163b155b1561120a57604051633ddc5cab60e21b815260040160405180910390fd5b60005b8360400151518110156112fb5760008460400151828151811061123257611232611c8b565b6020908102919091018101516001600160e01b031981166000908152918a9052604090912054909150606081901c1561127e57604051634923a77160e11b815260040160405180910390fd5b85516001600160e01b0319838116600081815260208d90526040902060609390931b6bffffffffffffffffffffffff19168b1790925560058a901b60e090811692831c91831c199990991617978190036112ec57600389901c600090815260028b0160205260408120989098555b5050506001958601950161120d565b5093959294509192505050565b80516001600160a01b03163b61133157604051633ddc5cab60e21b815260040160405180910390fd5b60005b8160400151518110156114535760008260400151828151811061135957611359611c8b565b6020908102919091018101516001600160e01b03198116600090815291869052604090912054909150606081901c806113a5576040516337e25a9760e11b815260040160405180910390fd5b306001600160a01b038216036113ce5760405163e983573160e01b815260040160405180910390fd5b84600001516001600160a01b0316816001600160a01b031603611404576040516330baabf360e11b815260040160405180910390fd5b5083516001600160e01b031992909216600090815260208690526040902060609290921b6bffffffffffffffffffffffff19166bffffffffffffffffffffffff91909116179055600101611334565b505050565b805160009081906001600160a01b03161561148657604051633ab3490960e21b815260040160405180910390fd5b600385901c6007861660005b85604001515181101561166c576000866040015182815181106114b7576114b7611c8b565b6020908102919091018101516001600160e01b031981166000908152918c9052604090912054909150606081901c611502576040516337e25a9760e11b815260040160405180910390fd5b30606082901c036115265760405163e983573160e01b815260040160405180910390fd5b600089900361155257600019909401600081815260028c0160205260409020549850936007935061155a565b600019909301925b600584901b89901b6000806001600160e01b0319808416908616146115b6576001600160e01b03198316600090815260208f90526040902080546bffffffffffffffffffffffff19166bffffffffffffffffffffffff86161790555b50506001600160e01b03198316600090815260208d90526040812055611fff600383901c1660e0600584901b1687821461161957600082815260028f016020526040902080546001600160e01b031980841c19909116908516831c17905561163d565b80836001600160e01b031916901c816001600160e01b031960001b901c198d16179b505b8660000361165b57600088815260028f01602052604081208190559b505b505060019093019250611492915050565b5060039190911b1796939550929350505050565b8051156001600160a01b03831615146116ac576040516326df4ccd60e01b815260040160405180910390fd5b6001600160a01b03821615611760576001600160a01b03821630146116f3576001600160a01b0382163b6116f357604051633ddc5cab60e21b815260040160405180910390fd5b6000826001600160a01b03168260405161170d9190611def565b600060405180830381855af49150503d8060008114611748576040519150601f19603f3d011682016040523d82523d6000602084013e61174d565b606091505b5050905080611453573d6000803e3d6000fd5b5050565b7f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f67168046080546040516001600160a01b038481169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a380546001600160a01b0319166001600160a01b0392909216919091179055565b80356001600160e01b0319811681146117f657600080fd5b919050565b60006020828403121561180d57600080fd5b610e4f826117de565b80356001600160a01b03811681146117f657600080fd5b60008083601f84011261183f57600080fd5b50813567ffffffffffffffff81111561185757600080fd5b60208301915083602082850101111561186f57600080fd5b9250929050565b60008060008060006060868803121561188e57600080fd5b853567ffffffffffffffff808211156118a657600080fd5b818801915088601f8301126118ba57600080fd5b8135818111156118c957600080fd5b8960208260051b85010111156118de57600080fd5b602083019750809650506118f460208901611816565b9450604088013591508082111561190a57600080fd5b506119178882890161182d565b969995985093965092949392505050565b6020808252825182820181905260009190848201906040850190845b818110156119695783516001600160a01b031683529284019291840191600101611944565b50909695505050505050565b600081518084526020808501945080840160005b838110156119af5781516001600160e01b03191687529582019590820190600101611989565b509495945050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611a2957888303603f19018552815180516001600160a01b03168452870151878401879052611a1687850182611975565b95880195935050908601906001016119e1565b509098975050505050505050565b600060208284031215611a4957600080fd5b610e4f82611816565b6020808252825182820181905260009190848201906040850190845b818110156119695783516001600160e01b03191683529284019291840191600101611a6e565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715611acd57611acd611a94565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611afc57611afc611a94565b604052919050565b600067ffffffffffffffff821115611b1e57611b1e611a94565b5060051b60200190565b6000611b3b611b3684611b04565b611ad3565b83815260208082019190600586811b860136811115611b5957600080fd5b865b81811015611c4f57803567ffffffffffffffff80821115611b7c5760008081fd5b818a01915060608236031215611b925760008081fd5b611b9a611aaa565b611ba383611816565b81528683013560038110611bb75760008081fd5b8188015260408381013583811115611bcf5760008081fd5b939093019236601f850112611be657600092508283fd5b83359250611bf6611b3684611b04565b83815292871b84018801928881019036851115611c135760008081fd5b948901945b84861015611c3857611c29866117de565b82529489019490890190611c18565b918301919091525088525050948301948301611b5b565b5092979650505050505050565b634e487b7160e01b600052601160045260246000fd5b600060018201611c8457611c84611c5c565b5060010190565b634e487b7160e01b600052603260045260246000fd5b600060ff821660ff8103611cb757611cb7611c5c565b60010192915050565b634e487b7160e01b600052602160045260246000fd5b60005b83811015611cf1578181015183820152602001611cd9565b50506000910152565b60008151808452611d12816020860160208601611cd6565b601f01601f19169290920160200192915050565b6000606080830181845280875180835260808601915060808160051b87010192506020808a016000805b84811015611dbf57898703607f19018652825180516001600160a01b031688528481015160038110611d9057634e487b7160e01b84526021600452602484fd5b88860152604090810151908801899052611dac89890182611975565b9750509483019491830191600101611d50565b5050506001600160a01b0389169087015250508381036040850152611de48186611cfa565b979650505050505050565b60008251611e01818460208701611cd6565b919091019291505056fea164736f6c6343000812000a

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

000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000074b6565706572730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064b45455045520000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003068747470733a2f2f6b6565706572732d746f6b656e2d6d657461646174612e73332e616d617a6f6e6177732e636f6d2f00000000000000000000000000000000

-----Decoded View---------------
Arg [0] : name_ (string): Keepers
Arg [1] : symbol_ (string): KEEPER
Arg [2] : baseURI_ (string): https://keepers-token-metadata.s3.amazonaws.com/

-----Encoded View---------------
10 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [4] : 4b65657065727300000000000000000000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [6] : 4b45455045520000000000000000000000000000000000000000000000000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000030
Arg [8] : 68747470733a2f2f6b6565706572732d746f6b656e2d6d657461646174612e73
Arg [9] : 332e616d617a6f6e6177732e636f6d2f00000000000000000000000000000000


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

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