Skip to content

Commit 0b61cff

Browse files
committed
added distributor instances categorization by instance id referencing distribution id
1 parent 20cee6e commit 0b61cff

File tree

5 files changed

+95
-28
lines changed

5 files changed

+95
-28
lines changed

.changeset/big-cheetahs-dream.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@peeramid-labs/eds": major
3+
---
4+
5+
added distributor instances categorization by instance id referencing distribution id

src/abstracts/Distributor.sol

+53-26
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,29 @@ import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
77
import "../interfaces/IInitializer.sol";
88
import "../abstracts/CodeIndexer.sol";
99
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
10-
abstract contract Distributor is IDistributor, CodeIndexer, ERC165{
11-
10+
abstract contract Distributor is IDistributor, CodeIndexer, ERC165 {
1211
struct DistributionComponent {
1312
bytes32 id;
1413
address initializer;
1514
}
1615
using EnumerableSet for EnumerableSet.Bytes32Set;
1716
EnumerableSet.Bytes32Set private distirbutionsSet;
1817
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;
2021
mapping(bytes32 => DistributionComponent) private distributionComponents;
2122

2223
function getDistributions() public view returns (bytes32[] memory) {
2324
return distirbutionsSet.values();
2425
}
2526

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];
2933
}
3034

3135
function getDistributionURI(bytes32 distributorsId) public view returns (string memory) {
@@ -37,10 +41,10 @@ abstract contract Distributor is IDistributor, CodeIndexer, ERC165{
3741
function _addDistribution(bytes32 id, address initializerAddress) internal virtual {
3842
ICodeIndex codeIndex = getContractsIndex();
3943
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));
4145
if (distirbutionsSet.contains(distributorsId)) revert DistributionExists(distributorsId);
4246
distirbutionsSet.add(distributorsId);
43-
distributionComponents[distributorsId] = DistributionComponent(id, initializerAddress);
47+
distributionComponents[distributorsId] = DistributionComponent(id, initializerAddress);
4448
emit DistributionAdded(id, initializerAddress);
4549
}
4650

@@ -51,51 +55,74 @@ abstract contract Distributor is IDistributor, CodeIndexer, ERC165{
5155
emit DistributionRemoved(distributorsId);
5256
}
5357

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) {
5562
ICodeIndex codeIndex = getContractsIndex();
5663
if (!distirbutionsSet.contains(distributorsId)) revert DistributionNotFound(distributorsId);
5764
DistributionComponent memory distributionComponent = distributionComponents[distributorsId];
5865
address initializer = address(initializers[distributionComponent.id]);
5966
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);
6270
if (initializer != address(0)) {
6371
(bool success, bytes memory result) = address(distributionComponent.initializer).delegatecall(
6472
abi.encodeWithSelector(selector, instances, args)
6573
);
6674
require(success, string(result));
6775
}
76+
uint256 instanceId = numInstances;
6877
for (uint256 i = 0; i < instances.length; i++) {
69-
distributionOf[instances[i]] = distributorsId;
78+
instanceIds[instances[i]] = instanceId;
79+
distributionOf[instanceId] = distributorsId;
7080
}
71-
emit Instantiated(distributorsId, args);
81+
emit Instantiated(distributorsId, args, instances);
7282
return (instances, distributionName, distributionVersion);
7383
}
7484

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+
*/
7593
function beforeCall(
7694
bytes memory,
7795
bytes4,
78-
address instance,
96+
address maybeInstance,
7997
uint256,
8098
bytes memory
8199
) 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
85108
return abi.encode(distributorsId, "");
86-
} else {
87-
revert InvalidInstance(instance);
88109
}
110+
revert InvalidInstance(maybeInstance);
89111
}
90112

91113
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+
}
99126

100127
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
101128
return interfaceId == type(IDistributor).interfaceId || super.supportsInterface(interfaceId);

src/abstracts/VersionDistributor.sol

-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ abstract contract VersionDistributor is IVersionDistributor, CodeIndexer {
2828
if (!ERC165Checker.supportsInterface(address(repository), type(IRepository).interfaceId)) {
2929
revert InvalidRepository(repository);
3030
}
31-
ICodeIndex codeIndex = getContractsIndex();
3231
initializers[address(repository)] = IInitializer(initializer);
3332
_repositories.add(address(repository));
3433
versions[address(repository)] = version;
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity >=0.8.0 <0.9.0;
3+
4+
import "../abstracts/CloneDistribution.sol";
5+
6+
contract SACMDistribution is CloneDistribution {
7+
bytes32 immutable metadata;
8+
address immutable _reference;
9+
bytes32 immutable public distributionName;
10+
uint256 immutable public distributionVersion;
11+
12+
constructor(bytes32 codeHash, bytes32 _metadata, bytes32 name, uint256 version) {
13+
distributionName = name;
14+
distributionVersion = version;
15+
metadata = _metadata;
16+
ICodeIndex index = getContractsIndex();
17+
_reference = index.get(codeHash);
18+
if (_reference == address(0)) {
19+
revert("CodeHashDistribution: CodeHash not found in index");
20+
}
21+
}
22+
23+
function sources() internal view virtual override returns (address[] memory, bytes32 name, uint256 version) {
24+
address[] memory _sources = new address[](1);
25+
_sources[0] = _reference;
26+
return (_sources, distributionName, distributionVersion);
27+
}
28+
29+
function getMetadata() public view virtual override returns (string memory) {
30+
return string(abi.encodePacked(metadata)); //ToDo: Add IPFS link with readme!
31+
}
32+
}

src/interfaces/IDistributor.sol

+5-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ interface IDistributor is IERC7746, IERC165 {
1010
error DistributionExists(bytes32 id);
1111
error InitializerNotFound(bytes32 id);
1212
error InvalidInstance(address instance);
13-
event Instantiated(bytes32 indexed distributionId, bytes indexed argsHash);
13+
event Instantiated(bytes32 indexed distributionId, bytes indexed argsHash, address[] instances);
1414
event DistributionRemoved(bytes32 indexed id);
1515

1616
event DistributionAdded(bytes32 indexed id, address indexed initializer);
@@ -27,4 +27,8 @@ interface IDistributor is IERC7746, IERC165 {
2727
function addDistribution(bytes32 distributorId, address initializer) external;
2828

2929
function removeDistribution(bytes32 distributorId) external;
30+
31+
function getDistributionId(address instance) external view returns (bytes32);
32+
function getInstanceId(address instance) external view returns (uint256);
33+
3034
}

0 commit comments

Comments
 (0)