@@ -7,25 +7,29 @@ import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
7
7
import "../interfaces/IInitializer.sol " ;
8
8
import "../abstracts/CodeIndexer.sol " ;
9
9
import "@openzeppelin/contracts/utils/introspection/ERC165.sol " ;
10
- abstract contract Distributor is IDistributor , CodeIndexer , ERC165 {
11
-
10
+ abstract contract Distributor is IDistributor , CodeIndexer , ERC165 {
12
11
struct DistributionComponent {
13
12
bytes32 id;
14
13
address initializer;
15
14
}
16
15
using EnumerableSet for EnumerableSet.Bytes32Set;
17
16
EnumerableSet.Bytes32Set private distirbutionsSet;
18
17
mapping (bytes32 => IInitializer) private initializers;
19
- mapping (address => bytes32 ) private distributionOf;
18
+ mapping (address => uint256 ) private instanceIds;
19
+ uint256 numInstances;
20
+ mapping (uint256 => bytes32 ) public distributionOf;
20
21
mapping (bytes32 => DistributionComponent) private distributionComponents;
21
22
22
23
function getDistributions () public view returns (bytes32 [] memory ) {
23
24
return distirbutionsSet.values ();
24
25
}
25
26
26
- function distributionId (address instance ) public view virtual returns (bytes32 instanceId )
27
- {
28
- return distributionOf[instance];
27
+ function getDistributionId (address instance ) public view virtual returns (bytes32 ) {
28
+ return distributionOf[getInstanceId (instance)];
29
+ }
30
+
31
+ function getInstanceId (address instance ) public view virtual returns (uint256 ) {
32
+ return instanceIds[instance];
29
33
}
30
34
31
35
function getDistributionURI (bytes32 distributorsId ) public view returns (string memory ) {
@@ -37,10 +41,10 @@ abstract contract Distributor is IDistributor, CodeIndexer, ERC165{
37
41
function _addDistribution (bytes32 id , address initializerAddress ) internal virtual {
38
42
ICodeIndex codeIndex = getContractsIndex ();
39
43
if (codeIndex.get (id) == address (0 )) revert DistributionNotFound (id);
40
- bytes32 distributorsId = keccak256 (abi.encode (id,initializerAddress));
44
+ bytes32 distributorsId = keccak256 (abi.encode (id, initializerAddress));
41
45
if (distirbutionsSet.contains (distributorsId)) revert DistributionExists (distributorsId);
42
46
distirbutionsSet.add (distributorsId);
43
- distributionComponents[distributorsId] = DistributionComponent (id, initializerAddress);
47
+ distributionComponents[distributorsId] = DistributionComponent (id, initializerAddress);
44
48
emit DistributionAdded (id, initializerAddress);
45
49
}
46
50
@@ -51,51 +55,74 @@ abstract contract Distributor is IDistributor, CodeIndexer, ERC165{
51
55
emit DistributionRemoved (distributorsId);
52
56
}
53
57
54
- function _instantiate (bytes32 distributorsId , bytes memory args ) internal virtual returns (address [] memory instances , bytes32 distributionName , uint256 distributionVersion ) {
58
+ function _instantiate (
59
+ bytes32 distributorsId ,
60
+ bytes memory args
61
+ ) internal virtual returns (address [] memory instances , bytes32 distributionName , uint256 distributionVersion ) {
55
62
ICodeIndex codeIndex = getContractsIndex ();
56
63
if (! distirbutionsSet.contains (distributorsId)) revert DistributionNotFound (distributorsId);
57
64
DistributionComponent memory distributionComponent = distributionComponents[distributorsId];
58
65
address initializer = address (initializers[distributionComponent.id]);
59
66
bytes4 selector = IInitializer.initialize.selector ;
60
- bytes memory instantiationArgs = initializer != address (0 ) ? args : bytes ("" );
61
- (instances, distributionName, distributionVersion) = IDistribution (codeIndex.get (distributionComponent.id)).instantiate (instantiationArgs);
67
+ // bytes memory instantiationArgs = initializer != address(0) ? args : bytes ("");
68
+ (instances, distributionName, distributionVersion) = IDistribution (codeIndex.get (distributionComponent.id))
69
+ .instantiate (args);
62
70
if (initializer != address (0 )) {
63
71
(bool success , bytes memory result ) = address (distributionComponent.initializer).delegatecall (
64
72
abi.encodeWithSelector (selector, instances, args)
65
73
);
66
74
require (success, string (result));
67
75
}
76
+ uint256 instanceId = numInstances;
68
77
for (uint256 i = 0 ; i < instances.length ; i++ ) {
69
- distributionOf[instances[i]] = distributorsId;
78
+ instanceIds[instances[i]] = instanceId;
79
+ distributionOf[instanceId] = distributorsId;
70
80
}
71
- emit Instantiated (distributorsId, args);
81
+ emit Instantiated (distributorsId, args, instances );
72
82
return (instances, distributionName, distributionVersion);
73
83
}
74
84
85
+ /*
86
+ * @dev This is ERC7746 implementation
87
+ * This hook must be called by instance methods that access scope is
88
+ * limited to the same instance or distribution
89
+ * it will revert if `msg.sender` is not a valid instance
90
+ * it will revert if `maybeInstance` is not a valid instance
91
+ * it will revert if instanceId belongs to disactivated distribution
92
+ */
75
93
function beforeCall (
76
94
bytes memory ,
77
95
bytes4 ,
78
- address instance ,
96
+ address maybeInstance ,
79
97
uint256 ,
80
98
bytes memory
81
99
) public view virtual returns (bytes memory ) {
82
- bytes32 distributorsId = distributionOf[instance];
83
- // DistributionComponent memory distributionComponent = distributionComponents[distributorsId];
84
- if (distributorsId != bytes32 (0 ) && distirbutionsSet.contains (distributorsId) == true ) {
100
+ bytes32 distributorsId = distributionOf[getInstanceId (maybeInstance)];
101
+ if (
102
+ distributorsId != bytes32 (0 ) &&
103
+ getInstanceId (msg .sender ) == getInstanceId (maybeInstance) &&
104
+ distirbutionsSet.contains (distributorsId) == true
105
+ ) {
106
+ // ToDo: This check could be based on DistributionOf, hence allowing cross-instance calls
107
+ // Use layerConfig to allow client to configure requirement for the call
85
108
return abi.encode (distributorsId, "" );
86
- } else {
87
- revert InvalidInstance (instance);
88
109
}
110
+ revert InvalidInstance (maybeInstance);
89
111
}
90
112
91
113
function afterCall (
92
- bytes memory layerConfig ,
93
- bytes4 selector ,
94
- address sender ,
95
- uint256 value ,
96
- bytes memory data ,
97
- bytes memory beforeCallResult
98
- ) public virtual {}
114
+ bytes memory ,
115
+ bytes4 ,
116
+ address maybeInstance ,
117
+ uint256 ,
118
+ bytes memory ,
119
+ bytes memory
120
+ ) public virtual {
121
+ bytes32 distributorsId = distributionOf[getInstanceId (maybeInstance)];
122
+ if (getInstanceId (msg .sender ) != getInstanceId (maybeInstance) && distirbutionsSet.contains (distributorsId) == true ) {
123
+ revert InvalidInstance (maybeInstance);
124
+ }
125
+ }
99
126
100
127
function supportsInterface (bytes4 interfaceId ) public view virtual override (ERC165 , IERC165 ) returns (bool ) {
101
128
return interfaceId == type (IDistributor).interfaceId || super .supportsInterface (interfaceId);
0 commit comments