-
Notifications
You must be signed in to change notification settings - Fork 621
/
Copy pathLibAccessLayers.sol
150 lines (135 loc) · 4.49 KB
/
LibAccessLayers.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// SPDX-License-Identifier: CC0-1.0
pragma solidity =0.8.20;
import "../ILayer.sol";
library LibAccessLayers {
bytes32 constant ACCESS_LAYERS_STORAGE_POSITION = keccak256("lib.access.layer.storage");
struct LayerStruct {
address layerAddress;
bytes4 beforeSig;
bytes4 afterSig;
bytes layerConfigData;
}
function accessLayersStorage() internal pure returns (LayerStruct[] storage ls) {
bytes32 position = ACCESS_LAYERS_STORAGE_POSITION;
assembly {
ls.slot := position
}
}
function setLayer(
address layerAddress,
uint256 layerIndex,
bytes memory layerConfigData,
bytes4 beforeCallMethodSignature,
bytes4 afterCallMethodSignature
) internal {
LayerStruct[] storage ls = accessLayersStorage();
ls[layerIndex].layerAddress = layerAddress;
ls[layerIndex].layerConfigData = layerConfigData;
ls[layerIndex].beforeSig = beforeCallMethodSignature;
ls[layerIndex].afterSig = afterCallMethodSignature;
}
function addLayer(LayerStruct memory newLayer) internal {
LayerStruct[] storage ls = accessLayersStorage();
ls.push(newLayer);
}
function setLayers(LayerStruct[] memory newLayers) internal {
for (uint256 i = 0; i < newLayers.length; i++) {
addLayer(newLayers[i]);
}
}
function addLayer(
address layerAddress,
bytes memory layerConfigData,
bytes4 beforeCallMethodSignature,
bytes4 afterCallMethodSignature
) internal {
LayerStruct[] storage ls = accessLayersStorage();
LayerStruct memory newLayer = LayerStruct({
layerAddress: layerAddress,
layerConfigData: layerConfigData,
beforeSig: beforeCallMethodSignature,
afterSig: afterCallMethodSignature
});
ls.push(newLayer);
}
function popLayer() internal {
LayerStruct[] storage ls = accessLayersStorage();
ls.pop();
}
function getLayer(uint256 layerIdx) internal view returns (LayerStruct storage) {
LayerStruct[] storage ls = accessLayersStorage();
return ls[layerIdx];
}
function beforeCall(
bytes4 _selector,
address sender,
bytes calldata data,
uint256 value
) internal returns (bytes[] memory) {
LayerStruct[] storage ls = accessLayersStorage();
bytes[] memory layerReturns = new bytes[](ls.length);
for (uint256 i = 0; i < ls.length; i++) {
layerReturns[i] = validateLayerBeforeCall(ls[i], _selector, sender, data, value);
}
return layerReturns;
}
function validateLayerBeforeCall(
LayerStruct storage layer,
bytes4 _selector,
address sender,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
bytes memory retval = ILayer(layer.layerAddress).beforeCallValidation(
layer.layerConfigData,
_selector,
sender,
value,
data
);
return retval;
}
function afterCall(
bytes4 _selector,
address sender,
bytes calldata data,
uint256 value,
bytes[] memory beforeCallReturns
) internal {
LayerStruct[] storage ls = accessLayersStorage();
for (uint256 i = 0; i < ls.length; i++) {
validateLayerAfterCall(ls[ls.length - 1 - i], _selector, sender, data, value, beforeCallReturns[i]);
}
}
function extractRevertReason(bytes memory revertData) internal pure returns (string memory reason) {
uint l = revertData.length;
if (l < 68) return "";
uint t;
assembly {
revertData := add(revertData, 4)
t := mload(revertData) // Save the content of the length slot
mstore(revertData, sub(l, 4)) // Set proper length
}
reason = abi.decode(revertData, (string));
assembly {
mstore(revertData, t) // Restore the content of the length slot
}
}
function validateLayerAfterCall(
LayerStruct storage layer,
bytes4 _selector,
address sender,
bytes calldata data,
uint256 value,
bytes memory beforeCallReturnValue
) internal {
ILayer(layer.layerAddress).afterCallValidation(
layer.layerConfigData,
_selector,
sender,
value,
data,
beforeCallReturnValue
);
}
}