@@ -5,16 +5,14 @@ import {Ownable} from "@solady/auth/Ownable.sol";
5
5
import {Multicallable} from "@solady/utils/Multicallable.sol " ;
6
6
import {ERC20 } from "@solady/tokens/ERC20.sol " ;
7
7
8
- import {HookFlagsDirectory} from "../../hook/HookFlagsDirectory.sol " ;
9
- import {HookInstaller} from "../HookInstaller.sol " ;
8
+ import {CoreContract} from "../CoreContract.sol " ;
10
9
11
- import {IERC20HookInstaller } from "../../interface/IERC20HookInstaller.sol " ;
12
10
import {BeforeMintHookERC20} from "../../hook/BeforeMintHookERC20.sol " ;
13
11
import {BeforeApproveHookERC20} from "../../hook/BeforeApproveHookERC20.sol " ;
14
12
import {BeforeTransferHookERC20} from "../../hook/BeforeTransferHookERC20.sol " ;
15
13
import {BeforeBurnHookERC20} from "../../hook/BeforeBurnHookERC20.sol " ;
16
14
17
- contract ERC20Core is ERC20 , HookInstaller , Ownable , Multicallable , IERC20HookInstaller , HookFlagsDirectory {
15
+ contract ERC20Core is ERC20 , CoreContract , Ownable , Multicallable {
18
16
/*//////////////////////////////////////////////////////////////
19
17
STORAGE
20
18
//////////////////////////////////////////////////////////////*/
@@ -33,16 +31,10 @@ contract ERC20Core is ERC20, HookInstaller, Ownable, Multicallable, IERC20HookIn
33
31
//////////////////////////////////////////////////////////////*/
34
32
35
33
/// @notice Emitted when the on initialize call fails.
36
- error ERC20CoreOnInitializeCallFailed ();
37
-
38
- /// @notice Emitted when a hook initialization call fails.
39
- error ERC20CoreHookInitializeCallFailed ();
34
+ error ERC20CoreInitCallFailed ();
40
35
41
36
/// @notice Emitted when a hook call fails.
42
- error ERC20CoreHookCallFailed ();
43
-
44
- /// @notice Emitted when insufficient value is sent in the constructor.
45
- error ERC20CoreInsufficientValueInConstructor ();
37
+ error ERC20CoreCallbackFailed ();
46
38
47
39
/// @notice Emitted on an attempt to mint tokens when no beforeMint hook is installed.
48
40
error ERC20CoreMintDisabled ();
@@ -58,23 +50,14 @@ contract ERC20Core is ERC20, HookInstaller, Ownable, Multicallable, IERC20HookIn
58
50
CONSTRUCTOR
59
51
//////////////////////////////////////////////////////////////*/
60
52
61
- /**
62
- * @notice Initializes the ERC20 token.
63
- *
64
- * @param _name The name of the token.
65
- * @param _symbol The symbol of the token.
66
- * @param _contractURI The contract URI of the token.
67
- * @param _owner The owner of the contract.
68
- * @param _onInitializeCall Any external call to make on contract initialization.
69
- * @param _hooksToInstall Any hooks to install and initialize on contract initialization.
70
- */
71
53
constructor (
72
54
string memory _name ,
73
55
string memory _symbol ,
74
56
string memory _contractURI ,
75
57
address _owner ,
76
- OnInitializeParams memory _onInitializeCall ,
77
- InstallHookParams[] memory _hooksToInstall
58
+ address [] memory _extensionsToInstall ,
59
+ address _initCallTarget ,
60
+ bytes memory _initCalldata
78
61
) payable {
79
62
// Set contract metadata
80
63
name_ = _name;
@@ -84,26 +67,15 @@ contract ERC20Core is ERC20, HookInstaller, Ownable, Multicallable, IERC20HookIn
84
67
// Set contract owner
85
68
_setOwner (_owner);
86
69
87
- // Track native token value sent to the constructor
88
- uint256 constructorValue = msg .value ;
89
-
90
- // Initialize the core token
91
- if (_onInitializeCall.target != address (0 )) {
92
- if (constructorValue < _onInitializeCall.value) revert ERC20CoreInsufficientValueInConstructor ();
93
- constructorValue -= _onInitializeCall.value;
94
-
95
- (bool success , bytes memory returndata ) =
96
- _onInitializeCall.target.call {value: _onInitializeCall.value}(_onInitializeCall.data);
97
-
98
- if (! success) _revert (returndata, ERC20CoreOnInitializeCallFailed .selector );
70
+ // External call upon core core contract initialization.
71
+ if (_initCallTarget != address (0 ) && _initCalldata.length > 0 ) {
72
+ (bool success , bytes memory returndata ) = _initCallTarget.call {value: msg .value }(_initCalldata);
73
+ if (! success) _revert (returndata, ERC20CoreInitCallFailed .selector );
99
74
}
100
75
101
76
// Install and initialize hooks
102
- for (uint256 i = 0 ; i < _hooksToInstall.length ; i++ ) {
103
- if (constructorValue < _hooksToInstall[i].initValue) revert ERC20CoreInsufficientValueInConstructor ();
104
- constructorValue -= _hooksToInstall[i].initValue;
105
-
106
- _installHook (_hooksToInstall[i]);
77
+ for (uint256 i = 0 ; i < _extensionsToInstall.length ; i++ ) {
78
+ _installExtension (_extensionsToInstall[i]);
107
79
}
108
80
}
109
81
@@ -129,14 +101,18 @@ contract ERC20Core is ERC20, HookInstaller, Ownable, Multicallable, IERC20HookIn
129
101
return contractURI_;
130
102
}
131
103
132
- /// @notice Returns all of the contract's hooks and their implementations.
133
- function getAllHooks () external view returns (ERC20Hooks memory hooks ) {
134
- hooks = ERC20Hooks ({
135
- beforeMint: getHookImplementation (BEFORE_MINT_ERC20_FLAG),
136
- beforeTransfer: getHookImplementation (BEFORE_TRANSFER_ERC20_FLAG),
137
- beforeBurn: getHookImplementation (BEFORE_BURN_ERC20_FLAG),
138
- beforeApprove: getHookImplementation (BEFORE_APPROVE_ERC20_FLAG)
139
- });
104
+ function getSupportedCallbackFunctions ()
105
+ public
106
+ pure
107
+ override
108
+ returns (bytes4 [] memory supportedCallbackFunctions )
109
+ {
110
+ supportedCallbackFunctions = new bytes4 [](4 );
111
+
112
+ supportedCallbackFunctions[0 ] = BeforeMintHookERC20.beforeMintERC20.selector ;
113
+ supportedCallbackFunctions[1 ] = BeforeTransferHookERC20.beforeTransferERC20.selector ;
114
+ supportedCallbackFunctions[2 ] = BeforeBurnHookERC20.beforeBurnERC20.selector ;
115
+ supportedCallbackFunctions[3 ] = BeforeApproveHookERC20.beforeApproveERC20.selector ;
140
116
}
141
117
142
118
/*//////////////////////////////////////////////////////////////
@@ -223,19 +199,12 @@ contract ERC20Core is ERC20, HookInstaller, Ownable, Multicallable, IERC20HookIn
223
199
INTERNAL FUNCTIONS
224
200
//////////////////////////////////////////////////////////////*/
225
201
226
- /// @dev Returns whether the caller can update hooks.
227
- function _canUpdateHooks (address _caller ) internal view override returns (bool ) {
228
- return _caller == owner ();
229
- }
230
-
231
- /// @dev Returns whether the caller can write to hooks.
232
- function _isAuthorizedToCallHookFallbackFunction (address _caller ) internal view override returns (bool ) {
233
- return _caller == owner ();
202
+ function _isAuthorizedToInstallExtensions (address _target ) internal view override returns (bool ) {
203
+ return _target == owner ();
234
204
}
235
205
236
- /// @dev Should return the supported hook flags.
237
- function _supportedHookFlags () internal view virtual override returns (uint256 ) {
238
- return BEFORE_MINT_ERC20_FLAG | BEFORE_TRANSFER_ERC20_FLAG | BEFORE_BURN_ERC20_FLAG | BEFORE_APPROVE_ERC20_FLAG;
206
+ function _isAuthorizedToCallExtensionFunctions (address _target ) internal view override returns (bool ) {
207
+ return _target == owner ();
239
208
}
240
209
241
210
/// @dev Sets contract URI
@@ -245,19 +214,19 @@ contract ERC20Core is ERC20, HookInstaller, Ownable, Multicallable, IERC20HookIn
245
214
}
246
215
247
216
/*//////////////////////////////////////////////////////////////
248
- HOOKS INTERNAL FUNCTIONS
217
+ CALLBACK INTERNAL FUNCTIONS
249
218
//////////////////////////////////////////////////////////////*/
250
219
251
220
/// @dev Calls the beforeMint hook.
252
221
function _beforeMint (address _to , uint256 _amount , bytes calldata _data ) internal virtual {
253
- address hook = getHookImplementation (BEFORE_MINT_ERC20_FLAG );
222
+ address extension = getCallbackFunctionImplementation (BeforeMintHookERC20.beforeMintERC20. selector );
254
223
255
- if (hook != address (0 )) {
256
- (bool success , bytes memory returndata ) = hook .call {value: msg .value }(
224
+ if (extension != address (0 )) {
225
+ (bool success , bytes memory returndata ) = extension .call {value: msg .value }(
257
226
abi.encodeWithSelector (BeforeMintHookERC20.beforeMintERC20.selector , _to, _amount, _data)
258
227
);
259
228
260
- if (! success) _revert (returndata, ERC20CoreHookCallFailed .selector );
229
+ if (! success) _revert (returndata, ERC20CoreCallbackFailed .selector );
261
230
} else {
262
231
// Revert if beforeMint hook is not installed to disable un-permissioned minting.
263
232
revert ERC20CoreMintDisabled ();
@@ -266,37 +235,37 @@ contract ERC20Core is ERC20, HookInstaller, Ownable, Multicallable, IERC20HookIn
266
235
267
236
/// @dev Calls the beforeTransfer hook, if installed.
268
237
function _beforeTransfer (address _from , address _to , uint256 _amount ) internal virtual {
269
- address hook = getHookImplementation (BEFORE_TRANSFER_ERC20_FLAG );
238
+ address extension = getCallbackFunctionImplementation (BeforeTransferHookERC20.beforeTransferERC20. selector );
270
239
271
- if (hook != address (0 )) {
272
- (bool success , bytes memory returndata ) = hook .call (
240
+ if (extension != address (0 )) {
241
+ (bool success , bytes memory returndata ) = extension .call (
273
242
abi.encodeWithSelector (BeforeTransferHookERC20.beforeTransferERC20.selector , _from, _to, _amount)
274
243
);
275
- if (! success) _revert (returndata, ERC20CoreHookCallFailed .selector );
244
+ if (! success) _revert (returndata, ERC20CoreCallbackFailed .selector );
276
245
}
277
246
}
278
247
279
248
/// @dev Calls the beforeBurn hook, if installed.
280
249
function _beforeBurn (address _from , uint256 _amount , bytes calldata _data ) internal virtual {
281
- address hook = getHookImplementation (BEFORE_BURN_ERC20_FLAG );
250
+ address extension = getCallbackFunctionImplementation (BeforeBurnHookERC20.beforeBurnERC20. selector );
282
251
283
- if (hook != address (0 )) {
284
- (bool success , bytes memory returndata ) = hook .call {value: msg .value }(
252
+ if (extension != address (0 )) {
253
+ (bool success , bytes memory returndata ) = extension .call {value: msg .value }(
285
254
abi.encodeWithSelector (BeforeBurnHookERC20.beforeBurnERC20.selector , _from, _amount, _data)
286
255
);
287
- if (! success) _revert (returndata, ERC20CoreHookCallFailed .selector );
256
+ if (! success) _revert (returndata, ERC20CoreCallbackFailed .selector );
288
257
}
289
258
}
290
259
291
260
/// @dev Calls the beforeApprove hook, if installed.
292
261
function _beforeApprove (address _from , address _to , uint256 _amount ) internal virtual {
293
- address hook = getHookImplementation (BEFORE_APPROVE_ERC20_FLAG );
262
+ address extension = getCallbackFunctionImplementation (BeforeApproveHookERC20.beforeApproveERC20. selector );
294
263
295
- if (hook != address (0 )) {
296
- (bool success , bytes memory returndata ) = hook .call (
264
+ if (extension != address (0 )) {
265
+ (bool success , bytes memory returndata ) = extension .call (
297
266
abi.encodeWithSelector (BeforeApproveHookERC20.beforeApproveERC20.selector , _from, _to, _amount)
298
267
);
299
- if (! success) _revert (returndata, ERC20CoreHookCallFailed .selector );
268
+ if (! success) _revert (returndata, ERC20CoreCallbackFailed .selector );
300
269
}
301
270
}
302
271
}
0 commit comments