-
Notifications
You must be signed in to change notification settings - Fork 11
/
CallFacet.sol
111 lines (90 loc) · 3.17 KB
/
CallFacet.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
// SPDX-License-Identifier: MIT
pragma experimental ABIEncoderV2;
pragma solidity ^0.7.1;
import "diamond-2/contracts/libraries/LibDiamond.sol";
import "../../interfaces/ICallFacet.sol";
import "../shared/Reentry/ReentryProtection.sol";
import "../shared/Access/CallProtection.sol";
import "./LibCallStorage.sol";
contract CallFacet is ReentryProtection, ICallFacet {
// uses modified call protection modifier to also allow whitelisted addresses to call
modifier protectedCall() {
require(
msg.sender == LibDiamond.diamondStorage().contractOwner ||
LibCallStorage.callStorage().canCall[msg.sender] ||
msg.sender == address(this), "NOT_ALLOWED"
);
_;
}
function addCaller(address _caller) external override {
require(msg.sender == LibDiamond.diamondStorage().contractOwner, "NOT_ALLOWED");
LibCallStorage.CallStorage storage callStorage = LibCallStorage.callStorage();
require(!callStorage.canCall[_caller], "IS_ALREADY_CALLER");
callStorage.callers.push(_caller);
callStorage.canCall[_caller] = true;
emit CallerAdded(_caller);
}
function removeCaller(address _caller) external override {
require(msg.sender == LibDiamond.diamondStorage().contractOwner, "NOT_ALLOWED");
LibCallStorage.CallStorage storage callStorage = LibCallStorage.callStorage();
require(callStorage.canCall[_caller], "IS_NOT_CALLER");
callStorage.canCall[_caller] = false;
for(uint256 i = 0; i < callStorage.callers.length; i ++) {
address currentCaller = callStorage.callers[i];
// if found remove it
if(currentCaller == _caller) {
callStorage.callers[i] = callStorage.callers[callStorage.callers.length - 1];
callStorage.callers.pop();
break;
}
}
emit CallerRemoved(_caller);
}
function call(
address[] memory _targets,
bytes[] memory _calldata,
uint256[] memory _values
) public override noReentry protectedCall {
require(
_targets.length == _calldata.length && _values.length == _calldata.length,
"ARRAY_LENGTH_MISMATCH"
);
for (uint256 i = 0; i < _targets.length; i++) {
_call(_targets[i], _calldata[i], _values[i]);
}
}
function callNoValue(
address[] memory _targets,
bytes[] memory _calldata
) public override noReentry protectedCall {
require(
_targets.length == _calldata.length,
"ARRAY_LENGTH_MISMATCH"
);
for (uint256 i = 0; i < _targets.length; i++) {
_call(_targets[i], _calldata[i], 0);
}
}
function singleCall(
address _target,
bytes calldata _calldata,
uint256 _value
) external override noReentry protectedCall {
_call(_target, _calldata, _value);
}
function _call(
address _target,
bytes memory _calldata,
uint256 _value
) internal {
(bool success, ) = _target.call{ value: _value }(_calldata);
require(success, "CALL_FAILED");
emit Call(_target, _calldata, _value);
}
function canCall(address _caller) external view override returns (bool) {
return LibCallStorage.callStorage().canCall[_caller];
}
function getCallers() external view override returns (address[] memory) {
return LibCallStorage.callStorage().callers;
}
}