-
Notifications
You must be signed in to change notification settings - Fork 86
/
OperatorFiltererUpgradeable.sol
80 lines (71 loc) · 3.69 KB
/
OperatorFiltererUpgradeable.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
//SPDX-License-Identifier: MIT
pragma solidity 0.8.23;
import {IOperatorFilterRegistry} from "../interfaces/IOperatorFilterRegistry.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";
///@title OperatorFiltererUpgradeable
///@author The Sandbox
///@notice This contract would subscribe or copy or just to the subscription provided or just register to default subscription list
///@dev This contract is the upgradeable version of the OpenSea implementation https://github.com/ProjectOpenSea/operator-filter-registry/blob/main/src/OperatorFilterer.sol and adapted to the 0.5.9 solidity version
abstract contract OperatorFiltererUpgradeable is Context {
event ContractRegistered(address indexed subscriptionOrRegistrant, bool subscribe);
/// @notice the caller is not the operator
error OperatorNotAllowed();
modifier onlyAllowedOperatorApproval(address operator) virtual {
IOperatorFilterRegistry registry = _getOperatorFilterRegistry();
// Check registry code length to facilitate testing in environments without a deployed registry.
if (address(registry).code.length > 0) {
if (!registry.isOperatorAllowed(address(this), operator)) {
revert OperatorNotAllowed();
}
}
_;
}
modifier onlyAllowedOperator(address from) virtual {
IOperatorFilterRegistry registry = _getOperatorFilterRegistry();
// Check registry code length to facilitate testing in environments without a deployed registry.
if (address(registry).code.length > 0) {
// 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 == _msgSender()) {
_;
return;
}
if (!registry.isOperatorAllowed(address(this), _msgSender())) {
revert OperatorNotAllowed();
}
}
_;
}
/// @notice return the address of the operator filter registry
/// @return the address of the operator filter registry
function operatorFilterRegistry() external view returns (IOperatorFilterRegistry) {
return _getOperatorFilterRegistry();
}
/// @notice Register this contract into the registry
/// @param subscriptionOrRegistrantToCopy address to subscribe or copy entries from
/// @param subscribe should it subscribe
function _register(address subscriptionOrRegistrantToCopy, bool subscribe) internal {
IOperatorFilterRegistry registry = _getOperatorFilterRegistry();
if (address(registry).code.length > 0) {
if (!registry.isRegistered(address(this))) {
if (subscribe) {
registry.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy);
} else {
if (subscriptionOrRegistrantToCopy != address(0)) {
registry.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy);
} else {
registry.register(address(this));
}
}
}
}
emit ContractRegistered(subscriptionOrRegistrantToCopy, subscribe);
}
/// @notice get the OpenSea operator filter
/// @return the address of the OpenSea operator filter registry
function _getOperatorFilterRegistry() internal view virtual returns (IOperatorFilterRegistry);
/// @notice set the OpenSea operator filter
/// @param registry the address of the OpenSea operator filter registry
function _setOperatorFilterRegistry(IOperatorFilterRegistry registry) internal virtual;
}