1+ // SPDX-License-Identifier: MIT
2+ // @author: thirdweb (https://github.com/thirdweb-dev/dynamic-contracts)
3+
4+ pragma solidity ^ 0.8.0 ;
5+
6+ // Interface
7+ import "../interface/IBaseRouter.sol " ;
8+
9+ // Core
10+ import "../core/Router.sol " ;
11+
12+ // Utils
13+ import "./utils/StringSet.sol " ;
14+ import "./utils/DefaultExtensionSet.sol " ;
15+ import "./utils/ExtensionState.sol " ;
16+
17+ abstract contract BaseRouterWithDefaults is IBaseRouter , Router , ExtensionState {
18+ using StringSet for StringSet.Set;
19+
20+ /*///////////////////////////////////////////////////////////////
21+ State variables
22+ //////////////////////////////////////////////////////////////*/
23+
24+ /// @notice The DefaultExtensionSet that stores default extensions of the router.
25+ address public immutable defaultExtensionSet;
26+
27+ /*///////////////////////////////////////////////////////////////
28+ Constructor
29+ //////////////////////////////////////////////////////////////*/
30+
31+ constructor (Extension[] memory _extensions ) {
32+
33+ DefaultExtensionSet map = new DefaultExtensionSet ();
34+ defaultExtensionSet = address (map);
35+
36+ uint256 len = _extensions.length ;
37+
38+ for (uint256 i = 0 ; i < len; i += 1 ) {
39+ require (_canSetExtension (_extensions[i]), "BaseRouter: not authorized. " );
40+ map.setExtension (_extensions[i]);
41+ }
42+ }
43+
44+ /*///////////////////////////////////////////////////////////////
45+ ERC 165 logic
46+ //////////////////////////////////////////////////////////////*/
47+
48+ /// @dev See {IERC165-supportsInterface}.
49+ function supportsInterface (bytes4 interfaceId ) public view virtual override returns (bool ) {
50+ return interfaceId == type (IBaseRouter).interfaceId || super .supportsInterface (interfaceId);
51+ }
52+
53+ /*///////////////////////////////////////////////////////////////
54+ External functions
55+ //////////////////////////////////////////////////////////////*/
56+
57+ /// @dev Adds a new extension to the router.
58+ function addExtension (Extension memory _extension ) external {
59+ require (_canSetExtension (_extension), "BaseRouter: not authorized. " );
60+
61+ _addExtension (_extension);
62+ }
63+
64+ /// @dev Updates an existing extension in the router, or overrides a default extension.
65+ function updateExtension (Extension memory _extension ) external {
66+ require (_canSetExtension (_extension), "BaseRouter: not authorized. " );
67+
68+ _updateExtension (_extension);
69+ }
70+
71+ /// @dev Removes an existing extension from the router.
72+ function removeExtension (Extension memory _extension ) external {
73+ require (_canSetExtension (_extension), "BaseRouter: not authorized. " );
74+
75+ _removeExtension (_extension.metadata.name);
76+ }
77+
78+ /*///////////////////////////////////////////////////////////////
79+ View functions
80+ //////////////////////////////////////////////////////////////*/
81+
82+ /**
83+ * @notice Returns all extensions stored. Override default lugins stored in router are
84+ * given precedence over default extensions in DefaultExtensionSet.
85+ */
86+ function getAllExtensions () external view returns (Extension[] memory allExtensions ) {
87+ Extension[] memory defaultExtensions = IDefaultExtensionSet (defaultExtensionSet).getAllExtensions ();
88+ uint256 defaultExtensionsLen = defaultExtensions.length ;
89+
90+ string [] memory names = _extensionStateStorage ().extensionNames.values ();
91+ uint256 namesLen = names.length ;
92+
93+ uint256 overrides = 0 ;
94+ for (uint256 i = 0 ; i < defaultExtensionsLen; i += 1 ) {
95+ if (_extensionStateStorage ().extensionNames.contains (defaultExtensions[i].metadata.name)) {
96+ overrides += 1 ;
97+ }
98+ }
99+
100+ uint256 total = (namesLen + defaultExtensionsLen) - overrides;
101+
102+ allExtensions = new Extension [](total);
103+ uint256 idx = 0 ;
104+
105+ for (uint256 i = 0 ; i < defaultExtensionsLen; i += 1 ) {
106+ string memory name = defaultExtensions[i].metadata.name;
107+ if (! _extensionStateStorage ().extensionNames.contains (name)) {
108+ allExtensions[idx] = defaultExtensions[i];
109+ idx += 1 ;
110+ }
111+ }
112+
113+ for (uint256 i = 0 ; i < namesLen; i += 1 ) {
114+ allExtensions[idx] = _extensionStateStorage ().extensions[names[i]];
115+ idx += 1 ;
116+ }
117+ }
118+
119+ /// @dev Returns the extension metadata and functions for a given extension.
120+ function getExtension (string memory _extensionName ) public view returns (Extension memory ) {
121+ bool isLocalExtension = _extensionStateStorage ().extensionNames.contains (_extensionName);
122+
123+ return isLocalExtension ? _extensionStateStorage ().extensions[_extensionName] : IDefaultExtensionSet (defaultExtensionSet).getExtension (_extensionName);
124+ }
125+
126+ /// @dev Returns the extension's implementation smart contract address.
127+ function getExtensionImplementation (string memory _extensionName ) external view returns (address ) {
128+ return getExtension (_extensionName).metadata.implementation;
129+ }
130+
131+ /// @dev Returns all functions that belong to the given extension contract.
132+ function getAllFunctionsOfExtension (string memory _extensionName ) external view returns (ExtensionFunction[] memory ) {
133+ return getExtension (_extensionName).functions;
134+ }
135+
136+ /// @dev Returns the extension metadata for a given function.
137+ function getExtensionForFunction (bytes4 _functionSelector ) public view returns (ExtensionMetadata memory ) {
138+ ExtensionMetadata memory metadata = _extensionStateStorage ().extensionMetadata[_functionSelector];
139+
140+ bool isLocalExtension = metadata.implementation != address (0 );
141+
142+ return isLocalExtension ? metadata : IDefaultExtensionSet (defaultExtensionSet).getExtensionForFunction (_functionSelector);
143+ }
144+
145+ /// @dev Returns the extension implementation address stored in router, for the given function.
146+ function getImplementationForFunction (bytes4 _functionSelector )
147+ public
148+ view
149+ override
150+ returns (address extensionAddress )
151+ {
152+ return getExtensionForFunction (_functionSelector).implementation;
153+ }
154+
155+ /*///////////////////////////////////////////////////////////////
156+ Internal functions
157+ //////////////////////////////////////////////////////////////*/
158+
159+ /// @dev Returns whether a extension can be set in the given execution context.
160+ function _canSetExtension (Extension memory _extension ) internal view virtual returns (bool );
161+ }
0 commit comments