@openzeppelin/confidential-contracts 0.4.0 → 0.5.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/contracts/BatcherConfidential.json +5 -0
- package/build/contracts/CheckpointsConfidential.json +2 -2
- package/build/contracts/ERC7984.json +6 -28
- package/build/contracts/ERC7984BalanceCapHookModule.json +277 -0
- package/build/contracts/ERC7984ERC20Wrapper.json +6 -28
- package/build/contracts/ERC7984Freezable.json +6 -28
- package/build/contracts/ERC7984HolderCapHookModule.json +291 -0
- package/build/contracts/ERC7984HookModule.json +200 -0
- package/build/contracts/ERC7984Hooked.json +832 -0
- package/build/contracts/ERC7984IdentityCheck.json +691 -0
- package/build/contracts/ERC7984ObserverAccess.json +6 -28
- package/build/contracts/ERC7984Omnibus.json +6 -28
- package/build/contracts/ERC7984Restricted.json +6 -28
- package/build/contracts/ERC7984Rwa.json +61 -29
- package/build/contracts/ERC7984Utils.json +2 -2
- package/build/contracts/ERC7984Votes.json +6 -28
- package/build/contracts/FHESafeMath.json +2 -2
- package/build/contracts/IERC7984HookModule.json +151 -0
- package/build/contracts/IERC7984Rwa.json +87 -0
- package/build/contracts/IIdentityRegistry.json +30 -0
- package/finance/BatcherConfidential.sol +7 -3
- package/governance/utils/VotesConfidential.sol +2 -2
- package/interfaces/IERC7984HookModule.sol +39 -0
- package/interfaces/IERC7984Receiver.sol +3 -1
- package/interfaces/IERC7984Rwa.sol +28 -1
- package/package.json +1 -1
- package/token/ERC7984/ERC7984.sol +39 -28
- package/token/ERC7984/extensions/ERC7984ERC20Wrapper.sol +3 -3
- package/token/ERC7984/extensions/ERC7984Freezable.sol +3 -7
- package/token/ERC7984/extensions/ERC7984Hooked.sol +158 -0
- package/token/ERC7984/extensions/ERC7984IdentityCheck.sol +58 -0
- package/token/ERC7984/extensions/ERC7984Restricted.sol +3 -3
- package/token/ERC7984/extensions/ERC7984Rwa.sol +65 -28
- package/token/ERC7984/utils/ERC7984BalanceCapHookModule.sol +92 -0
- package/token/ERC7984/utils/ERC7984HolderCapHookModule.sol +145 -0
- package/token/ERC7984/utils/ERC7984HookModule.sol +170 -0
- package/utils/FHESafeMath.sol +26 -1
- package/utils/HandleAccessManager.sol +5 -3
- package/utils/structs/CheckpointsConfidential.sol +1 -2
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.5.0-rc.0) (token/ERC7984/utils/ERC7984HookModule.sol)
|
|
3
|
+
|
|
4
|
+
pragma solidity ^0.8.27;
|
|
5
|
+
|
|
6
|
+
import {FHE, ebool, euint64} from "@fhevm/solidity/lib/FHE.sol";
|
|
7
|
+
import {ERC165, IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
|
|
8
|
+
import {IERC7984HookModule} from "./../../../interfaces/IERC7984HookModule.sol";
|
|
9
|
+
import {HandleAccessManager} from "./../../../utils/HandleAccessManager.sol";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @dev An abstract base contract for building ERC-7984 hook modules. Compatible with {ERC7984Hooked}.
|
|
13
|
+
*/
|
|
14
|
+
abstract contract ERC7984HookModule is IERC7984HookModule, ERC165 {
|
|
15
|
+
/// @dev The caller `account` is not authorized to perform the operation.
|
|
16
|
+
error ERC7984HookModuleUnauthorizedAccount(address account);
|
|
17
|
+
|
|
18
|
+
/// @dev The caller `user` does not have access to the encrypted amount `amount`.
|
|
19
|
+
error ERC7984HookModuleUnauthorizedUseOfEncryptedAmount(euint64 amount, address user);
|
|
20
|
+
|
|
21
|
+
/// @dev The module is already installed for the given token.
|
|
22
|
+
error ERC7984HookModuleAlreadyInstalled(address token);
|
|
23
|
+
|
|
24
|
+
/// @dev The module is not installed for the given token.
|
|
25
|
+
error ERC7984HookModuleNotInstalled(address token);
|
|
26
|
+
|
|
27
|
+
mapping(address token => bool) private _installed;
|
|
28
|
+
|
|
29
|
+
/// @inheritdoc IERC7984HookModule
|
|
30
|
+
function preTransfer(address from, address to, euint64 encryptedAmount) public virtual returns (ebool) {
|
|
31
|
+
require(
|
|
32
|
+
FHE.isAllowed(encryptedAmount, msg.sender),
|
|
33
|
+
ERC7984HookModuleUnauthorizedUseOfEncryptedAmount(encryptedAmount, msg.sender)
|
|
34
|
+
);
|
|
35
|
+
ebool compliant = _preTransfer(msg.sender, from, to, encryptedAmount);
|
|
36
|
+
FHE.allowTransient(compliant, msg.sender);
|
|
37
|
+
return compliant;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/// @inheritdoc IERC7984HookModule
|
|
41
|
+
function postTransfer(address from, address to, euint64 encryptedAmount) public virtual {
|
|
42
|
+
require(
|
|
43
|
+
FHE.isAllowed(encryptedAmount, msg.sender),
|
|
44
|
+
ERC7984HookModuleUnauthorizedUseOfEncryptedAmount(encryptedAmount, msg.sender)
|
|
45
|
+
);
|
|
46
|
+
_postTransfer(msg.sender, from, to, encryptedAmount);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/// @inheritdoc IERC7984HookModule
|
|
50
|
+
function onInstall(bytes calldata initData) public virtual {
|
|
51
|
+
require(!_isModuleInstalled(msg.sender), ERC7984HookModuleAlreadyInstalled(msg.sender));
|
|
52
|
+
|
|
53
|
+
_onInstall(msg.sender, initData);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// @inheritdoc IERC7984HookModule
|
|
57
|
+
function onUninstall(bytes calldata deinitData) public virtual {
|
|
58
|
+
require(_isModuleInstalled(msg.sender), ERC7984HookModuleNotInstalled(msg.sender));
|
|
59
|
+
|
|
60
|
+
_onUninstall(msg.sender, deinitData);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/// @inheritdoc ERC165
|
|
64
|
+
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
|
|
65
|
+
return interfaceId == type(IERC7984HookModule).interfaceId || super.supportsInterface(interfaceId);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @dev Internal function which may be overridden by the derived contract to perform actions
|
|
70
|
+
* when the module is installed.
|
|
71
|
+
*/
|
|
72
|
+
function _onInstall(address token, bytes calldata /* initData */) internal virtual {
|
|
73
|
+
_installed[token] = true;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @dev Internal function which may be overridden by the derived contract to perform actions
|
|
78
|
+
* when the module is uninstalled.
|
|
79
|
+
*/
|
|
80
|
+
function _onUninstall(address token, bytes calldata /* deinitData */) internal virtual {
|
|
81
|
+
delete _installed[token];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @dev Internal function which runs before a transfer. Transient access is already granted to the module
|
|
86
|
+
* for `encryptedAmount`. If additional handle access is needed from the token, call {_getTokenHandleAllowance}.
|
|
87
|
+
*
|
|
88
|
+
* NOTE: ACL allowance on `encryptedAmount` is already checked for `msg.sender` in {preTransfer}.
|
|
89
|
+
*/
|
|
90
|
+
function _preTransfer(
|
|
91
|
+
address /* token */,
|
|
92
|
+
address /* from */,
|
|
93
|
+
address /* to */,
|
|
94
|
+
euint64 /* encryptedAmount */
|
|
95
|
+
) internal virtual returns (ebool) {
|
|
96
|
+
return FHE.asEbool(true);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @dev Internal function which performs operations after transfers. Transient access is already granted to the module
|
|
101
|
+
* for `encryptedAmount`. If additional handle access is needed from the token, call {_getTokenHandleAllowance}.
|
|
102
|
+
*
|
|
103
|
+
* NOTE: ACL allowance on `encryptedAmount` is already checked for `msg.sender` in {postTransfer}.
|
|
104
|
+
*/
|
|
105
|
+
function _postTransfer(
|
|
106
|
+
address /*token*/,
|
|
107
|
+
address /*from*/,
|
|
108
|
+
address /*to*/,
|
|
109
|
+
euint64 /*encryptedAmount*/
|
|
110
|
+
) internal virtual {
|
|
111
|
+
// default to no-op
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @dev Check if the module is installed for the given token. The default implementation reads from
|
|
116
|
+
* an internal storage flag maintained by {onInstall} and {onUninstall}. Derived contracts may override
|
|
117
|
+
* to extend the check, but should typically rely on the default behavior.
|
|
118
|
+
*
|
|
119
|
+
* NOTE: This function should use internal storage to check if the module is installed for the given token.
|
|
120
|
+
* Do not use external storage like {ERC7984Hooked-isModuleInstalled}.
|
|
121
|
+
*/
|
|
122
|
+
function _isModuleInstalled(address token) internal view virtual returns (bool) {
|
|
123
|
+
return _installed[token];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/// @dev Allow modules to get access to token handles during transaction.
|
|
127
|
+
function _getTokenHandleAllowance(address token, euint64 handle) internal virtual {
|
|
128
|
+
_getTokenHandleAllowance(token, handle, false);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/// @dev Allow modules to get access to token handles.
|
|
132
|
+
function _getTokenHandleAllowance(address token, euint64 handle, bool persistent) internal virtual {
|
|
133
|
+
if (FHE.isInitialized(handle)) {
|
|
134
|
+
HandleAccessManager(token).getHandleAllowance(euint64.unwrap(handle), address(this), persistent);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* @dev Optionally emit the result of the pre-transfer hook.
|
|
140
|
+
*
|
|
141
|
+
* Grants persistent ACL on `compliant` to both this contract and `from`.
|
|
142
|
+
*/
|
|
143
|
+
function _emitPreTransferResults(
|
|
144
|
+
address token,
|
|
145
|
+
address from,
|
|
146
|
+
address to,
|
|
147
|
+
euint64 encryptedAmount,
|
|
148
|
+
ebool compliant,
|
|
149
|
+
bytes32 context
|
|
150
|
+
) internal virtual {
|
|
151
|
+
if (FHE.isInitialized(compliant)) {
|
|
152
|
+
if (from != address(0)) {
|
|
153
|
+
FHE.allowThis(compliant);
|
|
154
|
+
FHE.allow(compliant, from);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
emit ERC7984HookModuleResult(token, from, to, encryptedAmount, compliant, context);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* @dev Get transient ACL allowance for the given handle from a contract that inherits {HandleAccessManager}.
|
|
162
|
+
*
|
|
163
|
+
* Additionally verifies that the token is authorized to access the handle.
|
|
164
|
+
*/
|
|
165
|
+
function _accessHandle(address token, euint64 handle) internal {
|
|
166
|
+
if (!FHE.isInitialized(handle)) return;
|
|
167
|
+
require(FHE.isAllowed(handle, token), ERC7984HookModuleUnauthorizedUseOfEncryptedAmount(handle, token));
|
|
168
|
+
_getTokenHandleAllowance(token, handle, false);
|
|
169
|
+
}
|
|
170
|
+
}
|
package/utils/FHESafeMath.sol
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.5.0-rc.0) (utils/FHESafeMath.sol)
|
|
3
3
|
pragma solidity ^0.8.24;
|
|
4
4
|
|
|
5
5
|
import {FHE, ebool, euint64} from "@fhevm/solidity/lib/FHE.sol";
|
|
@@ -72,4 +72,29 @@ library FHESafeMath {
|
|
|
72
72
|
success = FHE.le(difference, a);
|
|
73
73
|
res = FHE.select(success, difference, FHE.asEuint64(0));
|
|
74
74
|
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @dev Add `a` and `b` saturating at `type(uint64).max` on overflow. The returned value is the sum
|
|
78
|
+
* of `a` and `b` if it does not overflow, otherwise `type(uint64).max`.
|
|
79
|
+
*/
|
|
80
|
+
function saturatingAdd(euint64 a, euint64 b) internal returns (euint64) {
|
|
81
|
+
if (!FHE.isInitialized(a)) {
|
|
82
|
+
return b;
|
|
83
|
+
}
|
|
84
|
+
if (!FHE.isInitialized(b)) {
|
|
85
|
+
return a;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
euint64 sum = FHE.add(a, b);
|
|
89
|
+
return FHE.select(FHE.ge(sum, a), sum, FHE.asEuint64(type(uint64).max));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @dev Subtract `b` from `a` saturating at zero on underflow. The returned value is `a - b` if
|
|
94
|
+
* `a >= b`, otherwise 0.
|
|
95
|
+
*/
|
|
96
|
+
function saturatingSub(euint64 a, euint64 b) internal returns (euint64) {
|
|
97
|
+
euint64 minB = FHE.min(a, b);
|
|
98
|
+
return FHE.sub(a, minB);
|
|
99
|
+
}
|
|
75
100
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.5.0-rc.0) (utils/HandleAccessManager.sol)
|
|
3
3
|
pragma solidity ^0.8.26;
|
|
4
4
|
|
|
5
5
|
import {Impl} from "@fhevm/solidity/lib/Impl.sol";
|
|
@@ -23,8 +23,10 @@ abstract contract HandleAccessManager {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
* @dev
|
|
26
|
+
* @dev Validation function that must return true if the message sender is allowed to call
|
|
27
27
|
* {getHandleAllowance} for the given handle.
|
|
28
28
|
*/
|
|
29
|
-
function _validateHandleAllowance(bytes32
|
|
29
|
+
function _validateHandleAllowance(bytes32) internal view virtual returns (bool) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
30
32
|
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.5.0-rc.0) (utils/structs/CheckpointsConfidential.sol)
|
|
3
3
|
// This file was procedurally generated from scripts/generate/templates/CheckpointsConfidential.js.
|
|
4
4
|
|
|
5
5
|
pragma solidity ^0.8.24;
|
|
6
6
|
|
|
7
7
|
import {euint32, euint64} from "@fhevm/solidity/lib/FHE.sol";
|
|
8
|
-
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
|
|
9
8
|
import {Checkpoints} from "@openzeppelin/contracts/utils/structs/Checkpoints.sol";
|
|
10
9
|
|
|
11
10
|
/**
|