// SPDX-License-Identifier: MITpragmasolidity ^0.8.13;import {OperatorFilterer} from"./OperatorFilterer.sol";
import {CANONICAL_CORI_SUBSCRIPTION} from"./lib/Constants.sol";
/**
* @title DefaultOperatorFilterer
* @notice Inherits from OperatorFilterer and automatically subscribes to the default OpenSea subscription.
* @dev Please note that if your token contract does not provide an owner with EIP-173, it must provide
* administration methods on the contract itself to interact with the registry otherwise the subscription
* will be locked to the options set during construction.
*/abstractcontractDefaultOperatorFiltererisOperatorFilterer{
/// @dev The constructor that is called when the contract is being deployed.constructor() OperatorFilterer(CANONICAL_CORI_SUBSCRIPTION, true) {}
}
Contract Source Code
File 5 of 17: ERC165.sol
Contract Source Code
File 6 of 17: ERC721.sol
Contract Source Code
File 7 of 17: IERC165.sol
Contract Source Code
File 8 of 17: IERC721.sol
Contract Source Code
File 9 of 17: IERC721Metadata.sol
Contract Source Code
File 10 of 17: IERC721Receiver.sol
Contract Source Code
File 11 of 17: IOperatorFilterRegistry.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.13;interfaceIOperatorFilterRegistry{
/**
* @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.
*/functionisOperatorAllowed(address registrant, address operator) externalviewreturns (bool);
/**
* @notice Registers an address with the registry. May be called by address itself or by EIP-173 owner.
*/functionregister(address registrant) external;
/**
* @notice Registers an address with the registry and "subscribes" to another address's filtered operators and codeHashes.
*/functionregisterAndSubscribe(address registrant, address subscription) external;
/**
* @notice Registers an address with the registry and copies the filtered operators and codeHashes from another
* address without subscribing.
*/functionregisterAndCopyEntries(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.
*/functionunregister(address addr) external;
/**
* @notice Update an operator address for a registered address - when filtered is true, the operator is filtered.
*/functionupdateOperator(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.
*/functionupdateOperators(address registrant, address[] calldata operators, bool filtered) external;
/**
* @notice Update a codeHash for a registered address - when filtered is true, the codeHash is filtered.
*/functionupdateCodeHash(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.
*/functionupdateCodeHashes(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.
*/functionsubscribe(address registrant, address registrantToSubscribe) external;
/**
* @notice Unsubscribe an address from its current subscribed registrant, and optionally copy its filtered operators and codeHashes.
*/functionunsubscribe(address registrant, bool copyExistingEntries) external;
/**
* @notice Get the subscription address of a given registrant, if any.
*/functionsubscriptionOf(address addr) externalreturns (address registrant);
/**
* @notice Get the set of addresses subscribed to a given registrant.
* Note that order is not guaranteed as updates are made.
*/functionsubscribers(address registrant) externalreturns (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.
*/functionsubscriberAt(address registrant, uint256 index) externalreturns (address);
/**
* @notice Copy filtered operators and codeHashes from a different registrantToCopy to addr.
*/functioncopyEntriesOf(address registrant, address registrantToCopy) external;
/**
* @notice Returns true if operator is filtered by a given address or its subscription.
*/functionisOperatorFiltered(address registrant, address operator) externalreturns (bool);
/**
* @notice Returns true if the hash of an address's code is filtered by a given address or its subscription.
*/functionisCodeHashOfFiltered(address registrant, address operatorWithCode) externalreturns (bool);
/**
* @notice Returns true if a codeHash is filtered by a given address or its subscription.
*/functionisCodeHashFiltered(address registrant, bytes32 codeHash) externalreturns (bool);
/**
* @notice Returns a list of filtered operators for a given address or its subscription.
*/functionfilteredOperators(address addr) externalreturns (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.
*/functionfilteredCodeHashes(address addr) externalreturns (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.
*/functionfilteredOperatorAt(address registrant, uint256 index) externalreturns (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.
*/functionfilteredCodeHashAt(address registrant, uint256 index) externalreturns (bytes32);
/**
* @notice Returns true if an address has registered
*/functionisRegistered(address addr) externalreturns (bool);
/**
* @dev Convenience method to compute the code hash of an arbitrary contract
*/functioncodeHashOf(address addr) externalreturns (bytes32);
}
Contract Source Code
File 12 of 17: Math.sol
Contract Source Code
File 13 of 17: OperatorFilterer.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.13;import {IOperatorFilterRegistry} from"./IOperatorFilterRegistry.sol";
import {CANONICAL_OPERATOR_FILTER_REGISTRY_ADDRESS} from"./lib/Constants.sol";
/**
* @title OperatorFilterer
* @notice Abstract contract whose constructor automatically registers and optionally subscribes to or copies another
* registrant's entries in the OperatorFilterRegistry.
* @dev This smart contract is meant to be inherited by token contracts so they can use the following:
* - `onlyAllowedOperator` modifier for `transferFrom` and `safeTransferFrom` methods.
* - `onlyAllowedOperatorApproval` modifier for `approve` and `setApprovalForAll` methods.
* Please note that if your token contract does not provide an owner with EIP-173, it must provide
* administration methods on the contract itself to interact with the registry otherwise the subscription
* will be locked to the options set during construction.
*/abstractcontractOperatorFilterer{
/// @dev Emitted when an operator is not allowed.errorOperatorNotAllowed(address operator);
IOperatorFilterRegistry publicconstant OPERATOR_FILTER_REGISTRY =
IOperatorFilterRegistry(CANONICAL_OPERATOR_FILTER_REGISTRY_ADDRESS);
/// @dev The constructor that is called when the contract is being deployed.constructor(address subscriptionOrRegistrantToCopy, bool subscribe) {
// If an inheriting token contract is deployed to a network without the registry deployed, the modifier// will not revert, but the contract will need to be registered with the registry once it is deployed in// order for the modifier to filter addresses.if (address(OPERATOR_FILTER_REGISTRY).code.length>0) {
if (subscribe) {
OPERATOR_FILTER_REGISTRY.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy);
} else {
if (subscriptionOrRegistrantToCopy !=address(0)) {
OPERATOR_FILTER_REGISTRY.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy);
} else {
OPERATOR_FILTER_REGISTRY.register(address(this));
}
}
}
}
/**
* @dev A helper function to check if an operator is allowed.
*/modifieronlyAllowedOperator(addressfrom) virtual{
// Allow spending tokens from addresses with balance// Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred// from an EOA.if (from!=msg.sender) {
_checkFilterOperator(msg.sender);
}
_;
}
/**
* @dev A helper function to check if an operator approval is allowed.
*/modifieronlyAllowedOperatorApproval(address operator) virtual{
_checkFilterOperator(operator);
_;
}
/**
* @dev A helper function to check if an operator is allowed.
*/function_checkFilterOperator(address operator) internalviewvirtual{
// Check registry code length to facilitate testing in environments without a deployed registry.if (address(OPERATOR_FILTER_REGISTRY).code.length>0) {
// under normal circumstances, this function will revert rather than return false, but inheriting contracts// may specify their own OperatorFilterRegistry implementations, which may behave differentlyif (!OPERATOR_FILTER_REGISTRY.isOperatorAllowed(address(this), operator)) {
revert OperatorNotAllowed(operator);
}
}
}
}