-
Notifications
You must be signed in to change notification settings - Fork 20
/
EVCUtil.sol
111 lines (92 loc) · 4.42 KB
/
EVCUtil.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: GPL-2.0-or-later
pragma solidity ^0.8.19;
import "../interfaces/IEthereumVaultConnector.sol";
/// @title EVCUtil
/// @dev This contract is an abstract base contract for interacting with the Ethereum Vault Connector (EVC).
/// It provides utility functions for authenticating the callers in the context of the EVC, a pattern for enforcing the
/// contracts to be called through the EVC.
abstract contract EVCUtil {
IEVC internal immutable evc;
error NotAuthorized();
error ControllerDisabled();
constructor(IEVC _evc) {
evc = _evc;
}
/// @notice Ensures that the msg.sender is the EVC by using the EVC callback functionality if necessary.
/// @dev Optional to use for functions requiring account and vault status checks to enforce predictable bahvior.
/// @dev If this modifier used in conjuction with any other modifier, it must appear as the first (outermost)
/// modifier of the function.
modifier callThroughEVC() virtual {
if (msg.sender == address(evc)) {
_;
} else {
bytes memory result = evc.call(address(this), msg.sender, 0, msg.data);
assembly {
return(add(32, result), mload(result))
}
}
}
/// @notice Ensures that the msg.sender is the EVC by using the EVC callback functionality if necessary.
/// @dev Optional to use for functions requiring account and vault status checks to enforce predictable bahvior.
/// @dev If this modifier used in conjuction with any other modifier, it must appear as the first (outermost)
/// modifier of the function.
/// @dev This modifier is used for payable functions because it forwards the value to the EVC.
modifier callThroughEVCPayable() virtual {
if (msg.sender == address(evc)) {
_;
} else {
bytes memory result = evc.call{value: msg.value}(address(this), msg.sender, msg.value, msg.data);
assembly {
return(add(32, result), mload(result))
}
}
}
/// @notice Ensures that the caller is the EVC in the appropriate context.
/// @dev Should be used for checkAccountStatus and checkVaultStatus functions.
modifier onlyEVCWithChecksInProgress() virtual {
if (msg.sender != address(evc) || !evc.areChecksInProgress()) {
revert NotAuthorized();
}
_;
}
/// @notice Retrieves the message sender in the context of the EVC.
/// @dev This function returns the account on behalf of which the current operation is being performed, which is
/// either msg.sender or the account authenticated by the EVC.
/// @return The address of the message sender.
function _msgSender() internal view virtual returns (address) {
address sender = msg.sender;
if (sender == address(evc)) {
(sender,) = evc.getCurrentOnBehalfOfAccount(address(0));
}
return sender;
}
/// @notice Retrieves the message sender in the context of the EVC for a borrow operation.
/// @dev This function returns the account on behalf of which the current operation is being performed, which is
/// either msg.sender or the account authenticated by the EVC. This function reverts if this contract is not enabled
/// as a controller for the account on behalf of which the operation is being executed.
/// @return The address of the message sender.
function _msgSenderForBorrow() internal view virtual returns (address) {
address sender = msg.sender;
bool controllerEnabled;
if (sender == address(evc)) {
(sender, controllerEnabled) = evc.getCurrentOnBehalfOfAccount(address(this));
} else {
controllerEnabled = evc.isControllerEnabled(sender, address(this));
}
if (!controllerEnabled) {
revert ControllerDisabled();
}
return sender;
}
/// @notice Retrieves the owner of an account from the EVC.
/// @dev Use with care. If the account is not registered on the EVC yet, the queried account address is returned.
/// @param account The address of the account.
/// @return owner The address of the account owner.
function _getAccountOwner(address account) internal view virtual returns (address owner) {
try evc.getAccountOwner(account) returns (address _owner) {
owner = _owner;
} catch {
owner = account;
}
}
}