@openzeppelin/confidential-contracts 0.4.1 → 0.5.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 +16 -0
- package/build/contracts/CheckpointsConfidential.json +2 -2
- package/build/contracts/ERC7984.json +6 -28
- package/build/contracts/ERC7984BalanceCapHookModule.json +242 -0
- package/build/contracts/ERC7984ERC20Wrapper.json +6 -28
- package/build/contracts/ERC7984Freezable.json +6 -28
- package/build/contracts/ERC7984HolderCapHookModule.json +256 -0
- package/build/contracts/ERC7984HookModule.json +165 -0
- package/build/contracts/ERC7984Hooked.json +827 -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 +138 -0
- package/build/contracts/IERC7984Rwa.json +87 -0
- package/finance/BatcherConfidential.sol +20 -5
- package/governance/utils/VotesConfidential.sol +2 -2
- package/interfaces/IERC7984HookModule.sol +32 -0
- package/interfaces/IERC7984Receiver.sol +3 -1
- package/interfaces/IERC7984Rwa.sol +28 -1
- package/package.json +1 -1
- package/token/ERC7984/ERC7984.sol +43 -29
- package/token/ERC7984/extensions/ERC7984ERC20Wrapper.sol +3 -3
- package/token/ERC7984/extensions/ERC7984Freezable.sol +3 -7
- package/token/ERC7984/extensions/ERC7984Hooked.sol +157 -0
- package/token/ERC7984/extensions/ERC7984Restricted.sol +3 -3
- package/token/ERC7984/extensions/ERC7984Rwa.sol +83 -28
- package/token/ERC7984/utils/ERC7984BalanceCapHookModule.sol +87 -0
- package/token/ERC7984/utils/ERC7984HolderCapHookModule.sol +141 -0
- package/token/ERC7984/utils/ERC7984HookModule.sol +131 -0
- package/utils/FHESafeMath.sol +26 -1
- package/utils/HandleAccessManager.sol +5 -3
- package/utils/structs/CheckpointsConfidential.sol +1 -2
|
@@ -72,6 +72,31 @@
|
|
|
72
72
|
"name": "OperatorSet",
|
|
73
73
|
"type": "event"
|
|
74
74
|
},
|
|
75
|
+
{
|
|
76
|
+
"anonymous": false,
|
|
77
|
+
"inputs": [
|
|
78
|
+
{
|
|
79
|
+
"indexed": true,
|
|
80
|
+
"internalType": "address",
|
|
81
|
+
"name": "lostAccount",
|
|
82
|
+
"type": "address"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"indexed": true,
|
|
86
|
+
"internalType": "address",
|
|
87
|
+
"name": "newAccount",
|
|
88
|
+
"type": "address"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"indexed": false,
|
|
92
|
+
"internalType": "euint64",
|
|
93
|
+
"name": "amount",
|
|
94
|
+
"type": "bytes32"
|
|
95
|
+
}
|
|
96
|
+
],
|
|
97
|
+
"name": "TokensRecovered",
|
|
98
|
+
"type": "event"
|
|
99
|
+
},
|
|
75
100
|
{
|
|
76
101
|
"inputs": [
|
|
77
102
|
{
|
|
@@ -621,6 +646,44 @@
|
|
|
621
646
|
"stateMutability": "nonpayable",
|
|
622
647
|
"type": "function"
|
|
623
648
|
},
|
|
649
|
+
{
|
|
650
|
+
"inputs": [
|
|
651
|
+
{
|
|
652
|
+
"internalType": "address",
|
|
653
|
+
"name": "account",
|
|
654
|
+
"type": "address"
|
|
655
|
+
}
|
|
656
|
+
],
|
|
657
|
+
"name": "isAdmin",
|
|
658
|
+
"outputs": [
|
|
659
|
+
{
|
|
660
|
+
"internalType": "bool",
|
|
661
|
+
"name": "",
|
|
662
|
+
"type": "bool"
|
|
663
|
+
}
|
|
664
|
+
],
|
|
665
|
+
"stateMutability": "view",
|
|
666
|
+
"type": "function"
|
|
667
|
+
},
|
|
668
|
+
{
|
|
669
|
+
"inputs": [
|
|
670
|
+
{
|
|
671
|
+
"internalType": "address",
|
|
672
|
+
"name": "account",
|
|
673
|
+
"type": "address"
|
|
674
|
+
}
|
|
675
|
+
],
|
|
676
|
+
"name": "isAgent",
|
|
677
|
+
"outputs": [
|
|
678
|
+
{
|
|
679
|
+
"internalType": "bool",
|
|
680
|
+
"name": "",
|
|
681
|
+
"type": "bool"
|
|
682
|
+
}
|
|
683
|
+
],
|
|
684
|
+
"stateMutability": "view",
|
|
685
|
+
"type": "function"
|
|
686
|
+
},
|
|
624
687
|
{
|
|
625
688
|
"inputs": [
|
|
626
689
|
{
|
|
@@ -678,6 +741,30 @@
|
|
|
678
741
|
"stateMutability": "view",
|
|
679
742
|
"type": "function"
|
|
680
743
|
},
|
|
744
|
+
{
|
|
745
|
+
"inputs": [
|
|
746
|
+
{
|
|
747
|
+
"internalType": "address",
|
|
748
|
+
"name": "lostAccount",
|
|
749
|
+
"type": "address"
|
|
750
|
+
},
|
|
751
|
+
{
|
|
752
|
+
"internalType": "address",
|
|
753
|
+
"name": "newAccount",
|
|
754
|
+
"type": "address"
|
|
755
|
+
}
|
|
756
|
+
],
|
|
757
|
+
"name": "recoverAddress",
|
|
758
|
+
"outputs": [
|
|
759
|
+
{
|
|
760
|
+
"internalType": "euint64",
|
|
761
|
+
"name": "",
|
|
762
|
+
"type": "bytes32"
|
|
763
|
+
}
|
|
764
|
+
],
|
|
765
|
+
"stateMutability": "nonpayable",
|
|
766
|
+
"type": "function"
|
|
767
|
+
},
|
|
681
768
|
{
|
|
682
769
|
"inputs": [
|
|
683
770
|
{
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.5.0) (finance/BatcherConfidential.sol)
|
|
3
3
|
|
|
4
4
|
pragma solidity ^0.8.27;
|
|
5
5
|
|
|
6
|
-
import {FHE, externalEuint64, euint64, ebool
|
|
6
|
+
import {FHE, externalEuint64, euint64, ebool} from "@fhevm/solidity/lib/FHE.sol";
|
|
7
7
|
import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol";
|
|
8
8
|
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
9
9
|
import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
|
|
@@ -16,8 +16,8 @@ import {FHESafeMath} from "./../utils/FHESafeMath.sol";
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* @dev `BatcherConfidential` is a batching primitive that enables routing between two {ERC7984ERC20Wrapper} contracts
|
|
19
|
-
* via a non-confidential route. Users deposit {fromToken} into the batcher and receive
|
|
20
|
-
* made by using `ERC7984` transfer and call functions such as {ERC7984-confidentialTransferAndCall}.
|
|
19
|
+
* (with distinct underlying tokens) via a non-confidential route. Users deposit {fromToken} into the batcher and receive
|
|
20
|
+
* {toToken} in exchange. Deposits are made by using `ERC7984` transfer and call functions such as {ERC7984-confidentialTransferAndCall}.
|
|
21
21
|
*
|
|
22
22
|
* Developers must implement the virtual function {_executeRoute} to perform the batch's route. This function is called
|
|
23
23
|
* once the batch deposits are unwrapped into the underlying tokens. The function should swap the underlying {fromToken} for
|
|
@@ -110,6 +110,12 @@ abstract contract BatcherConfidential is ReentrancyGuardTransient, IERC7984Recei
|
|
|
110
110
|
/// @dev The given `token` does not support `IERC7984ERC20Wrapper` via `ERC165`.
|
|
111
111
|
error InvalidWrapperToken(address token);
|
|
112
112
|
|
|
113
|
+
/// @dev The underlying wrapper tokens are the same.
|
|
114
|
+
error DuplicateUnderlyingTokens();
|
|
115
|
+
|
|
116
|
+
/// @dev Intermediate steps must not result in underlying {toToken} being transferred to or from the batcher.
|
|
117
|
+
error IntermediateStepToTokenBalanceChanged(uint256 batchId);
|
|
118
|
+
|
|
113
119
|
constructor(IERC7984ERC20Wrapper fromToken_, IERC7984ERC20Wrapper toToken_) {
|
|
114
120
|
require(
|
|
115
121
|
ERC165Checker.supportsInterface(address(fromToken_), type(IERC7984ERC20Wrapper).interfaceId),
|
|
@@ -119,6 +125,7 @@ abstract contract BatcherConfidential is ReentrancyGuardTransient, IERC7984Recei
|
|
|
119
125
|
ERC165Checker.supportsInterface(address(toToken_), type(IERC7984ERC20Wrapper).interfaceId),
|
|
120
126
|
InvalidWrapperToken(address(toToken_))
|
|
121
127
|
);
|
|
128
|
+
require(fromToken_.underlying() != toToken_.underlying(), DuplicateUnderlyingTokens());
|
|
122
129
|
|
|
123
130
|
_fromToken = fromToken_;
|
|
124
131
|
_toToken = toToken_;
|
|
@@ -216,10 +223,13 @@ abstract contract BatcherConfidential is ReentrancyGuardTransient, IERC7984Recei
|
|
|
216
223
|
FHE.checkSignatures(handles, abi.encode(unwrapAmountCleartext), decryptionProof);
|
|
217
224
|
}
|
|
218
225
|
|
|
226
|
+
uint256 beforeUnderlyingToTokenBalance;
|
|
227
|
+
|
|
219
228
|
ExecuteOutcome outcome;
|
|
220
229
|
if (unwrapAmountCleartext == 0) {
|
|
221
230
|
outcome = ExecuteOutcome.Cancel;
|
|
222
231
|
} else {
|
|
232
|
+
beforeUnderlyingToTokenBalance = IERC20(toToken().underlying()).balanceOf(address(this));
|
|
223
233
|
outcome = _executeRoute(batchId, unwrapAmountCleartext);
|
|
224
234
|
}
|
|
225
235
|
|
|
@@ -251,6 +261,11 @@ abstract contract BatcherConfidential is ReentrancyGuardTransient, IERC7984Recei
|
|
|
251
261
|
_batches[batchId].canceled = true;
|
|
252
262
|
|
|
253
263
|
emit BatchCanceled(batchId);
|
|
264
|
+
} else if (outcome == ExecuteOutcome.Partial) {
|
|
265
|
+
require(
|
|
266
|
+
IERC20(toToken().underlying()).balanceOf(address(this)) == beforeUnderlyingToTokenBalance,
|
|
267
|
+
IntermediateStepToTokenBalanceChanged(batchId)
|
|
268
|
+
);
|
|
254
269
|
}
|
|
255
270
|
}
|
|
256
271
|
|
|
@@ -401,7 +416,7 @@ abstract contract BatcherConfidential is ReentrancyGuardTransient, IERC7984Recei
|
|
|
401
416
|
*
|
|
402
417
|
* NOTE: {dispatchBatchCallback} (and in turn {_executeRoute}) can be repeatedly called until the route execution is complete.
|
|
403
418
|
* If a multi-step route is necessary, intermediate steps should return `ExecuteOutcome.Partial`. Intermediate steps *must* not
|
|
404
|
-
* result in underlying {toToken} being transferred
|
|
419
|
+
* result in underlying {toToken} being transferred to or from the batcher.
|
|
405
420
|
*
|
|
406
421
|
* [WARNING]
|
|
407
422
|
* ====
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.5.0) (governance/utils/VotesConfidential.sol)
|
|
3
3
|
|
|
4
4
|
pragma solidity ^0.8.26;
|
|
5
5
|
|
|
6
|
-
import {FHE,
|
|
6
|
+
import {FHE, euint64} from "@fhevm/solidity/lib/FHE.sol";
|
|
7
7
|
import {IERC6372} from "@openzeppelin/contracts/interfaces/IERC6372.sol";
|
|
8
8
|
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
|
|
9
9
|
import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.5.0) (interfaces/IERC7984HookModule.sol)
|
|
3
|
+
|
|
4
|
+
pragma solidity ^0.8.24;
|
|
5
|
+
|
|
6
|
+
import {euint64, ebool} from "@fhevm/solidity/lib/FHE.sol";
|
|
7
|
+
import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";
|
|
8
|
+
|
|
9
|
+
/// @dev Interface for an ERC-7984 hook module.
|
|
10
|
+
interface IERC7984HookModule is IERC165 {
|
|
11
|
+
/// @dev Optionally emitted by a module to indicate the result of its validation (pre-transfer) hook.
|
|
12
|
+
event ERC7984HookModuleResult(
|
|
13
|
+
address indexed token,
|
|
14
|
+
address indexed from,
|
|
15
|
+
address indexed to,
|
|
16
|
+
euint64 encryptedAmount,
|
|
17
|
+
ebool result,
|
|
18
|
+
bytes32 context
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @dev Hook that runs before a transfer. Should not mutate token state. Module is already
|
|
23
|
+
* granted transient access to `encryptedAmount`.
|
|
24
|
+
*/
|
|
25
|
+
function preTransfer(address from, address to, euint64 encryptedAmount) external returns (ebool);
|
|
26
|
+
|
|
27
|
+
/// @dev Performs operation after transfer.
|
|
28
|
+
function postTransfer(address from, address to, euint64 encryptedAmount) external;
|
|
29
|
+
|
|
30
|
+
/// @dev Performs operations after installation.
|
|
31
|
+
function onInstall(bytes calldata initData) external;
|
|
32
|
+
}
|
|
@@ -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) (interfaces/IERC7984Receiver.sol)
|
|
3
3
|
pragma solidity ^0.8.24;
|
|
4
4
|
|
|
5
5
|
import {ebool, euint64} from "@fhevm/solidity/lib/FHE.sol";
|
|
@@ -10,6 +10,8 @@ interface IERC7984Receiver {
|
|
|
10
10
|
* @dev Called upon receiving a confidential token transfer. Returns an encrypted boolean indicating success
|
|
11
11
|
* of the callback. If false is returned, the token contract will attempt to refund the transfer.
|
|
12
12
|
*
|
|
13
|
+
* NOTE: The calling contract (token) must be granted ACL allowance to read the confidential return value.
|
|
14
|
+
*
|
|
13
15
|
* WARNING: Do not manually refund the transfer AND return false, as this can lead to double refunds.
|
|
14
16
|
*/
|
|
15
17
|
function onConfidentialTransferReceived(
|
|
@@ -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) (interfaces/IERC7984Rwa.sol)
|
|
3
3
|
pragma solidity ^0.8.24;
|
|
4
4
|
|
|
5
5
|
import {externalEuint64, euint64} from "@fhevm/solidity/lib/FHE.sol";
|
|
@@ -7,46 +7,69 @@ import {IERC7984} from "./IERC7984.sol";
|
|
|
7
7
|
|
|
8
8
|
/// @dev Interface for confidential RWA contracts.
|
|
9
9
|
interface IERC7984Rwa is IERC7984 {
|
|
10
|
+
/// @dev Emitted when the balance `amount` of `lostAccount` is recovered to `newAccount`.
|
|
11
|
+
event TokensRecovered(address indexed lostAccount, address indexed newAccount, euint64 amount);
|
|
12
|
+
|
|
10
13
|
/// @dev Returns true if the contract is paused, false otherwise.
|
|
11
14
|
function paused() external view returns (bool);
|
|
15
|
+
|
|
16
|
+
/// @dev Returns true if has admin role, false otherwise.
|
|
17
|
+
function isAdmin(address account) external view returns (bool);
|
|
18
|
+
|
|
19
|
+
/// @dev Returns true if agent, false otherwise.
|
|
20
|
+
function isAgent(address account) external view returns (bool);
|
|
21
|
+
|
|
12
22
|
/// @dev Returns whether an account is allowed to interact with the token.
|
|
13
23
|
function canTransact(address account) external view returns (bool);
|
|
24
|
+
|
|
14
25
|
/// @dev Returns the confidential frozen balance of an account.
|
|
15
26
|
function confidentialFrozen(address account) external view returns (euint64);
|
|
27
|
+
|
|
16
28
|
/// @dev Returns the confidential available (unfrozen) balance of an account. Up to {IERC7984-confidentialBalanceOf}.
|
|
17
29
|
function confidentialAvailable(address account) external returns (euint64);
|
|
30
|
+
|
|
18
31
|
/// @dev Pauses contract.
|
|
19
32
|
function pause() external;
|
|
33
|
+
|
|
20
34
|
/// @dev Unpauses contract.
|
|
21
35
|
function unpause() external;
|
|
36
|
+
|
|
22
37
|
/// @dev Blocks a user account.
|
|
23
38
|
function blockUser(address account) external;
|
|
39
|
+
|
|
24
40
|
/// @dev Unblocks a user account.
|
|
25
41
|
function unblockUser(address account) external;
|
|
42
|
+
|
|
26
43
|
/// @dev Sets confidential amount of token for an account as frozen with proof.
|
|
27
44
|
function setConfidentialFrozen(
|
|
28
45
|
address account,
|
|
29
46
|
externalEuint64 encryptedAmount,
|
|
30
47
|
bytes calldata inputProof
|
|
31
48
|
) external;
|
|
49
|
+
|
|
32
50
|
/// @dev Sets confidential amount of token for an account as frozen.
|
|
33
51
|
function setConfidentialFrozen(address account, euint64 encryptedAmount) external;
|
|
52
|
+
|
|
34
53
|
/// @dev Mints confidential amount of tokens to account with proof.
|
|
35
54
|
function confidentialMint(
|
|
36
55
|
address to,
|
|
37
56
|
externalEuint64 encryptedAmount,
|
|
38
57
|
bytes calldata inputProof
|
|
39
58
|
) external returns (euint64);
|
|
59
|
+
|
|
40
60
|
/// @dev Mints confidential amount of tokens to account.
|
|
41
61
|
function confidentialMint(address to, euint64 encryptedAmount) external returns (euint64);
|
|
62
|
+
|
|
42
63
|
/// @dev Burns confidential amount of tokens from account with proof.
|
|
43
64
|
function confidentialBurn(
|
|
44
65
|
address account,
|
|
45
66
|
externalEuint64 encryptedAmount,
|
|
46
67
|
bytes calldata inputProof
|
|
47
68
|
) external returns (euint64);
|
|
69
|
+
|
|
48
70
|
/// @dev Burns confidential amount of tokens from account.
|
|
49
71
|
function confidentialBurn(address account, euint64 encryptedAmount) external returns (euint64);
|
|
72
|
+
|
|
50
73
|
/// @dev Forces transfer of confidential amount of tokens from account to account with proof by skipping compliance checks.
|
|
51
74
|
function forceConfidentialTransferFrom(
|
|
52
75
|
address from,
|
|
@@ -54,10 +77,14 @@ interface IERC7984Rwa is IERC7984 {
|
|
|
54
77
|
externalEuint64 encryptedAmount,
|
|
55
78
|
bytes calldata inputProof
|
|
56
79
|
) external returns (euint64);
|
|
80
|
+
|
|
57
81
|
/// @dev Forces transfer of confidential amount of tokens from account to account by skipping compliance checks.
|
|
58
82
|
function forceConfidentialTransferFrom(
|
|
59
83
|
address from,
|
|
60
84
|
address to,
|
|
61
85
|
euint64 encryptedAmount
|
|
62
86
|
) external returns (euint64);
|
|
87
|
+
|
|
88
|
+
/// @dev Recovers the address of a lost account to a new account.
|
|
89
|
+
function recoverAddress(address lostAccount, address newAccount) external returns (euint64);
|
|
63
90
|
}
|
package/package.json
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) (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";
|
|
@@ -44,9 +44,6 @@ abstract contract ERC7984 is IERC7984, ERC165 {
|
|
|
44
44
|
/// @dev The given holder `holder` is not authorized to spend on behalf of `spender`.
|
|
45
45
|
error ERC7984UnauthorizedSpender(address holder, address spender);
|
|
46
46
|
|
|
47
|
-
/// @dev The holder `holder` is trying to send tokens but has a balance of 0.
|
|
48
|
-
error ERC7984ZeroBalance(address holder);
|
|
49
|
-
|
|
50
47
|
/**
|
|
51
48
|
* @dev The caller `user` does not have access to the encrypted amount `amount`.
|
|
52
49
|
*
|
|
@@ -57,9 +54,6 @@ abstract contract ERC7984 is IERC7984, ERC165 {
|
|
|
57
54
|
/// @dev The given caller `caller` is not authorized for the current operation.
|
|
58
55
|
error ERC7984UnauthorizedCaller(address caller);
|
|
59
56
|
|
|
60
|
-
/// @dev The given gateway request ID `requestId` is invalid.
|
|
61
|
-
error ERC7984InvalidGatewayRequest(uint256 requestId);
|
|
62
|
-
|
|
63
57
|
constructor(string memory name_, string memory symbol_, string memory contractURI_) {
|
|
64
58
|
_name = name_;
|
|
65
59
|
_symbol = symbol_;
|
|
@@ -106,7 +100,10 @@ abstract contract ERC7984 is IERC7984, ERC165 {
|
|
|
106
100
|
return holder == spender || block.timestamp <= _operators[holder][spender];
|
|
107
101
|
}
|
|
108
102
|
|
|
109
|
-
|
|
103
|
+
/**
|
|
104
|
+
* @dev See {IERC7984-setOperator}. Operators are given ACL allowance (ability to decrypt) for the transferred amount
|
|
105
|
+
* of transfers they initiate.
|
|
106
|
+
*/
|
|
110
107
|
function setOperator(address operator, uint48 until) public virtual {
|
|
111
108
|
_setOperator(msg.sender, operator, until);
|
|
112
109
|
}
|
|
@@ -132,22 +129,20 @@ abstract contract ERC7984 is IERC7984, ERC165 {
|
|
|
132
129
|
address to,
|
|
133
130
|
externalEuint64 encryptedAmount,
|
|
134
131
|
bytes calldata inputProof
|
|
135
|
-
) public virtual returns (euint64
|
|
132
|
+
) public virtual returns (euint64) {
|
|
136
133
|
require(isOperator(from, msg.sender), ERC7984UnauthorizedSpender(from, msg.sender));
|
|
137
|
-
transferred = _transfer(from, to, FHE.fromExternal(encryptedAmount, inputProof));
|
|
134
|
+
euint64 transferred = _transfer(from, to, FHE.fromExternal(encryptedAmount, inputProof));
|
|
138
135
|
FHE.allowTransient(transferred, msg.sender);
|
|
136
|
+
return transferred;
|
|
139
137
|
}
|
|
140
138
|
|
|
141
139
|
/// @inheritdoc IERC7984
|
|
142
|
-
function confidentialTransferFrom(
|
|
143
|
-
address from,
|
|
144
|
-
address to,
|
|
145
|
-
euint64 amount
|
|
146
|
-
) public virtual returns (euint64 transferred) {
|
|
140
|
+
function confidentialTransferFrom(address from, address to, euint64 amount) public virtual returns (euint64) {
|
|
147
141
|
require(FHE.isAllowed(amount, msg.sender), ERC7984UnauthorizedUseOfEncryptedAmount(amount, msg.sender));
|
|
148
142
|
require(isOperator(from, msg.sender), ERC7984UnauthorizedSpender(from, msg.sender));
|
|
149
|
-
transferred = _transfer(from, to, amount);
|
|
143
|
+
euint64 transferred = _transfer(from, to, amount);
|
|
150
144
|
FHE.allowTransient(transferred, msg.sender);
|
|
145
|
+
return transferred;
|
|
151
146
|
}
|
|
152
147
|
|
|
153
148
|
/// @inheritdoc IERC7984
|
|
@@ -156,9 +151,8 @@ abstract contract ERC7984 is IERC7984, ERC165 {
|
|
|
156
151
|
externalEuint64 encryptedAmount,
|
|
157
152
|
bytes calldata inputProof,
|
|
158
153
|
bytes calldata data
|
|
159
|
-
) public virtual returns (euint64
|
|
160
|
-
|
|
161
|
-
FHE.allowTransient(transferred, msg.sender);
|
|
154
|
+
) public virtual returns (euint64) {
|
|
155
|
+
return _transferAndCall(msg.sender, to, FHE.fromExternal(encryptedAmount, inputProof), data);
|
|
162
156
|
}
|
|
163
157
|
|
|
164
158
|
/// @inheritdoc IERC7984
|
|
@@ -166,10 +160,9 @@ abstract contract ERC7984 is IERC7984, ERC165 {
|
|
|
166
160
|
address to,
|
|
167
161
|
euint64 amount,
|
|
168
162
|
bytes calldata data
|
|
169
|
-
) public virtual returns (euint64
|
|
163
|
+
) public virtual returns (euint64) {
|
|
170
164
|
require(FHE.isAllowed(amount, msg.sender), ERC7984UnauthorizedUseOfEncryptedAmount(amount, msg.sender));
|
|
171
|
-
|
|
172
|
-
FHE.allowTransient(transferred, msg.sender);
|
|
165
|
+
return _transferAndCall(msg.sender, to, amount, data);
|
|
173
166
|
}
|
|
174
167
|
|
|
175
168
|
/// @inheritdoc IERC7984
|
|
@@ -179,10 +172,9 @@ abstract contract ERC7984 is IERC7984, ERC165 {
|
|
|
179
172
|
externalEuint64 encryptedAmount,
|
|
180
173
|
bytes calldata inputProof,
|
|
181
174
|
bytes calldata data
|
|
182
|
-
) public virtual returns (euint64
|
|
175
|
+
) public virtual returns (euint64) {
|
|
183
176
|
require(isOperator(from, msg.sender), ERC7984UnauthorizedSpender(from, msg.sender));
|
|
184
|
-
|
|
185
|
-
FHE.allowTransient(transferred, msg.sender);
|
|
177
|
+
return _transferAndCall(from, to, FHE.fromExternal(encryptedAmount, inputProof), data);
|
|
186
178
|
}
|
|
187
179
|
|
|
188
180
|
/// @inheritdoc IERC7984
|
|
@@ -191,11 +183,10 @@ abstract contract ERC7984 is IERC7984, ERC165 {
|
|
|
191
183
|
address to,
|
|
192
184
|
euint64 amount,
|
|
193
185
|
bytes calldata data
|
|
194
|
-
) public virtual returns (euint64
|
|
186
|
+
) public virtual returns (euint64) {
|
|
195
187
|
require(FHE.isAllowed(amount, msg.sender), ERC7984UnauthorizedUseOfEncryptedAmount(amount, msg.sender));
|
|
196
188
|
require(isOperator(from, msg.sender), ERC7984UnauthorizedSpender(from, msg.sender));
|
|
197
|
-
|
|
198
|
-
FHE.allowTransient(transferred, msg.sender);
|
|
189
|
+
return _transferAndCall(from, to, amount, data);
|
|
199
190
|
}
|
|
200
191
|
|
|
201
192
|
/**
|
|
@@ -255,6 +246,25 @@ abstract contract ERC7984 is IERC7984, ERC165 {
|
|
|
255
246
|
return _update(from, to, amount);
|
|
256
247
|
}
|
|
257
248
|
|
|
249
|
+
/**
|
|
250
|
+
* @dev Transfers the given amount of tokens from `from` to `to` and calls the `onConfidentialTransferReceived`
|
|
251
|
+
* function on the recipient.
|
|
252
|
+
*
|
|
253
|
+
* The token contract initiates a second transfer refunding the tokens from the recipient to the sender--the
|
|
254
|
+
* amount is 0 if the callback succeeds, otherwise the amount is the amount that was transferred.
|
|
255
|
+
*
|
|
256
|
+
* The returned `transferred` amount is a fresh ciphertext computed as `sent - refund`
|
|
257
|
+
* and `msg.sender` only receives a transient FHE allowance for it. This value is generally
|
|
258
|
+
* intended to be processed only in the same transaction. Event observers see `sent` and `refund` individually.
|
|
259
|
+
*
|
|
260
|
+
* WARNING: The refund triggered when {IERC7984Receiver-onConfidentialTransferReceived} returns an encrypted
|
|
261
|
+
* false is best-effort only. A receiver that transfers, burns, or otherwise reduces its balance during
|
|
262
|
+
* the hook can still return false, in which case the refund transfers zero tokens. The sender's tokens
|
|
263
|
+
* end up with the recipient rather than being refunded.
|
|
264
|
+
*
|
|
265
|
+
* WARNING: Refunds are subject to the same validation flow as a normal transfer--they may fail for a variety of
|
|
266
|
+
* reasons (such as failed hook validation in {ERC7984Hooked}). In these cases, the tokens do not return to the sender.
|
|
267
|
+
*/
|
|
258
268
|
function _transferAndCall(
|
|
259
269
|
address from,
|
|
260
270
|
address to,
|
|
@@ -270,8 +280,13 @@ abstract contract ERC7984 is IERC7984, ERC165 {
|
|
|
270
280
|
// Try to refund if callback fails
|
|
271
281
|
euint64 refund = _update(to, from, FHE.select(success, FHE.asEuint64(0), sent));
|
|
272
282
|
transferred = FHE.sub(sent, refund);
|
|
283
|
+
FHE.allowTransient(transferred, msg.sender);
|
|
273
284
|
}
|
|
274
285
|
|
|
286
|
+
/**
|
|
287
|
+
* @dev Safely moves up to `amount` from `from` to `to`, or mints/burns if `from`/`to` is the zero address.
|
|
288
|
+
* Emits a {ConfidentialTransfer} event with the successfully transferred amount.
|
|
289
|
+
*/
|
|
275
290
|
function _update(address from, address to, euint64 amount) internal virtual returns (euint64 transferred) {
|
|
276
291
|
ebool success;
|
|
277
292
|
euint64 ptr;
|
|
@@ -282,7 +297,6 @@ abstract contract ERC7984 is IERC7984, ERC165 {
|
|
|
282
297
|
_totalSupply = ptr;
|
|
283
298
|
} else {
|
|
284
299
|
euint64 fromBalance = _balances[from];
|
|
285
|
-
require(FHE.isInitialized(fromBalance), ERC7984ZeroBalance(from));
|
|
286
300
|
(success, ptr) = FHESafeMath.tryDecrease(fromBalance, amount);
|
|
287
301
|
FHE.allowThis(ptr);
|
|
288
302
|
FHE.allow(ptr, from);
|
|
@@ -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) (token/ERC7984/extensions/ERC7984ERC20Wrapper.sol)
|
|
3
3
|
|
|
4
4
|
pragma solidity ^0.8.27;
|
|
5
5
|
|
|
@@ -180,8 +180,8 @@ abstract contract ERC7984ERC20Wrapper is ERC7984, IERC7984ERC20Wrapper, IERC1363
|
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
/**
|
|
183
|
-
* @dev
|
|
184
|
-
* unwrap request
|
|
183
|
+
* @dev Gets the address that will receive the ERC-20 tokens associated with a pending unwrap request identified by
|
|
184
|
+
* `unwrapRequestId`. Returns `address(0)` if there is no pending unwrap request with id `unwrapRequestId`.
|
|
185
185
|
*/
|
|
186
186
|
function unwrapRequester(bytes32 unwrapRequestId) public view virtual returns (address) {
|
|
187
187
|
return _unwrapRequests[unwrapRequestId];
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.5.0) (token/ERC7984/extensions/ERC7984Freezable.sol)
|
|
3
3
|
|
|
4
4
|
pragma solidity ^0.8.27;
|
|
5
5
|
|
|
6
|
-
import {FHE,
|
|
6
|
+
import {FHE, euint64} from "@fhevm/solidity/lib/FHE.sol";
|
|
7
7
|
import {FHESafeMath} from "../../../utils/FHESafeMath.sol";
|
|
8
8
|
import {ERC7984} from "../ERC7984.sol";
|
|
9
9
|
|
|
@@ -40,11 +40,7 @@ abstract contract ERC7984Freezable is ERC7984 {
|
|
|
40
40
|
|
|
41
41
|
/// @dev Internal function to calculate the available balance of an account. Does not give any allowances.
|
|
42
42
|
function _confidentialAvailable(address account) internal virtual returns (euint64) {
|
|
43
|
-
(
|
|
44
|
-
confidentialBalanceOf(account),
|
|
45
|
-
confidentialFrozen(account)
|
|
46
|
-
);
|
|
47
|
-
return FHE.select(success, unfrozen, FHE.asEuint64(0));
|
|
43
|
+
return FHESafeMath.saturatingSub(confidentialBalanceOf(account), confidentialFrozen(account));
|
|
48
44
|
}
|
|
49
45
|
|
|
50
46
|
/// @dev Internal function to freeze a confidential amount of tokens for an account.
|