Skip to content

Commit 4a0a32c

Browse files
committed
implemented ERC-721 version
1 parent 345bc15 commit 4a0a32c

2 files changed

Lines changed: 164 additions & 0 deletions

File tree

remappings.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ forge-std/=lib/forge-std/src/
55
@erc721a-upgradeable/=lib/ERC721A-Upgradeable/contracts/
66
@limitbreak/creator-token-standards/=lib/creator-token-standards/src/
77
@limitbreak/permit-c/=lib/PermitC/src/
8+
@imtbl/contracts/=lib/contracts.git/contracts/
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity ^0.8.20;
3+
4+
import {Module} from "../../../Module.sol";
5+
import {Role} from "../../../Role.sol";
6+
7+
import {BeforeApproveCallbackERC721} from "../../../callback/BeforeApproveCallbackERC721.sol";
8+
import {BeforeApproveForAllCallback} from "../../../callback/BeforeApproveForAllCallback.sol";
9+
import {BeforeTransferCallbackERC721} from "../../../callback/BeforeTransferCallbackERC721.sol";
10+
import {OperatorAllowlistEnforced} from "@imtbl/contracts/allowlist/OperatorAllowlistEnforced.sol";
11+
12+
library ImmutableAllowlistStorage {
13+
14+
/// @custom:storage-location erc7201:token.immutableallowlist
15+
bytes32 public constant IMMUTABLE_ALLOWLIST_STORAGE_POSITION =
16+
keccak256(abi.encode(uint256(keccak256("token.immutableAllowlist.ERC721")) - 1)) & ~bytes32(uint256(0xff));
17+
18+
struct Data {
19+
address operatorAllowlistRegistry;
20+
}
21+
22+
function data() internal pure returns (Data storage data_) {
23+
bytes32 position = IMMUTABLE_ALLOWLIST_STORAGE_POSITION;
24+
assembly {
25+
data_.slot := position
26+
}
27+
}
28+
29+
}
30+
31+
contract ImmutableAllowlistERC721 is
32+
Module,
33+
BeforeApproveCallbackERC721,
34+
BeforeApproveForAllCallback,
35+
BeforeTransferCallbackERC721,
36+
OperatorAllowlistEnforced
37+
{
38+
39+
/*//////////////////////////////////////////////////////////////
40+
ERRORS
41+
//////////////////////////////////////////////////////////////*/
42+
43+
/// @notice Emitted when an unauthorized approval is attempted.
44+
error OperatorAllowlistUnauthorizedApproval(address operator);
45+
46+
/// @notice Emitted when an unauthorized transfer is attempted.
47+
error OperatorAllowlistUnauthorizedTransfer(address from, address to, address operator);
48+
49+
/// @notice Emitted when the operator allowlist is not set.
50+
error OperatorAllowlistNotSet();
51+
52+
/*//////////////////////////////////////////////////////////////
53+
MODULE CONFIG
54+
//////////////////////////////////////////////////////////////*/
55+
56+
/// @notice Returns all implemented callback and module functions.
57+
function getModuleConfig() external pure override returns (ModuleConfig memory config) {
58+
config.callbackFunctions = new CallbackFunction[](3);
59+
config.fallbackFunctions = new FallbackFunction[](2);
60+
61+
config.callbackFunctions[0] = CallbackFunction(this.beforeApproveERC721.selector);
62+
config.callbackFunctions[1] = CallbackFunction(this.beforeApproveForAll.selector);
63+
config.callbackFunctions[2] = CallbackFunction(this.beforeTransferERC721.selector);
64+
65+
config.fallbackFunctions[0] =
66+
FallbackFunction({selector: this.setOperatorAllowlistRegistry.selector, permissionBits: Role._MANAGER_ROLE});
67+
config.fallbackFunctions[1] =
68+
FallbackFunction({selector: this.getOperatorAllowlistRegistry.selector, permissionBits: 0});
69+
70+
config.requiredInterfaces = new bytes4[](1);
71+
config.requiredInterfaces[0] = 0x80ac58cd; // ERC721
72+
73+
config.registerInstallationCallback = true;
74+
}
75+
76+
/*//////////////////////////////////////////////////////////////
77+
MODIFIERS
78+
//////////////////////////////////////////////////////////////*/
79+
80+
modifier isOperatorAllowlistSet() {
81+
if (_immutableAllowlistStorage().operatorAllowlistRegistry == address(0)) {
82+
revert OperatorAllowlistNotSet();
83+
}
84+
_;
85+
}
86+
87+
/*//////////////////////////////////////////////////////////////
88+
CALLBACK FUNCTIONS
89+
//////////////////////////////////////////////////////////////*/
90+
91+
/// @notice Callback function for ERC721.approve
92+
function beforeApproveERC721(address _from, address _to, uint256 _tokenId, bool _approve)
93+
external
94+
override
95+
isOperatorAllowlistSet
96+
validateApproval(_to)
97+
returns (bytes memory)
98+
{}
99+
100+
/// @notice Callback function for ERC721.setApprovalForAll
101+
function beforeApproveForAll(address _from, address _to, bool _approved)
102+
external
103+
override
104+
isOperatorAllowlistSet
105+
validateApproval(_to)
106+
returns (bytes memory)
107+
{}
108+
109+
/// @notice Callback function for ERC721.transferFrom/safeTransferFrom
110+
function beforeTransferERC721(address _from, address _to, uint256 _tokenId)
111+
external
112+
override
113+
isOperatorAllowlistSet
114+
validateTransfer(_from, _to)
115+
returns (bytes memory)
116+
{}
117+
118+
/// @dev Called by a Core into an Module during the installation of the Module.
119+
function onInstall(bytes calldata data) external {
120+
address registry = abi.decode(data, (address));
121+
_immutableAllowlistStorage().operatorAllowlistRegistry = registry;
122+
}
123+
124+
/// @dev Called by a Core into an Module during the uninstallation of the Module.
125+
function onUninstall(bytes calldata data) external {}
126+
127+
/*//////////////////////////////////////////////////////////////
128+
Encode install / uninstall data
129+
//////////////////////////////////////////////////////////////*/
130+
131+
/// @dev Returns bytes encoded install params, to be sent to `onInstall` function
132+
function encodeBytesOnInstall(address operatorAllowlistRegistry) external pure returns (bytes memory) {
133+
return abi.encode(operatorAllowlistRegistry);
134+
}
135+
136+
/// @dev Returns bytes encoded uninstall params, to be sent to `onUninstall` function
137+
function encodeBytesOnUninstall() external pure returns (bytes memory) {
138+
return "";
139+
}
140+
141+
/*//////////////////////////////////////////////////////////////
142+
FALLBACK FUNCTIONS
143+
//////////////////////////////////////////////////////////////*/
144+
145+
/// @notice Set the operator allowlist registry address
146+
function setOperatorAllowlistRegistry(address newRegistry) external {
147+
_immutableAllowlistStorage().operatorAllowlistRegistry = newRegistry;
148+
}
149+
150+
/// @notice Get the current operator allowlist registry address
151+
function getOperatorAllowlistRegistry() external view returns (address) {
152+
return _immutableAllowlistStorage().operatorAllowlistRegistry;
153+
}
154+
155+
/*//////////////////////////////////////////////////////////////
156+
INTERNAL FUNCTIONS
157+
//////////////////////////////////////////////////////////////*/
158+
159+
function _immutableAllowlistStorage() internal pure returns (ImmutableAllowlistStorage.Data storage) {
160+
return ImmutableAllowlistStorage.data();
161+
}
162+
163+
}

0 commit comments

Comments
 (0)