|
| 1 | +// SPDX-License-Identifier: Apache-2.0 |
| 2 | +pragma solidity ^0.8.0; |
| 3 | + |
| 4 | +import "../interface/plugin/IPluginMap.sol"; |
| 5 | +import "../../openzeppelin-presets/utils/EnumerableSet.sol"; |
| 6 | + |
| 7 | +contract PluginMap is IPluginMap { |
| 8 | + using EnumerableSet for EnumerableSet.Bytes32Set; |
| 9 | + |
| 10 | + EnumerableSet.Bytes32Set private allSelectors; |
| 11 | + |
| 12 | + mapping(address => EnumerableSet.Bytes32Set) private selectorsForPlugin; |
| 13 | + mapping(bytes4 => Plugin) private pluginForSelector; |
| 14 | + |
| 15 | + /*/////////////////////////////////////////////////////////////// |
| 16 | + Constructor + initializer logic |
| 17 | + //////////////////////////////////////////////////////////////*/ |
| 18 | + |
| 19 | + constructor(Plugin[] memory _pluginsToAdd) { |
| 20 | + uint256 len = _pluginsToAdd.length; |
| 21 | + for (uint256 i = 0; i < len; i += 1) { |
| 22 | + _setPlugin(_pluginsToAdd[i]); |
| 23 | + } |
| 24 | + } |
| 25 | + |
| 26 | + /*/////////////////////////////////////////////////////////////// |
| 27 | + View functions |
| 28 | + //////////////////////////////////////////////////////////////*/ |
| 29 | + |
| 30 | + /// @dev View address of the plugged-in functionality contract for a given function signature. |
| 31 | + function getPluginForFunction(bytes4 _selector) public view returns (address) { |
| 32 | + address _pluginAddress = pluginForSelector[_selector].pluginAddress; |
| 33 | + require(_pluginAddress != address(0), "Map: No plugin available for selector"); |
| 34 | + |
| 35 | + return _pluginAddress; |
| 36 | + } |
| 37 | + |
| 38 | + /// @dev View all funtionality as list of function signatures. |
| 39 | + function getAllFunctionsOfPlugin(address _pluginAddress) external view returns (bytes4[] memory registered) { |
| 40 | + uint256 len = selectorsForPlugin[_pluginAddress].length(); |
| 41 | + registered = new bytes4[](len); |
| 42 | + |
| 43 | + for (uint256 i = 0; i < len; i += 1) { |
| 44 | + registered[i] = bytes4(selectorsForPlugin[_pluginAddress].at(i)); |
| 45 | + } |
| 46 | + } |
| 47 | + |
| 48 | + /// @dev View all funtionality existing on the contract. |
| 49 | + function getAllPlugins() external view returns (Plugin[] memory _plugins) { |
| 50 | + uint256 len = allSelectors.length(); |
| 51 | + _plugins = new Plugin[](len); |
| 52 | + |
| 53 | + for (uint256 i = 0; i < len; i += 1) { |
| 54 | + bytes4 selector = bytes4(allSelectors.at(i)); |
| 55 | + _plugins[i] = pluginForSelector[selector]; |
| 56 | + } |
| 57 | + } |
| 58 | + |
| 59 | + /*/////////////////////////////////////////////////////////////// |
| 60 | + Internal functions |
| 61 | + //////////////////////////////////////////////////////////////*/ |
| 62 | + |
| 63 | + /// @dev Add functionality to the contract. |
| 64 | + function _setPlugin(Plugin memory _plugin) internal { |
| 65 | + require(allSelectors.add(bytes32(_plugin.functionSelector)), "Map: Selector exists"); |
| 66 | + require( |
| 67 | + _plugin.functionSelector == bytes4(keccak256(abi.encodePacked(_plugin.functionSignature))), |
| 68 | + "Map: Incorrect selector" |
| 69 | + ); |
| 70 | + |
| 71 | + pluginForSelector[_plugin.functionSelector] = _plugin; |
| 72 | + selectorsForPlugin[_plugin.pluginAddress].add(bytes32(_plugin.functionSelector)); |
| 73 | + |
| 74 | + emit PluginSet(_plugin.functionSelector, _plugin.functionSignature, _plugin.pluginAddress); |
| 75 | + } |
| 76 | +} |
0 commit comments