@openzeppelin/confidential-contracts 0.3.0-rc.0 → 0.3.1
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/Checkpoints.json +2 -2
- package/build/contracts/CheckpointsConfidential.json +2 -2
- package/build/contracts/ERC7984.json +72 -38
- package/build/contracts/ERC7984ERC20Wrapper.json +159 -39
- package/build/contracts/ERC7984Freezable.json +72 -38
- package/build/contracts/ERC7984ObserverAccess.json +73 -39
- package/build/contracts/ERC7984Omnibus.json +72 -38
- package/build/contracts/ERC7984Restricted.json +74 -40
- package/build/contracts/ERC7984Rwa.json +55 -40
- package/build/contracts/ERC7984Utils.json +2 -2
- package/build/contracts/ERC7984Votes.json +80 -46
- package/build/contracts/FHESafeMath.json +2 -2
- package/build/contracts/IERC7984.json +19 -0
- package/finance/ERC7821WithExecutor.sol +3 -4
- package/finance/VestingWalletCliffConfidential.sol +3 -4
- package/finance/VestingWalletConfidential.sol +3 -4
- package/finance/VestingWalletConfidentialFactory.sol +1 -1
- package/interfaces/IERC7984.sol +4 -3
- package/interfaces/IERC7984Receiver.sol +1 -1
- package/interfaces/IERC7984Rwa.sol +2 -3
- package/package.json +2 -2
- package/token/ERC7984/ERC7984.sol +32 -25
- package/token/ERC7984/extensions/ERC7984ERC20Wrapper.sol +87 -40
- package/token/ERC7984/extensions/ERC7984Freezable.sol +13 -4
- package/token/ERC7984/extensions/ERC7984ObserverAccess.sol +2 -2
- package/token/ERC7984/extensions/ERC7984Omnibus.sol +3 -3
- package/token/ERC7984/extensions/ERC7984Restricted.sol +3 -11
- package/token/ERC7984/extensions/ERC7984Rwa.sol +38 -26
- package/token/ERC7984/extensions/ERC7984Votes.sol +1 -1
- package/token/ERC7984/utils/ERC7984Utils.sol +3 -2
- package/utils/FHESafeMath.sol +5 -2
- package/utils/structs/temporary-Checkpoints.sol +1 -1
|
@@ -143,11 +143,6 @@
|
|
|
143
143
|
"name": "ERC7984ZeroBalance",
|
|
144
144
|
"type": "error"
|
|
145
145
|
},
|
|
146
|
-
{
|
|
147
|
-
"inputs": [],
|
|
148
|
-
"name": "HandlesAlreadySavedForRequestID",
|
|
149
|
-
"type": "error"
|
|
150
|
-
},
|
|
151
146
|
{
|
|
152
147
|
"inputs": [
|
|
153
148
|
{
|
|
@@ -174,11 +169,6 @@
|
|
|
174
169
|
"name": "InvalidShortString",
|
|
175
170
|
"type": "error"
|
|
176
171
|
},
|
|
177
|
-
{
|
|
178
|
-
"inputs": [],
|
|
179
|
-
"name": "NoHandleFoundForRequestID",
|
|
180
|
-
"type": "error"
|
|
181
|
-
},
|
|
182
172
|
{
|
|
183
173
|
"inputs": [
|
|
184
174
|
{
|
|
@@ -217,6 +207,25 @@
|
|
|
217
207
|
"name": "VotesExpiredSignature",
|
|
218
208
|
"type": "error"
|
|
219
209
|
},
|
|
210
|
+
{
|
|
211
|
+
"anonymous": false,
|
|
212
|
+
"inputs": [
|
|
213
|
+
{
|
|
214
|
+
"indexed": true,
|
|
215
|
+
"internalType": "euint64",
|
|
216
|
+
"name": "encryptedAmount",
|
|
217
|
+
"type": "bytes32"
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"indexed": true,
|
|
221
|
+
"internalType": "address",
|
|
222
|
+
"name": "requester",
|
|
223
|
+
"type": "address"
|
|
224
|
+
}
|
|
225
|
+
],
|
|
226
|
+
"name": "AmountDiscloseRequested",
|
|
227
|
+
"type": "event"
|
|
228
|
+
},
|
|
220
229
|
{
|
|
221
230
|
"anonymous": false,
|
|
222
231
|
"inputs": [
|
|
@@ -261,19 +270,6 @@
|
|
|
261
270
|
"name": "ConfidentialTransfer",
|
|
262
271
|
"type": "event"
|
|
263
272
|
},
|
|
264
|
-
{
|
|
265
|
-
"anonymous": false,
|
|
266
|
-
"inputs": [
|
|
267
|
-
{
|
|
268
|
-
"indexed": true,
|
|
269
|
-
"internalType": "uint256",
|
|
270
|
-
"name": "requestID",
|
|
271
|
-
"type": "uint256"
|
|
272
|
-
}
|
|
273
|
-
],
|
|
274
|
-
"name": "DecryptionFulfilled",
|
|
275
|
-
"type": "event"
|
|
276
|
-
},
|
|
277
273
|
{
|
|
278
274
|
"anonymous": false,
|
|
279
275
|
"inputs": [
|
|
@@ -355,6 +351,25 @@
|
|
|
355
351
|
"name": "OperatorSet",
|
|
356
352
|
"type": "event"
|
|
357
353
|
},
|
|
354
|
+
{
|
|
355
|
+
"anonymous": false,
|
|
356
|
+
"inputs": [
|
|
357
|
+
{
|
|
358
|
+
"indexed": false,
|
|
359
|
+
"internalType": "bytes32[]",
|
|
360
|
+
"name": "handlesList",
|
|
361
|
+
"type": "bytes32[]"
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
"indexed": false,
|
|
365
|
+
"internalType": "bytes",
|
|
366
|
+
"name": "abiEncodedCleartexts",
|
|
367
|
+
"type": "bytes"
|
|
368
|
+
}
|
|
369
|
+
],
|
|
370
|
+
"name": "PublicDecryptionVerified",
|
|
371
|
+
"type": "event"
|
|
372
|
+
},
|
|
358
373
|
{
|
|
359
374
|
"inputs": [],
|
|
360
375
|
"name": "CLOCK_MODE",
|
|
@@ -767,6 +782,16 @@
|
|
|
767
782
|
"internalType": "euint64",
|
|
768
783
|
"name": "encryptedAmount",
|
|
769
784
|
"type": "bytes32"
|
|
785
|
+
},
|
|
786
|
+
{
|
|
787
|
+
"internalType": "uint64",
|
|
788
|
+
"name": "cleartextAmount",
|
|
789
|
+
"type": "uint64"
|
|
790
|
+
},
|
|
791
|
+
{
|
|
792
|
+
"internalType": "bytes",
|
|
793
|
+
"name": "decryptionProof",
|
|
794
|
+
"type": "bytes"
|
|
770
795
|
}
|
|
771
796
|
],
|
|
772
797
|
"name": "discloseEncryptedAmount",
|
|
@@ -817,29 +842,6 @@
|
|
|
817
842
|
"stateMutability": "view",
|
|
818
843
|
"type": "function"
|
|
819
844
|
},
|
|
820
|
-
{
|
|
821
|
-
"inputs": [
|
|
822
|
-
{
|
|
823
|
-
"internalType": "uint256",
|
|
824
|
-
"name": "requestId",
|
|
825
|
-
"type": "uint256"
|
|
826
|
-
},
|
|
827
|
-
{
|
|
828
|
-
"internalType": "bytes",
|
|
829
|
-
"name": "cleartexts",
|
|
830
|
-
"type": "bytes"
|
|
831
|
-
},
|
|
832
|
-
{
|
|
833
|
-
"internalType": "bytes",
|
|
834
|
-
"name": "decryptionProof",
|
|
835
|
-
"type": "bytes"
|
|
836
|
-
}
|
|
837
|
-
],
|
|
838
|
-
"name": "finalizeDiscloseEncryptedAmount",
|
|
839
|
-
"outputs": [],
|
|
840
|
-
"stateMutability": "nonpayable",
|
|
841
|
-
"type": "function"
|
|
842
|
-
},
|
|
843
845
|
{
|
|
844
846
|
"inputs": [
|
|
845
847
|
{
|
|
@@ -981,6 +983,19 @@
|
|
|
981
983
|
"stateMutability": "view",
|
|
982
984
|
"type": "function"
|
|
983
985
|
},
|
|
986
|
+
{
|
|
987
|
+
"inputs": [
|
|
988
|
+
{
|
|
989
|
+
"internalType": "euint64",
|
|
990
|
+
"name": "encryptedAmount",
|
|
991
|
+
"type": "bytes32"
|
|
992
|
+
}
|
|
993
|
+
],
|
|
994
|
+
"name": "requestDiscloseEncryptedAmount",
|
|
995
|
+
"outputs": [],
|
|
996
|
+
"stateMutability": "nonpayable",
|
|
997
|
+
"type": "function"
|
|
998
|
+
},
|
|
984
999
|
{
|
|
985
1000
|
"inputs": [
|
|
986
1001
|
{
|
|
@@ -999,6 +1014,25 @@
|
|
|
999
1014
|
"stateMutability": "nonpayable",
|
|
1000
1015
|
"type": "function"
|
|
1001
1016
|
},
|
|
1017
|
+
{
|
|
1018
|
+
"inputs": [
|
|
1019
|
+
{
|
|
1020
|
+
"internalType": "bytes4",
|
|
1021
|
+
"name": "interfaceId",
|
|
1022
|
+
"type": "bytes4"
|
|
1023
|
+
}
|
|
1024
|
+
],
|
|
1025
|
+
"name": "supportsInterface",
|
|
1026
|
+
"outputs": [
|
|
1027
|
+
{
|
|
1028
|
+
"internalType": "bool",
|
|
1029
|
+
"name": "",
|
|
1030
|
+
"type": "bool"
|
|
1031
|
+
}
|
|
1032
|
+
],
|
|
1033
|
+
"stateMutability": "view",
|
|
1034
|
+
"type": "function"
|
|
1035
|
+
},
|
|
1002
1036
|
{
|
|
1003
1037
|
"inputs": [],
|
|
1004
1038
|
"name": "symbol",
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
"contractName": "FHESafeMath",
|
|
4
4
|
"sourceName": "contracts/utils/FHESafeMath.sol",
|
|
5
5
|
"abi": [],
|
|
6
|
-
"bytecode": "
|
|
7
|
-
"deployedBytecode": "
|
|
6
|
+
"bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220dfd2955b2f5c80c39629efab80b102628759176a07e6500f461ab8aaee7442c364736f6c634300081d0033",
|
|
7
|
+
"deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220dfd2955b2f5c80c39629efab80b102628759176a07e6500f461ab8aaee7442c364736f6c634300081d0033",
|
|
8
8
|
"linkReferences": {},
|
|
9
9
|
"deployedLinkReferences": {}
|
|
10
10
|
}
|
|
@@ -437,6 +437,25 @@
|
|
|
437
437
|
"stateMutability": "nonpayable",
|
|
438
438
|
"type": "function"
|
|
439
439
|
},
|
|
440
|
+
{
|
|
441
|
+
"inputs": [
|
|
442
|
+
{
|
|
443
|
+
"internalType": "bytes4",
|
|
444
|
+
"name": "interfaceId",
|
|
445
|
+
"type": "bytes4"
|
|
446
|
+
}
|
|
447
|
+
],
|
|
448
|
+
"name": "supportsInterface",
|
|
449
|
+
"outputs": [
|
|
450
|
+
{
|
|
451
|
+
"internalType": "bool",
|
|
452
|
+
"name": "",
|
|
453
|
+
"type": "bool"
|
|
454
|
+
}
|
|
455
|
+
],
|
|
456
|
+
"stateMutability": "view",
|
|
457
|
+
"type": "function"
|
|
458
|
+
},
|
|
440
459
|
{
|
|
441
460
|
"inputs": [],
|
|
442
461
|
"name": "symbol",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.3.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";
|
|
@@ -15,8 +15,7 @@ abstract contract ERC7821WithExecutor is Initializable, ERC7821 {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC7821WithExecutor")) - 1)) & ~bytes32(uint256(0xff))
|
|
18
|
-
|
|
19
|
-
bytes32 private constant ERC7821WithExecutorStorageLocation =
|
|
18
|
+
bytes32 private constant ERC7821_WITH_EXECUTOR_STORAGE_LOCATION =
|
|
20
19
|
0x246106ffca67a7d3806ba14f6748826b9c39c9fa594b14f83fe454e8e9d0dc00;
|
|
21
20
|
|
|
22
21
|
/// @dev Trusted address that is able to execute arbitrary calls from the vesting wallet via `ERC7821.execute`.
|
|
@@ -40,7 +39,7 @@ abstract contract ERC7821WithExecutor is Initializable, ERC7821 {
|
|
|
40
39
|
|
|
41
40
|
function _getERC7821WithExecutorStorage() private pure returns (ERC7821WithExecutorStorage storage $) {
|
|
42
41
|
assembly ("memory-safe") {
|
|
43
|
-
$.slot :=
|
|
42
|
+
$.slot := ERC7821_WITH_EXECUTOR_STORAGE_LOCATION
|
|
44
43
|
}
|
|
45
44
|
}
|
|
46
45
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.3.0) (finance/VestingWalletCliffConfidential.sol)
|
|
3
3
|
pragma solidity ^0.8.27;
|
|
4
4
|
|
|
5
5
|
import {euint128} from "@fhevm/solidity/lib/FHE.sol";
|
|
@@ -16,8 +16,7 @@ abstract contract VestingWalletCliffConfidential is VestingWalletConfidential {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.VestingWalletCliffConfidential")) - 1)) & ~bytes32(uint256(0xff))
|
|
19
|
-
|
|
20
|
-
bytes32 private constant VestingWalletCliffStorageLocation =
|
|
19
|
+
bytes32 private constant VESTING_WALLET_CLIFF_STORAGE_LOCATION =
|
|
21
20
|
0x3c715f77db997bdb68403fafb54820cd57dedce553ed6315028656b0d601c700;
|
|
22
21
|
|
|
23
22
|
/// @dev The specified cliff duration is larger than the vesting duration.
|
|
@@ -67,7 +66,7 @@ abstract contract VestingWalletCliffConfidential is VestingWalletConfidential {
|
|
|
67
66
|
|
|
68
67
|
function _getVestingWalletCliffStorage() private pure returns (VestingWalletCliffStorage storage $) {
|
|
69
68
|
assembly ("memory-safe") {
|
|
70
|
-
$.slot :=
|
|
69
|
+
$.slot := VESTING_WALLET_CLIFF_STORAGE_LOCATION
|
|
71
70
|
}
|
|
72
71
|
}
|
|
73
72
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.3.0
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.3.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";
|
|
@@ -34,8 +34,7 @@ abstract contract VestingWalletConfidential is OwnableUpgradeable, ReentrancyGua
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.VestingWalletConfidential")) - 1)) & ~bytes32(uint256(0xff))
|
|
37
|
-
|
|
38
|
-
bytes32 private constant VestingWalletStorageLocation =
|
|
37
|
+
bytes32 private constant VESTING_WALLET_STORAGE_LOCATION =
|
|
39
38
|
0x78ce9ee9eb65fa0cf5bf10e861c3a95cb7c3c713c96ab1e5323a21e846796800;
|
|
40
39
|
|
|
41
40
|
/// @dev Emitted when releasable vested tokens are released.
|
|
@@ -136,7 +135,7 @@ abstract contract VestingWalletConfidential is OwnableUpgradeable, ReentrancyGua
|
|
|
136
135
|
|
|
137
136
|
function _getVestingWalletStorage() private pure returns (VestingWalletStorage storage $) {
|
|
138
137
|
assembly ("memory-safe") {
|
|
139
|
-
$.slot :=
|
|
138
|
+
$.slot := VESTING_WALLET_STORAGE_LOCATION
|
|
140
139
|
}
|
|
141
140
|
}
|
|
142
141
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.3.0
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.3.0) (finance/VestingWalletConfidentialFactory.sol)
|
|
3
3
|
pragma solidity ^0.8.27;
|
|
4
4
|
|
|
5
5
|
import {FHE, euint64, externalEuint64} from "@fhevm/solidity/lib/FHE.sol";
|
package/interfaces/IERC7984.sol
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.3.0
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.3.0) (interfaces/IERC7984.sol)
|
|
3
3
|
pragma solidity ^0.8.24;
|
|
4
4
|
|
|
5
5
|
import {euint64, externalEuint64} from "@fhevm/solidity/lib/FHE.sol";
|
|
6
|
+
import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";
|
|
6
7
|
|
|
7
8
|
/// @dev Draft interface for a confidential fungible token standard utilizing the Zama FHE library.
|
|
8
|
-
interface IERC7984 {
|
|
9
|
+
interface IERC7984 is IERC165 {
|
|
9
10
|
/**
|
|
10
11
|
* @dev Emitted when the expiration timestamp for an operator `operator` is updated for a given `holder`.
|
|
11
12
|
* The operator may move any amount of tokens on behalf of the holder until the timestamp `until`.
|
|
@@ -32,7 +33,7 @@ interface IERC7984 {
|
|
|
32
33
|
/// @dev Returns the number of decimals of the token. Recommended to be 6.
|
|
33
34
|
function decimals() external view returns (uint8);
|
|
34
35
|
|
|
35
|
-
/// @dev Returns the contract URI. See
|
|
36
|
+
/// @dev Returns the contract URI. See https://eips.ethereum.org/EIPS/eip-7572[ERC-7572] for details.
|
|
36
37
|
function contractURI() external view returns (string memory);
|
|
37
38
|
|
|
38
39
|
/// @dev Returns the confidential total supply of the token.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.3.0
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.3.0) (interfaces/IERC7984Receiver.sol)
|
|
3
3
|
pragma solidity ^0.8.24;
|
|
4
4
|
|
|
5
5
|
import {ebool, euint64} from "@fhevm/solidity/lib/FHE.sol";
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.3.0
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.3.0) (interfaces/IERC7984Rwa.sol)
|
|
3
3
|
pragma solidity ^0.8.24;
|
|
4
4
|
|
|
5
5
|
import {externalEuint64, euint64} from "@fhevm/solidity/lib/FHE.sol";
|
|
6
|
-
import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";
|
|
7
6
|
import {IERC7984} from "./IERC7984.sol";
|
|
8
7
|
|
|
9
8
|
/// @dev Interface for confidential RWA contracts.
|
|
10
|
-
interface IERC7984Rwa is IERC7984
|
|
9
|
+
interface IERC7984Rwa is IERC7984 {
|
|
11
10
|
/// @dev Returns true if the contract is paused, false otherwise.
|
|
12
11
|
function paused() external view returns (bool);
|
|
13
12
|
/// @dev Returns whether an account is allowed to interact with the token.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openzeppelin/confidential-contracts",
|
|
3
3
|
"description": "Smart Contract library for use with confidential coprocessors",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.1",
|
|
5
5
|
"files": [
|
|
6
6
|
"**/*.sol",
|
|
7
7
|
"/build/contracts/*.json",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"homepage": "https://openzeppelin.com/contracts/",
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"@fhevm/solidity": "0.
|
|
35
|
+
"@fhevm/solidity": "0.9.1",
|
|
36
36
|
"@openzeppelin/contracts": "^5.4.0",
|
|
37
37
|
"@openzeppelin/contracts-upgradeable": "^5.4.0"
|
|
38
38
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.3.0
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.3.0) (token/ERC7984/ERC7984.sol)
|
|
3
3
|
pragma solidity ^0.8.27;
|
|
4
4
|
|
|
5
5
|
import {FHE, externalEuint64, ebool, euint64} from "@fhevm/solidity/lib/FHE.sol";
|
|
6
|
+
import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
|
|
7
|
+
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
6
8
|
import {IERC7984} from "./../../interfaces/IERC7984.sol";
|
|
7
9
|
import {FHESafeMath} from "./../../utils/FHESafeMath.sol";
|
|
8
10
|
import {ERC7984Utils} from "./utils/ERC7984Utils.sol";
|
|
@@ -22,7 +24,7 @@ import {ERC7984Utils} from "./utils/ERC7984Utils.sol";
|
|
|
22
24
|
* - Transfer and call pattern
|
|
23
25
|
* - Safe overflow/underflow handling for FHE operations
|
|
24
26
|
*/
|
|
25
|
-
abstract contract ERC7984 is IERC7984 {
|
|
27
|
+
abstract contract ERC7984 is IERC7984, ERC165 {
|
|
26
28
|
mapping(address holder => euint64) private _balances;
|
|
27
29
|
mapping(address holder => mapping(address spender => uint48)) private _operators;
|
|
28
30
|
euint64 private _totalSupply;
|
|
@@ -30,6 +32,9 @@ abstract contract ERC7984 is IERC7984 {
|
|
|
30
32
|
string private _symbol;
|
|
31
33
|
string private _contractURI;
|
|
32
34
|
|
|
35
|
+
/// @dev Emitted when an encrypted amount `encryptedAmount` is requested for disclosure by `requester`.
|
|
36
|
+
event AmountDiscloseRequested(euint64 indexed encryptedAmount, address indexed requester);
|
|
37
|
+
|
|
33
38
|
/// @dev The given receiver `receiver` is invalid for transfers.
|
|
34
39
|
error ERC7984InvalidReceiver(address receiver);
|
|
35
40
|
|
|
@@ -61,6 +66,11 @@ abstract contract ERC7984 is IERC7984 {
|
|
|
61
66
|
_contractURI = contractURI_;
|
|
62
67
|
}
|
|
63
68
|
|
|
69
|
+
/// @inheritdoc ERC165
|
|
70
|
+
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
|
|
71
|
+
return interfaceId == type(IERC7984).interfaceId || super.supportsInterface(interfaceId);
|
|
72
|
+
}
|
|
73
|
+
|
|
64
74
|
/// @inheritdoc IERC7984
|
|
65
75
|
function name() public view virtual returns (string memory) {
|
|
66
76
|
return _name;
|
|
@@ -189,42 +199,39 @@ abstract contract ERC7984 is IERC7984 {
|
|
|
189
199
|
}
|
|
190
200
|
|
|
191
201
|
/**
|
|
192
|
-
* @dev
|
|
193
|
-
*
|
|
202
|
+
* @dev Starts the process to disclose an encrypted amount `encryptedAmount` publicly by making it
|
|
203
|
+
* publicly decryptable. Emits the {AmountDiscloseRequested} event.
|
|
194
204
|
*
|
|
195
|
-
* NOTE:
|
|
196
|
-
*
|
|
205
|
+
* NOTE: Both `msg.sender` and `address(this)` must have permission to access the encrypted amount
|
|
206
|
+
* `encryptedAmount` to request disclosure of the encrypted amount `encryptedAmount`.
|
|
197
207
|
*/
|
|
198
|
-
function
|
|
208
|
+
function requestDiscloseEncryptedAmount(euint64 encryptedAmount) public virtual {
|
|
199
209
|
require(
|
|
200
210
|
FHE.isAllowed(encryptedAmount, msg.sender),
|
|
201
211
|
ERC7984UnauthorizedUseOfEncryptedAmount(encryptedAmount, msg.sender)
|
|
202
212
|
);
|
|
203
213
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
FHE.requestDecryption(cts, this.finalizeDiscloseEncryptedAmount.selector);
|
|
214
|
+
FHE.makePubliclyDecryptable(encryptedAmount);
|
|
215
|
+
emit AmountDiscloseRequested(encryptedAmount, msg.sender);
|
|
207
216
|
}
|
|
208
217
|
|
|
209
218
|
/**
|
|
210
|
-
* @dev
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
* function might emit a disclosed amount related to another decryption request context.
|
|
214
|
-
* In this case it would only display public information
|
|
215
|
-
* since the handle would have already been allowed for public decryption through a previous
|
|
216
|
-
* `FHE.requestDecryption` call.
|
|
217
|
-
* The downside of this behavior is that a {finalizeDiscloseEncryptedAmount} watcher might observe
|
|
218
|
-
* unexpected `AmountDisclosed` events.
|
|
219
|
+
* @dev Publicly discloses an encrypted value with a given decryption proof. Emits the {AmountDisclosed} event.
|
|
220
|
+
*
|
|
221
|
+
* NOTE: May not be tied to a prior request via {requestDiscloseEncryptedAmount}.
|
|
219
222
|
*/
|
|
220
|
-
function
|
|
221
|
-
|
|
222
|
-
|
|
223
|
+
function discloseEncryptedAmount(
|
|
224
|
+
euint64 encryptedAmount,
|
|
225
|
+
uint64 cleartextAmount,
|
|
223
226
|
bytes calldata decryptionProof
|
|
224
227
|
) public virtual {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
+
bytes32[] memory handles = new bytes32[](1);
|
|
229
|
+
handles[0] = euint64.unwrap(encryptedAmount);
|
|
230
|
+
|
|
231
|
+
bytes memory cleartextMemory = abi.encode(cleartextAmount);
|
|
232
|
+
|
|
233
|
+
FHE.checkSignatures(handles, cleartextMemory, decryptionProof);
|
|
234
|
+
emit AmountDisclosed(encryptedAmount, cleartextAmount);
|
|
228
235
|
}
|
|
229
236
|
|
|
230
237
|
function _setOperator(address holder, address operator, uint48 until) internal virtual {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.3.
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.3.1) (token/ERC7984/extensions/ERC7984ERC20Wrapper.sol)
|
|
3
3
|
|
|
4
4
|
pragma solidity ^0.8.27;
|
|
5
5
|
|
|
@@ -24,8 +24,13 @@ abstract contract ERC7984ERC20Wrapper is ERC7984, IERC1363Receiver {
|
|
|
24
24
|
uint8 private immutable _decimals;
|
|
25
25
|
uint256 private immutable _rate;
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
mapping(euint64 unwrapAmount => address recipient) private _unwrapRequests;
|
|
28
|
+
|
|
29
|
+
event UnwrapRequested(address indexed receiver, euint64 amount);
|
|
30
|
+
event UnwrapFinalized(address indexed receiver, euint64 encryptedAmount, uint64 cleartextAmount);
|
|
31
|
+
|
|
32
|
+
error InvalidUnwrapRequest(euint64 amount);
|
|
33
|
+
error ERC7984TotalSupplyOverflow();
|
|
29
34
|
|
|
30
35
|
constructor(IERC20 underlying_) {
|
|
31
36
|
_underlying = underlying_;
|
|
@@ -41,28 +46,10 @@ abstract contract ERC7984ERC20Wrapper is ERC7984, IERC1363Receiver {
|
|
|
41
46
|
}
|
|
42
47
|
}
|
|
43
48
|
|
|
44
|
-
/// @inheritdoc ERC7984
|
|
45
|
-
function decimals() public view virtual override returns (uint8) {
|
|
46
|
-
return _decimals;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* @dev Returns the rate at which the underlying token is converted to the wrapped token.
|
|
51
|
-
* For example, if the `rate` is 1000, then 1000 units of the underlying token equal 1 unit of the wrapped token.
|
|
52
|
-
*/
|
|
53
|
-
function rate() public view virtual returns (uint256) {
|
|
54
|
-
return _rate;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/// @dev Returns the address of the underlying ERC-20 token that is being wrapped.
|
|
58
|
-
function underlying() public view returns (IERC20) {
|
|
59
|
-
return _underlying;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
49
|
/**
|
|
63
50
|
* @dev `ERC1363` callback function which wraps tokens to the address specified in `data` or
|
|
64
51
|
* the address `from` (if no address is specified in `data`). This function refunds any excess tokens
|
|
65
|
-
* sent beyond the nearest multiple of {rate}
|
|
52
|
+
* sent beyond the nearest multiple of {rate} to `from`. See {wrap} from more details on wrapping tokens.
|
|
66
53
|
*/
|
|
67
54
|
function onTransferReceived(
|
|
68
55
|
address /*operator*/,
|
|
@@ -102,8 +89,7 @@ abstract contract ERC7984ERC20Wrapper is ERC7984, IERC1363Receiver {
|
|
|
102
89
|
* @dev Unwraps tokens from `from` and sends the underlying tokens to `to`. The caller must be `from`
|
|
103
90
|
* or be an approved operator for `from`. `amount * rate()` underlying tokens are sent to `to`.
|
|
104
91
|
*
|
|
105
|
-
* NOTE:
|
|
106
|
-
* tokens.
|
|
92
|
+
* NOTE: The unwrap request created by this function must be finalized by calling {finalizeUnwrap}.
|
|
107
93
|
* NOTE: The caller *must* already be approved by ACL for the given `amount`.
|
|
108
94
|
*/
|
|
109
95
|
function unwrap(address from, address to, euint64 amount) public virtual {
|
|
@@ -124,36 +110,97 @@ abstract contract ERC7984ERC20Wrapper is ERC7984, IERC1363Receiver {
|
|
|
124
110
|
_unwrap(from, to, FHE.fromExternal(encryptedAmount, inputProof));
|
|
125
111
|
}
|
|
126
112
|
|
|
127
|
-
|
|
128
|
-
* @dev Fills an unwrap request for a given request id related to a decrypted unwrap amount.
|
|
129
|
-
*/
|
|
113
|
+
/// @dev Fills an unwrap request for a given cipher-text `burntAmount` with the `cleartextAmount` and `decryptionProof`.
|
|
130
114
|
function finalizeUnwrap(
|
|
131
|
-
|
|
132
|
-
|
|
115
|
+
euint64 burntAmount,
|
|
116
|
+
uint64 burntAmountCleartext,
|
|
133
117
|
bytes calldata decryptionProof
|
|
134
118
|
) public virtual {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
119
|
+
address to = _unwrapRequests[burntAmount];
|
|
120
|
+
require(to != address(0), InvalidUnwrapRequest(burntAmount));
|
|
121
|
+
delete _unwrapRequests[burntAmount];
|
|
122
|
+
|
|
123
|
+
bytes32[] memory handles = new bytes32[](1);
|
|
124
|
+
handles[0] = euint64.unwrap(burntAmount);
|
|
125
|
+
|
|
126
|
+
bytes memory cleartexts = abi.encode(burntAmountCleartext);
|
|
139
127
|
|
|
140
|
-
|
|
128
|
+
FHE.checkSignatures(handles, cleartexts, decryptionProof);
|
|
129
|
+
|
|
130
|
+
SafeERC20.safeTransfer(underlying(), to, burntAmountCleartext * rate());
|
|
131
|
+
|
|
132
|
+
emit UnwrapFinalized(to, burntAmount, burntAmountCleartext);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/// @inheritdoc ERC7984
|
|
136
|
+
function decimals() public view virtual override returns (uint8) {
|
|
137
|
+
return _decimals;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @dev Returns the rate at which the underlying token is converted to the wrapped token.
|
|
142
|
+
* For example, if the `rate` is 1000, then 1000 units of the underlying token equal 1 unit of the wrapped token.
|
|
143
|
+
*/
|
|
144
|
+
function rate() public view virtual returns (uint256) {
|
|
145
|
+
return _rate;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/// @dev Returns the address of the underlying ERC-20 token that is being wrapped.
|
|
149
|
+
function underlying() public view returns (IERC20) {
|
|
150
|
+
return _underlying;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* @dev Returns the underlying balance divided by the {rate}, a value greater or equal to the actual
|
|
155
|
+
* {confidentialTotalSupply}.
|
|
156
|
+
*
|
|
157
|
+
* NOTE: The return value of this function can be inflated by directly sending underlying tokens to the wrapper contract.
|
|
158
|
+
* Reductions will lag compared to {confidentialTotalSupply} since it is updated on {unwrap} while this function updates
|
|
159
|
+
* on {finalizeUnwrap}.
|
|
160
|
+
*/
|
|
161
|
+
function inferredTotalSupply() public view virtual returns (uint256) {
|
|
162
|
+
return underlying().balanceOf(address(this)) / rate();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/// @dev Returns the maximum total supply of wrapped tokens supported by the encrypted datatype.
|
|
166
|
+
function maxTotalSupply() public view virtual returns (uint256) {
|
|
167
|
+
return type(uint64).max;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* @dev This function must revert if the new {confidentialTotalSupply} is invalid (overflow occurred).
|
|
172
|
+
*
|
|
173
|
+
* NOTE: Overflow can be detected here since the wrapper holdings are non-confidential. In other cases, it may be impossible
|
|
174
|
+
* to infer total supply overflow synchronously. This function may revert even if the {confidentialTotalSupply} did
|
|
175
|
+
* not overflow.
|
|
176
|
+
*/
|
|
177
|
+
function _checkConfidentialTotalSupply() internal virtual {
|
|
178
|
+
if (inferredTotalSupply() > maxTotalSupply()) {
|
|
179
|
+
revert ERC7984TotalSupplyOverflow();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/// @inheritdoc ERC7984
|
|
184
|
+
function _update(address from, address to, euint64 amount) internal virtual override returns (euint64) {
|
|
185
|
+
if (from == address(0)) {
|
|
186
|
+
_checkConfidentialTotalSupply();
|
|
187
|
+
}
|
|
188
|
+
return super._update(from, to, amount);
|
|
141
189
|
}
|
|
142
190
|
|
|
191
|
+
/// @dev Internal logic for handling the creation of unwrap requests.
|
|
143
192
|
function _unwrap(address from, address to, euint64 amount) internal virtual {
|
|
144
193
|
require(to != address(0), ERC7984InvalidReceiver(to));
|
|
145
194
|
require(from == msg.sender || isOperator(from, msg.sender), ERC7984UnauthorizedSpender(from, msg.sender));
|
|
146
195
|
|
|
147
196
|
// try to burn, see how much we actually got
|
|
148
197
|
euint64 burntAmount = _burn(from, amount);
|
|
198
|
+
FHE.makePubliclyDecryptable(burntAmount);
|
|
149
199
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
cts[0] = euint64.unwrap(burntAmount);
|
|
153
|
-
uint256 requestID = FHE.requestDecryption(cts, this.finalizeUnwrap.selector);
|
|
200
|
+
assert(_unwrapRequests[burntAmount] == address(0));
|
|
201
|
+
_unwrapRequests[burntAmount] = to;
|
|
154
202
|
|
|
155
|
-
|
|
156
|
-
_receivers[requestID] = to;
|
|
203
|
+
emit UnwrapRequested(to, burntAmount);
|
|
157
204
|
}
|
|
158
205
|
|
|
159
206
|
/**
|