@openzeppelin/confidential-contracts 0.2.0-rc.2 → 0.3.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.
Files changed (44) hide show
  1. package/build/contracts/Checkpoints.json +2 -2
  2. package/build/contracts/CheckpointsConfidential.json +3 -9
  3. package/build/contracts/{ConfidentialFungibleToken.json → ERC7984.json} +28 -33
  4. package/build/contracts/{ConfidentialFungibleTokenERC20Wrapper.json → ERC7984ERC20Wrapper.json} +34 -39
  5. package/build/contracts/ERC7984Freezable.json +666 -0
  6. package/build/contracts/ERC7984ObserverAccess.json +676 -0
  7. package/build/contracts/ERC7984Omnibus.json +994 -0
  8. package/build/contracts/ERC7984Restricted.json +677 -0
  9. package/build/contracts/ERC7984Rwa.json +1370 -0
  10. package/build/contracts/{ConfidentialFungibleTokenUtils.json → ERC7984Utils.json} +4 -4
  11. package/build/contracts/{ConfidentialFungibleTokenVotes.json → ERC7984Votes.json} +99 -81
  12. package/build/contracts/{TFHESafeMath.json → FHESafeMath.json} +4 -4
  13. package/build/contracts/HandleAccessManager.json +34 -0
  14. package/build/contracts/{IConfidentialFungibleToken.json → IERC7984.json} +15 -15
  15. package/build/contracts/{IConfidentialFungibleTokenReceiver.json → IERC7984Receiver.json} +2 -2
  16. package/build/contracts/IERC7984Rwa.json +797 -0
  17. package/build/contracts/VestingWalletCliffConfidential.json +3 -3
  18. package/build/contracts/VestingWalletConfidential.json +3 -3
  19. package/build/contracts/VestingWalletConfidentialFactory.json +18 -153
  20. package/build/contracts/VotesConfidential.json +23 -0
  21. package/finance/ERC7821WithExecutor.sol +2 -2
  22. package/finance/VestingWalletCliffConfidential.sol +15 -4
  23. package/finance/VestingWalletConfidential.sol +32 -20
  24. package/finance/VestingWalletConfidentialFactory.sol +34 -123
  25. package/governance/utils/VotesConfidential.sol +18 -4
  26. package/interfaces/{IConfidentialFungibleToken.sol → IERC7984.sol} +6 -6
  27. package/interfaces/{IConfidentialFungibleTokenReceiver.sol → IERC7984Receiver.sol} +3 -3
  28. package/interfaces/IERC7984Rwa.sol +64 -0
  29. package/package.json +4 -4
  30. package/token/{ConfidentialFungibleToken.sol → ERC7984/ERC7984.sol} +73 -84
  31. package/token/{extensions/ConfidentialFungibleTokenERC20Wrapper.sol → ERC7984/extensions/ERC7984ERC20Wrapper.sol} +36 -27
  32. package/token/ERC7984/extensions/ERC7984Freezable.sol +66 -0
  33. package/token/ERC7984/extensions/ERC7984ObserverAccess.sol +63 -0
  34. package/token/ERC7984/extensions/ERC7984Omnibus.sol +209 -0
  35. package/token/ERC7984/extensions/ERC7984Restricted.sol +118 -0
  36. package/token/ERC7984/extensions/ERC7984Rwa.sol +236 -0
  37. package/token/ERC7984/extensions/ERC7984Votes.sol +31 -0
  38. package/token/{utils/ConfidentialFungibleTokenUtils.sol → ERC7984/utils/ERC7984Utils.sol} +12 -12
  39. package/utils/FHESafeMath.sol +72 -0
  40. package/utils/HandleAccessManager.sol +29 -0
  41. package/utils/structs/CheckpointsConfidential.sol +1 -6
  42. package/utils/structs/temporary-Checkpoints.sol +2 -2
  43. package/token/extensions/ConfidentialFungibleTokenVotes.sol +0 -29
  44. package/utils/TFHESafeMath.sol +0 -37
@@ -202,7 +202,7 @@
202
202
  "name": "released",
203
203
  "outputs": [
204
204
  {
205
- "internalType": "euint64",
205
+ "internalType": "euint128",
206
206
  "name": "",
207
207
  "type": "bytes32"
208
208
  }
@@ -251,9 +251,9 @@
251
251
  "type": "address"
252
252
  },
253
253
  {
254
- "internalType": "uint64",
254
+ "internalType": "uint48",
255
255
  "name": "timestamp",
256
- "type": "uint64"
256
+ "type": "uint48"
257
257
  }
258
258
  ],
259
259
  "name": "vestedAmount",
@@ -173,7 +173,7 @@
173
173
  "name": "released",
174
174
  "outputs": [
175
175
  {
176
- "internalType": "euint64",
176
+ "internalType": "euint128",
177
177
  "name": "",
178
178
  "type": "bytes32"
179
179
  }
@@ -222,9 +222,9 @@
222
222
  "type": "address"
223
223
  },
224
224
  {
225
- "internalType": "uint64",
225
+ "internalType": "uint48",
226
226
  "name": "timestamp",
227
- "type": "uint64"
227
+ "type": "uint48"
228
228
  }
229
229
  ],
230
230
  "name": "vestedAmount",
@@ -24,33 +24,6 @@
24
24
  "name": "InsufficientBalance",
25
25
  "type": "error"
26
26
  },
27
- {
28
- "inputs": [
29
- {
30
- "internalType": "address",
31
- "name": "owner",
32
- "type": "address"
33
- }
34
- ],
35
- "name": "OwnableInvalidOwner",
36
- "type": "error"
37
- },
38
- {
39
- "inputs": [
40
- {
41
- "internalType": "uint64",
42
- "name": "cliffSeconds",
43
- "type": "uint64"
44
- },
45
- {
46
- "internalType": "uint64",
47
- "name": "durationSeconds",
48
- "type": "uint64"
49
- }
50
- ],
51
- "name": "VestingWalletCliffConfidentialInvalidCliffDuration",
52
- "type": "error"
53
- },
54
27
  {
55
28
  "anonymous": false,
56
29
  "inputs": [
@@ -60,35 +33,11 @@
60
33
  "name": "vestingWalletConfidential",
61
34
  "type": "address"
62
35
  },
63
- {
64
- "indexed": true,
65
- "internalType": "address",
66
- "name": "beneficiary",
67
- "type": "address"
68
- },
69
36
  {
70
37
  "indexed": false,
71
- "internalType": "uint48",
72
- "name": "startTimestamp",
73
- "type": "uint48"
74
- },
75
- {
76
- "indexed": false,
77
- "internalType": "uint48",
78
- "name": "durationSeconds",
79
- "type": "uint48"
80
- },
81
- {
82
- "indexed": false,
83
- "internalType": "uint48",
84
- "name": "cliffSeconds",
85
- "type": "uint48"
86
- },
87
- {
88
- "indexed": true,
89
- "internalType": "address",
90
- "name": "executor",
91
- "type": "address"
38
+ "internalType": "bytes",
39
+ "name": "initArgs",
40
+ "type": "bytes"
92
41
  }
93
42
  ],
94
43
  "name": "VestingWalletConfidentialCreated",
@@ -106,44 +55,20 @@
106
55
  {
107
56
  "indexed": true,
108
57
  "internalType": "address",
109
- "name": "beneficiary",
110
- "type": "address"
111
- },
112
- {
113
- "indexed": true,
114
- "internalType": "address",
115
- "name": "confidentialFungibleToken",
58
+ "name": "token",
116
59
  "type": "address"
117
60
  },
118
61
  {
119
62
  "indexed": false,
120
63
  "internalType": "euint64",
121
- "name": "encryptedAmount",
64
+ "name": "transferredAmount",
122
65
  "type": "bytes32"
123
66
  },
124
67
  {
125
68
  "indexed": false,
126
- "internalType": "uint48",
127
- "name": "startTimestamp",
128
- "type": "uint48"
129
- },
130
- {
131
- "indexed": false,
132
- "internalType": "uint48",
133
- "name": "durationSeconds",
134
- "type": "uint48"
135
- },
136
- {
137
- "indexed": false,
138
- "internalType": "uint48",
139
- "name": "cliffSeconds",
140
- "type": "uint48"
141
- },
142
- {
143
- "indexed": false,
144
- "internalType": "address",
145
- "name": "executor",
146
- "type": "address"
69
+ "internalType": "bytes",
70
+ "name": "initArgs",
71
+ "type": "bytes"
147
72
  }
148
73
  ],
149
74
  "name": "VestingWalletConfidentialFunded",
@@ -153,46 +78,26 @@
153
78
  "inputs": [
154
79
  {
155
80
  "internalType": "address",
156
- "name": "confidentialFungibleToken",
81
+ "name": "token",
157
82
  "type": "address"
158
83
  },
159
84
  {
160
85
  "components": [
161
- {
162
- "internalType": "address",
163
- "name": "beneficiary",
164
- "type": "address"
165
- },
166
86
  {
167
87
  "internalType": "externalEuint64",
168
88
  "name": "encryptedAmount",
169
89
  "type": "bytes32"
170
90
  },
171
91
  {
172
- "internalType": "uint48",
173
- "name": "startTimestamp",
174
- "type": "uint48"
175
- },
176
- {
177
- "internalType": "uint48",
178
- "name": "durationSeconds",
179
- "type": "uint48"
180
- },
181
- {
182
- "internalType": "uint48",
183
- "name": "cliffSeconds",
184
- "type": "uint48"
92
+ "internalType": "bytes",
93
+ "name": "initArgs",
94
+ "type": "bytes"
185
95
  }
186
96
  ],
187
97
  "internalType": "struct VestingWalletConfidentialFactory.VestingPlan[]",
188
98
  "name": "vestingPlans",
189
99
  "type": "tuple[]"
190
100
  },
191
- {
192
- "internalType": "address",
193
- "name": "executor",
194
- "type": "address"
195
- },
196
101
  {
197
102
  "internalType": "bytes",
198
103
  "name": "inputProof",
@@ -207,29 +112,9 @@
207
112
  {
208
113
  "inputs": [
209
114
  {
210
- "internalType": "address",
211
- "name": "beneficiary",
212
- "type": "address"
213
- },
214
- {
215
- "internalType": "uint48",
216
- "name": "startTimestamp",
217
- "type": "uint48"
218
- },
219
- {
220
- "internalType": "uint48",
221
- "name": "durationSeconds",
222
- "type": "uint48"
223
- },
224
- {
225
- "internalType": "uint48",
226
- "name": "cliffSeconds",
227
- "type": "uint48"
228
- },
229
- {
230
- "internalType": "address",
231
- "name": "executor",
232
- "type": "address"
115
+ "internalType": "bytes",
116
+ "name": "initArgs",
117
+ "type": "bytes"
233
118
  }
234
119
  ],
235
120
  "name": "createVestingWalletConfidential",
@@ -246,29 +131,9 @@
246
131
  {
247
132
  "inputs": [
248
133
  {
249
- "internalType": "address",
250
- "name": "beneficiary",
251
- "type": "address"
252
- },
253
- {
254
- "internalType": "uint48",
255
- "name": "startTimestamp",
256
- "type": "uint48"
257
- },
258
- {
259
- "internalType": "uint48",
260
- "name": "durationSeconds",
261
- "type": "uint48"
262
- },
263
- {
264
- "internalType": "uint48",
265
- "name": "cliffSeconds",
266
- "type": "uint48"
267
- },
268
- {
269
- "internalType": "address",
270
- "name": "executor",
271
- "type": "address"
134
+ "internalType": "bytes",
135
+ "name": "initArgs",
136
+ "type": "bytes"
272
137
  }
273
138
  ],
274
139
  "name": "predictVestingWalletConfidential",
@@ -323,6 +323,29 @@
323
323
  "stateMutability": "view",
324
324
  "type": "function"
325
325
  },
326
+ {
327
+ "inputs": [
328
+ {
329
+ "internalType": "bytes32",
330
+ "name": "handle",
331
+ "type": "bytes32"
332
+ },
333
+ {
334
+ "internalType": "address",
335
+ "name": "account",
336
+ "type": "address"
337
+ },
338
+ {
339
+ "internalType": "bool",
340
+ "name": "persistent",
341
+ "type": "bool"
342
+ }
343
+ ],
344
+ "name": "getHandleAllowance",
345
+ "outputs": [],
346
+ "stateMutability": "nonpayable",
347
+ "type": "function"
348
+ },
326
349
  {
327
350
  "inputs": [
328
351
  {
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.2.0-rc.2) (finance/ERC7821WithExecutor.sol)
2
+ // OpenZeppelin Confidential Contracts (last updated v0.2.0) (finance/ERC7821WithExecutor.sol)
3
3
  pragma solidity ^0.8.20;
4
4
 
5
5
  import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
@@ -39,7 +39,7 @@ abstract contract ERC7821WithExecutor is Initializable, ERC7821 {
39
39
  }
40
40
 
41
41
  function _getERC7821WithExecutorStorage() private pure returns (ERC7821WithExecutorStorage storage $) {
42
- assembly {
42
+ assembly ("memory-safe") {
43
43
  $.slot := ERC7821WithExecutorStorageLocation
44
44
  }
45
45
  }
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.2.0-rc.2) (finance/VestingWalletCliffConfidential.sol)
2
+ // OpenZeppelin Confidential Contracts (last updated v0.2.0) (finance/VestingWalletCliffConfidential.sol)
3
3
  pragma solidity ^0.8.27;
4
4
 
5
5
  import {euint128} from "@fhevm/solidity/lib/FHE.sol";
@@ -33,7 +33,18 @@ abstract contract VestingWalletCliffConfidential is VestingWalletConfidential {
33
33
  * start timestamp (see {VestingWalletConfidential-start}) and ends `cliffSeconds` later.
34
34
  */
35
35
  // solhint-disable-next-line func-name-mixedcase
36
- function __VestingWalletCliffConfidential_init(uint48 cliffSeconds) internal onlyInitializing {
36
+ function __VestingWalletCliffConfidential_init(
37
+ address beneficiary,
38
+ uint48 startTimestamp,
39
+ uint48 durationSeconds,
40
+ uint48 cliffSeconds
41
+ ) internal onlyInitializing {
42
+ __VestingWalletConfidential_init(beneficiary, startTimestamp, durationSeconds);
43
+ __VestingWalletCliffConfidential_init_unchained(cliffSeconds);
44
+ }
45
+
46
+ // solhint-disable-next-line func-name-mixedcase
47
+ function __VestingWalletCliffConfidential_init_unchained(uint48 cliffSeconds) internal onlyInitializing {
37
48
  require(
38
49
  cliffSeconds <= duration(),
39
50
  VestingWalletCliffConfidentialInvalidCliffDuration(cliffSeconds, duration())
@@ -50,12 +61,12 @@ abstract contract VestingWalletCliffConfidential is VestingWalletConfidential {
50
61
  * effect from calling the inherited implementation (i.e. `super._vestingSchedule`). Carefully consider
51
62
  * this caveat if the overridden implementation of this function has any (e.g. writing to memory or reverting).
52
63
  */
53
- function _vestingSchedule(euint128 totalAllocation, uint64 timestamp) internal virtual override returns (euint128) {
64
+ function _vestingSchedule(euint128 totalAllocation, uint48 timestamp) internal virtual override returns (euint128) {
54
65
  return timestamp < cliff() ? euint128.wrap(0) : super._vestingSchedule(totalAllocation, timestamp);
55
66
  }
56
67
 
57
68
  function _getVestingWalletCliffStorage() private pure returns (VestingWalletCliffStorage storage $) {
58
- assembly {
69
+ assembly ("memory-safe") {
59
70
  $.slot := VestingWalletCliffStorageLocation
60
71
  }
61
72
  }
@@ -1,14 +1,14 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.2.0-rc.2) (finance/VestingWalletConfidential.sol)
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (finance/VestingWalletConfidential.sol)
3
3
  pragma solidity ^0.8.24;
4
4
 
5
5
  import {FHE, ebool, euint64, euint128} from "@fhevm/solidity/lib/FHE.sol";
6
6
  import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
7
7
  import {ReentrancyGuardTransient} from "@openzeppelin/contracts/utils/ReentrancyGuardTransient.sol";
8
- import {IConfidentialFungibleToken} from "./../interfaces/IConfidentialFungibleToken.sol";
8
+ import {IERC7984} from "./../interfaces/IERC7984.sol";
9
9
 
10
10
  /**
11
- * @dev A vesting wallet is an ownable contract that can receive ConfidentialFungibleTokens, and release these
11
+ * @dev A vesting wallet is an ownable contract that can receive ERC7984 tokens, and release these
12
12
  * assets to the wallet owner, also referred to as "beneficiary", according to a vesting schedule.
13
13
  *
14
14
  * Any assets transferred to this contract will follow the vesting schedule as if they were locked from the beginning.
@@ -22,11 +22,13 @@ import {IConfidentialFungibleToken} from "./../interfaces/IConfidentialFungibleT
22
22
  *
23
23
  * NOTE: When using this contract with any token whose balance is adjusted automatically (i.e. a rebase token), make
24
24
  * sure to account the supply/balance adjustment in the vesting schedule to ensure the vested amount is as intended.
25
+ *
26
+ * Confidential vesting wallet contracts can be deployed (as clones) using the {VestingWalletConfidentialFactory}.
25
27
  */
26
28
  abstract contract VestingWalletConfidential is OwnableUpgradeable, ReentrancyGuardTransient {
27
29
  /// @custom:storage-location erc7201:openzeppelin.storage.VestingWalletConfidential
28
30
  struct VestingWalletStorage {
29
- mapping(address token => euint64) _tokenReleased;
31
+ mapping(address token => euint128) _tokenReleased;
30
32
  uint64 _start;
31
33
  uint64 _duration;
32
34
  }
@@ -36,6 +38,7 @@ abstract contract VestingWalletConfidential is OwnableUpgradeable, ReentrancyGua
36
38
  bytes32 private constant VestingWalletStorageLocation =
37
39
  0x78ce9ee9eb65fa0cf5bf10e861c3a95cb7c3c713c96ab1e5323a21e846796800;
38
40
 
41
+ /// @dev Emitted when releasable vested tokens are released.
39
42
  event VestingWalletConfidentialTokenReleased(address indexed token, euint64 amount);
40
43
 
41
44
  /// @dev Timestamp at which the vesting starts.
@@ -54,16 +57,19 @@ abstract contract VestingWalletConfidential is OwnableUpgradeable, ReentrancyGua
54
57
  }
55
58
 
56
59
  /// @dev Amount of token already released
57
- function released(address token) public view virtual returns (euint64) {
60
+ function released(address token) public view virtual returns (euint128) {
58
61
  return _getVestingWalletStorage()._tokenReleased[token];
59
62
  }
60
63
 
61
64
  /**
62
65
  * @dev Getter for the amount of releasable `token` tokens. `token` should be the address of an
63
- * {IConfidentialFungibleToken} contract.
66
+ * {IERC7984} contract.
64
67
  */
65
68
  function releasable(address token) public virtual returns (euint64) {
66
- return FHE.asEuint64(FHE.sub(vestedAmount(token, uint64(block.timestamp)), released(token)));
69
+ euint128 vestedAmount_ = vestedAmount(token, uint48(block.timestamp));
70
+ euint128 releasedAmount = released(token);
71
+ ebool success = FHE.ge(vestedAmount_, releasedAmount);
72
+ return FHE.select(success, FHE.asEuint64(FHE.sub(vestedAmount_, releasedAmount)), FHE.asEuint64(0));
67
73
  }
68
74
 
69
75
  /**
@@ -74,25 +80,23 @@ abstract contract VestingWalletConfidential is OwnableUpgradeable, ReentrancyGua
74
80
  function release(address token) public virtual nonReentrant {
75
81
  euint64 amount = releasable(token);
76
82
  FHE.allowTransient(amount, token);
77
- euint64 amountSent = IConfidentialFungibleToken(token).confidentialTransfer(owner(), amount);
83
+ euint64 amountSent = IERC7984(token).confidentialTransfer(owner(), amount);
78
84
 
79
- euint64 newReleasedAmount = FHE.add(released(token), amountSent);
85
+ // This could overflow if the total supply is resent `type(uint128).max/type(uint64).max` times. This is an accepted risk.
86
+ euint128 newReleasedAmount = FHE.add(released(token), amountSent);
80
87
  FHE.allow(newReleasedAmount, owner());
81
88
  FHE.allowThis(newReleasedAmount);
82
89
  _getVestingWalletStorage()._tokenReleased[token] = newReleasedAmount;
83
90
  emit VestingWalletConfidentialTokenReleased(token, amountSent);
84
91
  }
85
92
 
86
- /// @dev Calculates the amount of tokens that have already vested. Default implementation is a linear vesting curve.
87
- function vestedAmount(address token, uint64 timestamp) public virtual returns (euint128) {
93
+ /**
94
+ * @dev Calculates the amount of tokens that have been vested at the given timestamp.
95
+ * Default implementation is a linear vesting curve.
96
+ */
97
+ function vestedAmount(address token, uint48 timestamp) public virtual returns (euint128) {
88
98
  return
89
- _vestingSchedule(
90
- FHE.add(
91
- FHE.asEuint128(IConfidentialFungibleToken(token).confidentialBalanceOf(address(this))),
92
- released(token)
93
- ),
94
- timestamp
95
- );
99
+ _vestingSchedule(FHE.add(released(token), IERC7984(token).confidentialBalanceOf(address(this))), timestamp);
96
100
  }
97
101
 
98
102
  /**
@@ -106,13 +110,21 @@ abstract contract VestingWalletConfidential is OwnableUpgradeable, ReentrancyGua
106
110
  uint48 durationSeconds
107
111
  ) internal onlyInitializing {
108
112
  __Ownable_init(beneficiary);
113
+ __VestingWalletConfidential_init_unchained(startTimestamp, durationSeconds);
114
+ }
115
+
116
+ // solhint-disable-next-line func-name-mixedcase
117
+ function __VestingWalletConfidential_init_unchained(
118
+ uint48 startTimestamp,
119
+ uint48 durationSeconds
120
+ ) internal onlyInitializing {
109
121
  VestingWalletStorage storage $ = _getVestingWalletStorage();
110
122
  $._start = startTimestamp;
111
123
  $._duration = durationSeconds;
112
124
  }
113
125
 
114
126
  /// @dev This returns the amount vested, as a function of time, for an asset given its total historical allocation.
115
- function _vestingSchedule(euint128 totalAllocation, uint64 timestamp) internal virtual returns (euint128) {
127
+ function _vestingSchedule(euint128 totalAllocation, uint48 timestamp) internal virtual returns (euint128) {
116
128
  if (timestamp < start()) {
117
129
  return euint128.wrap(0);
118
130
  } else if (timestamp >= end()) {
@@ -123,7 +135,7 @@ abstract contract VestingWalletConfidential is OwnableUpgradeable, ReentrancyGua
123
135
  }
124
136
 
125
137
  function _getVestingWalletStorage() private pure returns (VestingWalletStorage storage $) {
126
- assembly {
138
+ assembly ("memory-safe") {
127
139
  $.slot := VestingWalletStorageLocation
128
140
  }
129
141
  }