@@ -5,16 +5,14 @@ import {Ownable} from "@solady/auth/Ownable.sol";
55import {Multicallable} from "@solady/utils/Multicallable.sol " ;
66import {ERC20 } from "@solady/tokens/ERC20.sol " ;
77
8- import {HookFlagsDirectory} from "../../hook/HookFlagsDirectory.sol " ;
9- import {HookInstaller} from "../HookInstaller.sol " ;
8+ import {CoreContract} from "../CoreContract.sol " ;
109
11- import {IERC20HookInstaller } from "../../interface/IERC20HookInstaller.sol " ;
1210import {BeforeMintHookERC20} from "../../hook/BeforeMintHookERC20.sol " ;
1311import {BeforeApproveHookERC20} from "../../hook/BeforeApproveHookERC20.sol " ;
1412import {BeforeTransferHookERC20} from "../../hook/BeforeTransferHookERC20.sol " ;
1513import {BeforeBurnHookERC20} from "../../hook/BeforeBurnHookERC20.sol " ;
1614
17- contract ERC20Core is ERC20 , HookInstaller , Ownable , Multicallable , IERC20HookInstaller , HookFlagsDirectory {
15+ contract ERC20Core is ERC20 , CoreContract , Ownable , Multicallable {
1816 /*//////////////////////////////////////////////////////////////
1917 STORAGE
2018 //////////////////////////////////////////////////////////////*/
@@ -33,16 +31,10 @@ contract ERC20Core is ERC20, HookInstaller, Ownable, Multicallable, IERC20HookIn
3331 //////////////////////////////////////////////////////////////*/
3432
3533 /// @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 ();
4035
4136 /// @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 ();
4638
4739 /// @notice Emitted on an attempt to mint tokens when no beforeMint hook is installed.
4840 error ERC20CoreMintDisabled ();
@@ -58,23 +50,14 @@ contract ERC20Core is ERC20, HookInstaller, Ownable, Multicallable, IERC20HookIn
5850 CONSTRUCTOR
5951 //////////////////////////////////////////////////////////////*/
6052
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- */
7153 constructor (
7254 string memory _name ,
7355 string memory _symbol ,
7456 string memory _contractURI ,
7557 address _owner ,
76- OnInitializeParams memory _onInitializeCall ,
77- InstallHookParams[] memory _hooksToInstall
58+ address [] memory _extensionsToInstall ,
59+ address _initCallTarget ,
60+ bytes memory _initCalldata
7861 ) payable {
7962 // Set contract metadata
8063 name_ = _name;
@@ -84,26 +67,15 @@ contract ERC20Core is ERC20, HookInstaller, Ownable, Multicallable, IERC20HookIn
8467 // Set contract owner
8568 _setOwner (_owner);
8669
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 );
9974 }
10075
10176 // 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]);
10779 }
10880 }
10981
@@ -129,14 +101,18 @@ contract ERC20Core is ERC20, HookInstaller, Ownable, Multicallable, IERC20HookIn
129101 return contractURI_;
130102 }
131103
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 ;
140116 }
141117
142118 /*//////////////////////////////////////////////////////////////
@@ -223,19 +199,12 @@ contract ERC20Core is ERC20, HookInstaller, Ownable, Multicallable, IERC20HookIn
223199 INTERNAL FUNCTIONS
224200 //////////////////////////////////////////////////////////////*/
225201
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 ();
234204 }
235205
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 ();
239208 }
240209
241210 /// @dev Sets contract URI
@@ -245,19 +214,19 @@ contract ERC20Core is ERC20, HookInstaller, Ownable, Multicallable, IERC20HookIn
245214 }
246215
247216 /*//////////////////////////////////////////////////////////////
248- HOOKS INTERNAL FUNCTIONS
217+ CALLBACK INTERNAL FUNCTIONS
249218 //////////////////////////////////////////////////////////////*/
250219
251220 /// @dev Calls the beforeMint hook.
252221 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 );
254223
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 }(
257226 abi.encodeWithSelector (BeforeMintHookERC20.beforeMintERC20.selector , _to, _amount, _data)
258227 );
259228
260- if (! success) _revert (returndata, ERC20CoreHookCallFailed .selector );
229+ if (! success) _revert (returndata, ERC20CoreCallbackFailed .selector );
261230 } else {
262231 // Revert if beforeMint hook is not installed to disable un-permissioned minting.
263232 revert ERC20CoreMintDisabled ();
@@ -266,37 +235,37 @@ contract ERC20Core is ERC20, HookInstaller, Ownable, Multicallable, IERC20HookIn
266235
267236 /// @dev Calls the beforeTransfer hook, if installed.
268237 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 );
270239
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 (
273242 abi.encodeWithSelector (BeforeTransferHookERC20.beforeTransferERC20.selector , _from, _to, _amount)
274243 );
275- if (! success) _revert (returndata, ERC20CoreHookCallFailed .selector );
244+ if (! success) _revert (returndata, ERC20CoreCallbackFailed .selector );
276245 }
277246 }
278247
279248 /// @dev Calls the beforeBurn hook, if installed.
280249 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 );
282251
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 }(
285254 abi.encodeWithSelector (BeforeBurnHookERC20.beforeBurnERC20.selector , _from, _amount, _data)
286255 );
287- if (! success) _revert (returndata, ERC20CoreHookCallFailed .selector );
256+ if (! success) _revert (returndata, ERC20CoreCallbackFailed .selector );
288257 }
289258 }
290259
291260 /// @dev Calls the beforeApprove hook, if installed.
292261 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 );
294263
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 (
297266 abi.encodeWithSelector (BeforeApproveHookERC20.beforeApproveERC20.selector , _from, _to, _amount)
298267 );
299- if (! success) _revert (returndata, ERC20CoreHookCallFailed .selector );
268+ if (! success) _revert (returndata, ERC20CoreCallbackFailed .selector );
300269 }
301270 }
302271}
0 commit comments