Skip to content

Commit 6983f8c

Browse files
authored
Plugin architecture: permissionless Map (#291)
* forge update * Add permissionless Map * test for map * forge update
1 parent a02c7f7 commit 6983f8c

File tree

6 files changed

+743
-0
lines changed

6 files changed

+743
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity ^0.8.11;
3+
4+
interface IMap {
5+
struct ExtensionMap {
6+
bytes4 selector;
7+
address extension;
8+
}
9+
10+
event ExtensionRegistered(bytes4 indexed selector, address indexed extension);
11+
12+
function getExtensionForFunction(bytes4 _selector) external view returns (address);
13+
14+
function getAllFunctionsOfExtension(address _extension) external view returns (bytes4[] memory registered);
15+
16+
function getAllRegistered() external view returns (ExtensionMap[] memory registered);
17+
}

contracts/extension/plugin/Map.sol

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity ^0.8.0;
3+
4+
import "../interface/plugin/IMap.sol";
5+
6+
import "../Multicall.sol";
7+
import "../../openzeppelin-presets/utils/EnumerableSet.sol";
8+
9+
/**
10+
* TODO:
11+
* - Remove OZ EnumerableSet external dependency.
12+
*/
13+
14+
contract Map is IMap, Multicall {
15+
using EnumerableSet for EnumerableSet.Bytes32Set;
16+
17+
EnumerableSet.Bytes32Set private allSelectors;
18+
19+
mapping(address => EnumerableSet.Bytes32Set) private selectorsForExtension;
20+
mapping(bytes4 => address) private extension;
21+
22+
constructor(ExtensionMap[] memory _extensionsToRegister) {
23+
uint256 len = _extensionsToRegister.length;
24+
for (uint256 i = 0; i < len; i += 1) {
25+
_setExtensions(_extensionsToRegister[i].selector, _extensionsToRegister[i].extension);
26+
}
27+
}
28+
29+
function _setExtensions(bytes4 _selector, address _extension) internal {
30+
require(allSelectors.add(bytes32(_selector)), "REGISTERED");
31+
32+
extension[_selector] = _extension;
33+
selectorsForExtension[_extension].add(bytes32(_selector));
34+
35+
emit ExtensionRegistered(_selector, _extension);
36+
}
37+
38+
function getExtensionForFunction(bytes4 _selector) external view returns (address) {
39+
address ext = extension[_selector];
40+
require(ext != address(0), "No extension available for selector.");
41+
42+
return ext;
43+
}
44+
45+
function getAllFunctionsOfExtension(address _extension) external view returns (bytes4[] memory registered) {
46+
uint256 len = selectorsForExtension[_extension].length();
47+
registered = new bytes4[](len);
48+
49+
for (uint256 i = 0; i < len; i += 1) {
50+
registered[i] = bytes4(selectorsForExtension[_extension].at(i));
51+
}
52+
}
53+
54+
function getAllRegistered() external view returns (ExtensionMap[] memory functionExtensionPairs) {
55+
uint256 len = allSelectors.length();
56+
functionExtensionPairs = new ExtensionMap[](len);
57+
58+
for (uint256 i = 0; i < len; i += 1) {
59+
bytes4 selector = bytes4(allSelectors.at(i));
60+
functionExtensionPairs[i] = ExtensionMap(selector, extension[selector]);
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)