@openzeppelin/confidential-contracts 0.2.0 → 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.
- package/build/contracts/Checkpoints.json +2 -2
- package/build/contracts/CheckpointsConfidential.json +2 -2
- package/build/contracts/{ConfidentialFungibleToken.json → ERC7984.json} +28 -33
- package/build/contracts/{ConfidentialFungibleTokenERC20Wrapper.json → ERC7984ERC20Wrapper.json} +34 -39
- package/build/contracts/ERC7984Freezable.json +666 -0
- package/build/contracts/ERC7984ObserverAccess.json +676 -0
- package/build/contracts/ERC7984Omnibus.json +994 -0
- package/build/contracts/ERC7984Restricted.json +677 -0
- package/build/contracts/ERC7984Rwa.json +1370 -0
- package/build/contracts/{ConfidentialFungibleTokenUtils.json → ERC7984Utils.json} +4 -4
- package/build/contracts/{ConfidentialFungibleTokenVotes.json → ERC7984Votes.json} +76 -81
- package/build/contracts/FHESafeMath.json +2 -2
- package/build/contracts/{IConfidentialFungibleToken.json → IERC7984.json} +15 -15
- package/build/contracts/{IConfidentialFungibleTokenReceiver.json → IERC7984Receiver.json} +2 -2
- package/build/contracts/IERC7984Rwa.json +797 -0
- package/build/contracts/VestingWalletConfidentialFactory.json +2 -2
- package/finance/VestingWalletConfidential.sol +6 -9
- package/finance/VestingWalletConfidentialFactory.sol +7 -12
- package/interfaces/{IConfidentialFungibleToken.sol → IERC7984.sol} +5 -5
- package/interfaces/{IConfidentialFungibleTokenReceiver.sol → IERC7984Receiver.sol} +3 -3
- package/interfaces/IERC7984Rwa.sol +64 -0
- package/package.json +4 -4
- package/token/{ConfidentialFungibleToken.sol → ERC7984/ERC7984.sol} +68 -76
- package/token/{extensions/ConfidentialFungibleTokenERC20Wrapper.sol → ERC7984/extensions/ERC7984ERC20Wrapper.sol} +18 -20
- package/token/ERC7984/extensions/ERC7984Freezable.sol +66 -0
- package/token/ERC7984/extensions/ERC7984ObserverAccess.sol +63 -0
- package/token/ERC7984/extensions/ERC7984Omnibus.sol +209 -0
- package/token/ERC7984/extensions/ERC7984Restricted.sol +118 -0
- package/token/ERC7984/extensions/ERC7984Rwa.sol +236 -0
- package/token/{extensions/ConfidentialFungibleTokenVotes.sol → ERC7984/extensions/ERC7984Votes.sol} +8 -14
- package/token/{utils/ConfidentialFungibleTokenUtils.sol → ERC7984/utils/ERC7984Utils.sol} +12 -12
- package/utils/FHESafeMath.sol +42 -7
- package/utils/structs/temporary-Checkpoints.sol +2 -2
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
{
|
|
56
56
|
"indexed": true,
|
|
57
57
|
"internalType": "address",
|
|
58
|
-
"name": "
|
|
58
|
+
"name": "token",
|
|
59
59
|
"type": "address"
|
|
60
60
|
},
|
|
61
61
|
{
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"inputs": [
|
|
79
79
|
{
|
|
80
80
|
"internalType": "address",
|
|
81
|
-
"name": "
|
|
81
|
+
"name": "token",
|
|
82
82
|
"type": "address"
|
|
83
83
|
},
|
|
84
84
|
{
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.
|
|
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 {
|
|
8
|
+
import {IERC7984} from "./../interfaces/IERC7984.sol";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* @dev A vesting wallet is an ownable contract that can receive
|
|
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.
|
|
@@ -63,7 +63,7 @@ abstract contract VestingWalletConfidential is OwnableUpgradeable, ReentrancyGua
|
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
65
|
* @dev Getter for the amount of releasable `token` tokens. `token` should be the address of an
|
|
66
|
-
* {
|
|
66
|
+
* {IERC7984} contract.
|
|
67
67
|
*/
|
|
68
68
|
function releasable(address token) public virtual returns (euint64) {
|
|
69
69
|
euint128 vestedAmount_ = vestedAmount(token, uint48(block.timestamp));
|
|
@@ -80,7 +80,7 @@ abstract contract VestingWalletConfidential is OwnableUpgradeable, ReentrancyGua
|
|
|
80
80
|
function release(address token) public virtual nonReentrant {
|
|
81
81
|
euint64 amount = releasable(token);
|
|
82
82
|
FHE.allowTransient(amount, token);
|
|
83
|
-
euint64 amountSent =
|
|
83
|
+
euint64 amountSent = IERC7984(token).confidentialTransfer(owner(), amount);
|
|
84
84
|
|
|
85
85
|
// This could overflow if the total supply is resent `type(uint128).max/type(uint64).max` times. This is an accepted risk.
|
|
86
86
|
euint128 newReleasedAmount = FHE.add(released(token), amountSent);
|
|
@@ -96,10 +96,7 @@ abstract contract VestingWalletConfidential is OwnableUpgradeable, ReentrancyGua
|
|
|
96
96
|
*/
|
|
97
97
|
function vestedAmount(address token, uint48 timestamp) public virtual returns (euint128) {
|
|
98
98
|
return
|
|
99
|
-
_vestingSchedule(
|
|
100
|
-
FHE.add(released(token), IConfidentialFungibleToken(token).confidentialBalanceOf(address(this))),
|
|
101
|
-
timestamp
|
|
102
|
-
);
|
|
99
|
+
_vestingSchedule(FHE.add(released(token), IERC7984(token).confidentialBalanceOf(address(this))), timestamp);
|
|
103
100
|
}
|
|
104
101
|
|
|
105
102
|
/**
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.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";
|
|
6
6
|
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
|
|
7
|
-
import {
|
|
7
|
+
import {IERC7984} from "./../interfaces/IERC7984.sol";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* @dev A factory which enables batch funding of vesting wallets.
|
|
@@ -23,7 +23,7 @@ abstract contract VestingWalletConfidentialFactory {
|
|
|
23
23
|
/// @dev Emitted for each vesting wallet funded within a batch.
|
|
24
24
|
event VestingWalletConfidentialFunded(
|
|
25
25
|
address indexed vestingWalletConfidential,
|
|
26
|
-
address indexed
|
|
26
|
+
address indexed token,
|
|
27
27
|
euint64 transferredAmount,
|
|
28
28
|
bytes initArgs
|
|
29
29
|
);
|
|
@@ -43,7 +43,7 @@ abstract contract VestingWalletConfidentialFactory {
|
|
|
43
43
|
* Emits a {VestingWalletConfidentialFunded} event for each funded vesting plan.
|
|
44
44
|
*/
|
|
45
45
|
function batchFundVestingWalletConfidential(
|
|
46
|
-
address
|
|
46
|
+
address token,
|
|
47
47
|
VestingPlan[] calldata vestingPlans,
|
|
48
48
|
bytes calldata inputProof
|
|
49
49
|
) public virtual {
|
|
@@ -55,19 +55,14 @@ abstract contract VestingWalletConfidentialFactory {
|
|
|
55
55
|
address vestingWalletAddress = predictVestingWalletConfidential(vestingPlan.initArgs);
|
|
56
56
|
|
|
57
57
|
euint64 encryptedAmount = FHE.fromExternal(vestingPlan.encryptedAmount, inputProof);
|
|
58
|
-
FHE.allowTransient(encryptedAmount,
|
|
59
|
-
euint64 transferredAmount =
|
|
58
|
+
FHE.allowTransient(encryptedAmount, token);
|
|
59
|
+
euint64 transferredAmount = IERC7984(token).confidentialTransferFrom(
|
|
60
60
|
msg.sender,
|
|
61
61
|
vestingWalletAddress,
|
|
62
62
|
encryptedAmount
|
|
63
63
|
);
|
|
64
64
|
|
|
65
|
-
emit VestingWalletConfidentialFunded(
|
|
66
|
-
vestingWalletAddress,
|
|
67
|
-
confidentialFungibleToken,
|
|
68
|
-
transferredAmount,
|
|
69
|
-
vestingPlan.initArgs
|
|
70
|
-
);
|
|
65
|
+
emit VestingWalletConfidentialFunded(vestingWalletAddress, token, transferredAmount, vestingPlan.initArgs);
|
|
71
66
|
}
|
|
72
67
|
}
|
|
73
68
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.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
6
|
|
|
7
7
|
/// @dev Draft interface for a confidential fungible token standard utilizing the Zama FHE library.
|
|
8
|
-
interface
|
|
8
|
+
interface IERC7984 {
|
|
9
9
|
/**
|
|
10
10
|
* @dev Emitted when the expiration timestamp for an operator `operator` is updated for a given `holder`.
|
|
11
11
|
* The operator may move any amount of tokens on behalf of the holder until the timestamp `until`.
|
|
@@ -32,8 +32,8 @@ interface IConfidentialFungibleToken {
|
|
|
32
32
|
/// @dev Returns the number of decimals of the token. Recommended to be 6.
|
|
33
33
|
function decimals() external view returns (uint8);
|
|
34
34
|
|
|
35
|
-
/// @dev Returns the
|
|
36
|
-
function
|
|
35
|
+
/// @dev Returns the contract URI. See [ERC-7572](https://eips.ethereum.org/EIPS/eip-7572) for details.
|
|
36
|
+
function contractURI() external view returns (string memory);
|
|
37
37
|
|
|
38
38
|
/// @dev Returns the confidential total supply of the token.
|
|
39
39
|
function confidentialTotalSupply() external view returns (euint64);
|
|
@@ -91,7 +91,7 @@ interface IConfidentialFungibleToken {
|
|
|
91
91
|
* @dev Similar to {confidentialTransfer-address-externalEuint64-bytes} but with a callback to `to` after
|
|
92
92
|
* the transfer.
|
|
93
93
|
*
|
|
94
|
-
* The callback is made to the {
|
|
94
|
+
* The callback is made to the {IERC7984Receiver-onConfidentialTransferReceived} function on the
|
|
95
95
|
* to address with the actual transferred amount (may differ from the given `encryptedAmount`) and the given
|
|
96
96
|
* data `data`.
|
|
97
97
|
*/
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (interfaces/IERC7984Receiver.sol)
|
|
3
3
|
pragma solidity ^0.8.24;
|
|
4
4
|
|
|
5
5
|
import {ebool, euint64} from "@fhevm/solidity/lib/FHE.sol";
|
|
6
6
|
|
|
7
|
-
/// @dev Interface for contracts that can receive
|
|
8
|
-
interface
|
|
7
|
+
/// @dev Interface for contracts that can receive ERC7984 transfers with a callback.
|
|
8
|
+
interface IERC7984Receiver {
|
|
9
9
|
/**
|
|
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 transfer must be reversed.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (interfaces/IERC7984Rwa.sol)
|
|
3
|
+
pragma solidity ^0.8.24;
|
|
4
|
+
|
|
5
|
+
import {externalEuint64, euint64} from "@fhevm/solidity/lib/FHE.sol";
|
|
6
|
+
import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";
|
|
7
|
+
import {IERC7984} from "./IERC7984.sol";
|
|
8
|
+
|
|
9
|
+
/// @dev Interface for confidential RWA contracts.
|
|
10
|
+
interface IERC7984Rwa is IERC7984, IERC165 {
|
|
11
|
+
/// @dev Returns true if the contract is paused, false otherwise.
|
|
12
|
+
function paused() external view returns (bool);
|
|
13
|
+
/// @dev Returns whether an account is allowed to interact with the token.
|
|
14
|
+
function isUserAllowed(address account) external view returns (bool);
|
|
15
|
+
/// @dev Returns the confidential frozen balance of an account.
|
|
16
|
+
function confidentialFrozen(address account) external view returns (euint64);
|
|
17
|
+
/// @dev Returns the confidential available (unfrozen) balance of an account. Up to {IERC7984-confidentialBalanceOf}.
|
|
18
|
+
function confidentialAvailable(address account) external returns (euint64);
|
|
19
|
+
/// @dev Pauses contract.
|
|
20
|
+
function pause() external;
|
|
21
|
+
/// @dev Unpauses contract.
|
|
22
|
+
function unpause() external;
|
|
23
|
+
/// @dev Blocks a user account.
|
|
24
|
+
function blockUser(address account) external;
|
|
25
|
+
/// @dev Unblocks a user account.
|
|
26
|
+
function unblockUser(address account) external;
|
|
27
|
+
/// @dev Sets confidential amount of token for an account as frozen with proof.
|
|
28
|
+
function setConfidentialFrozen(
|
|
29
|
+
address account,
|
|
30
|
+
externalEuint64 encryptedAmount,
|
|
31
|
+
bytes calldata inputProof
|
|
32
|
+
) external;
|
|
33
|
+
/// @dev Sets confidential amount of token for an account as frozen.
|
|
34
|
+
function setConfidentialFrozen(address account, euint64 encryptedAmount) external;
|
|
35
|
+
/// @dev Mints confidential amount of tokens to account with proof.
|
|
36
|
+
function confidentialMint(
|
|
37
|
+
address to,
|
|
38
|
+
externalEuint64 encryptedAmount,
|
|
39
|
+
bytes calldata inputProof
|
|
40
|
+
) external returns (euint64);
|
|
41
|
+
/// @dev Mints confidential amount of tokens to account.
|
|
42
|
+
function confidentialMint(address to, euint64 encryptedAmount) external returns (euint64);
|
|
43
|
+
/// @dev Burns confidential amount of tokens from account with proof.
|
|
44
|
+
function confidentialBurn(
|
|
45
|
+
address account,
|
|
46
|
+
externalEuint64 encryptedAmount,
|
|
47
|
+
bytes calldata inputProof
|
|
48
|
+
) external returns (euint64);
|
|
49
|
+
/// @dev Burns confidential amount of tokens from account.
|
|
50
|
+
function confidentialBurn(address account, euint64 encryptedAmount) external returns (euint64);
|
|
51
|
+
/// @dev Forces transfer of confidential amount of tokens from account to account with proof by skipping compliance checks.
|
|
52
|
+
function forceConfidentialTransferFrom(
|
|
53
|
+
address from,
|
|
54
|
+
address to,
|
|
55
|
+
externalEuint64 encryptedAmount,
|
|
56
|
+
bytes calldata inputProof
|
|
57
|
+
) external returns (euint64);
|
|
58
|
+
/// @dev Forces transfer of confidential amount of tokens from account to account by skipping compliance checks.
|
|
59
|
+
function forceConfidentialTransferFrom(
|
|
60
|
+
address from,
|
|
61
|
+
address to,
|
|
62
|
+
euint64 encryptedAmount
|
|
63
|
+
) external returns (euint64);
|
|
64
|
+
}
|
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.
|
|
4
|
+
"version": "0.3.0-rc.0",
|
|
5
5
|
"files": [
|
|
6
6
|
"**/*.sol",
|
|
7
7
|
"/build/contracts/*.json",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
},
|
|
33
33
|
"homepage": "https://openzeppelin.com/contracts/",
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"@fhevm/solidity": "0.
|
|
36
|
-
"@openzeppelin/contracts": "^5.
|
|
37
|
-
"@openzeppelin/contracts-upgradeable": "^5.
|
|
35
|
+
"@fhevm/solidity": "0.8.0",
|
|
36
|
+
"@openzeppelin/contracts": "^5.4.0",
|
|
37
|
+
"@openzeppelin/contracts-upgradeable": "^5.4.0"
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.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 {
|
|
7
|
-
import {FHESafeMath} from "
|
|
8
|
-
import {
|
|
6
|
+
import {IERC7984} from "./../../interfaces/IERC7984.sol";
|
|
7
|
+
import {FHESafeMath} from "./../../utils/FHESafeMath.sol";
|
|
8
|
+
import {ERC7984Utils} from "./utils/ERC7984Utils.sol";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* @dev Reference implementation for {
|
|
11
|
+
* @dev Reference implementation for {IERC7984}.
|
|
12
12
|
*
|
|
13
13
|
* This contract implements a fungible token where balances and transfers are encrypted using the Zama fhEVM,
|
|
14
14
|
* providing confidentiality to users. Token amounts are stored as encrypted, unsigned integers (`euint64`)
|
|
@@ -22,87 +22,86 @@ import {ConfidentialFungibleTokenUtils} from "./utils/ConfidentialFungibleTokenU
|
|
|
22
22
|
* - Transfer and call pattern
|
|
23
23
|
* - Safe overflow/underflow handling for FHE operations
|
|
24
24
|
*/
|
|
25
|
-
abstract contract
|
|
25
|
+
abstract contract ERC7984 is IERC7984 {
|
|
26
26
|
mapping(address holder => euint64) private _balances;
|
|
27
27
|
mapping(address holder => mapping(address spender => uint48)) private _operators;
|
|
28
|
-
mapping(uint256 requestId => euint64 encryptedAmount) private _requestHandles;
|
|
29
28
|
euint64 private _totalSupply;
|
|
30
29
|
string private _name;
|
|
31
30
|
string private _symbol;
|
|
32
|
-
string private
|
|
31
|
+
string private _contractURI;
|
|
33
32
|
|
|
34
33
|
/// @dev The given receiver `receiver` is invalid for transfers.
|
|
35
|
-
error
|
|
34
|
+
error ERC7984InvalidReceiver(address receiver);
|
|
36
35
|
|
|
37
36
|
/// @dev The given sender `sender` is invalid for transfers.
|
|
38
|
-
error
|
|
37
|
+
error ERC7984InvalidSender(address sender);
|
|
39
38
|
|
|
40
39
|
/// @dev The given holder `holder` is not authorized to spend on behalf of `spender`.
|
|
41
|
-
error
|
|
40
|
+
error ERC7984UnauthorizedSpender(address holder, address spender);
|
|
42
41
|
|
|
43
42
|
/// @dev The holder `holder` is trying to send tokens but has a balance of 0.
|
|
44
|
-
error
|
|
43
|
+
error ERC7984ZeroBalance(address holder);
|
|
45
44
|
|
|
46
45
|
/**
|
|
47
46
|
* @dev The caller `user` does not have access to the encrypted amount `amount`.
|
|
48
47
|
*
|
|
49
48
|
* NOTE: Try using the equivalent transfer function with an input proof.
|
|
50
49
|
*/
|
|
51
|
-
error
|
|
50
|
+
error ERC7984UnauthorizedUseOfEncryptedAmount(euint64 amount, address user);
|
|
52
51
|
|
|
53
52
|
/// @dev The given caller `caller` is not authorized for the current operation.
|
|
54
|
-
error
|
|
53
|
+
error ERC7984UnauthorizedCaller(address caller);
|
|
55
54
|
|
|
56
55
|
/// @dev The given gateway request ID `requestId` is invalid.
|
|
57
|
-
error
|
|
56
|
+
error ERC7984InvalidGatewayRequest(uint256 requestId);
|
|
58
57
|
|
|
59
|
-
constructor(string memory name_, string memory symbol_, string memory
|
|
58
|
+
constructor(string memory name_, string memory symbol_, string memory contractURI_) {
|
|
60
59
|
_name = name_;
|
|
61
60
|
_symbol = symbol_;
|
|
62
|
-
|
|
61
|
+
_contractURI = contractURI_;
|
|
63
62
|
}
|
|
64
63
|
|
|
65
|
-
/// @inheritdoc
|
|
64
|
+
/// @inheritdoc IERC7984
|
|
66
65
|
function name() public view virtual returns (string memory) {
|
|
67
66
|
return _name;
|
|
68
67
|
}
|
|
69
68
|
|
|
70
|
-
/// @inheritdoc
|
|
69
|
+
/// @inheritdoc IERC7984
|
|
71
70
|
function symbol() public view virtual returns (string memory) {
|
|
72
71
|
return _symbol;
|
|
73
72
|
}
|
|
74
73
|
|
|
75
|
-
/// @inheritdoc
|
|
74
|
+
/// @inheritdoc IERC7984
|
|
76
75
|
function decimals() public view virtual returns (uint8) {
|
|
77
76
|
return 6;
|
|
78
77
|
}
|
|
79
78
|
|
|
80
|
-
/// @inheritdoc
|
|
81
|
-
function
|
|
82
|
-
return
|
|
79
|
+
/// @inheritdoc IERC7984
|
|
80
|
+
function contractURI() public view virtual returns (string memory) {
|
|
81
|
+
return _contractURI;
|
|
83
82
|
}
|
|
84
83
|
|
|
85
|
-
/// @inheritdoc
|
|
84
|
+
/// @inheritdoc IERC7984
|
|
86
85
|
function confidentialTotalSupply() public view virtual returns (euint64) {
|
|
87
86
|
return _totalSupply;
|
|
88
87
|
}
|
|
89
88
|
|
|
90
|
-
/// @inheritdoc
|
|
89
|
+
/// @inheritdoc IERC7984
|
|
91
90
|
function confidentialBalanceOf(address account) public view virtual returns (euint64) {
|
|
92
91
|
return _balances[account];
|
|
93
92
|
}
|
|
94
93
|
|
|
95
|
-
/// @inheritdoc
|
|
94
|
+
/// @inheritdoc IERC7984
|
|
96
95
|
function isOperator(address holder, address spender) public view virtual returns (bool) {
|
|
97
96
|
return holder == spender || block.timestamp <= _operators[holder][spender];
|
|
98
97
|
}
|
|
99
98
|
|
|
100
|
-
/// @inheritdoc
|
|
99
|
+
/// @inheritdoc IERC7984
|
|
101
100
|
function setOperator(address operator, uint48 until) public virtual {
|
|
102
101
|
_setOperator(msg.sender, operator, until);
|
|
103
102
|
}
|
|
104
103
|
|
|
105
|
-
/// @inheritdoc
|
|
104
|
+
/// @inheritdoc IERC7984
|
|
106
105
|
function confidentialTransfer(
|
|
107
106
|
address to,
|
|
108
107
|
externalEuint64 encryptedAmount,
|
|
@@ -111,43 +110,37 @@ abstract contract ConfidentialFungibleToken is IConfidentialFungibleToken {
|
|
|
111
110
|
return _transfer(msg.sender, to, FHE.fromExternal(encryptedAmount, inputProof));
|
|
112
111
|
}
|
|
113
112
|
|
|
114
|
-
/// @inheritdoc
|
|
113
|
+
/// @inheritdoc IERC7984
|
|
115
114
|
function confidentialTransfer(address to, euint64 amount) public virtual returns (euint64) {
|
|
116
|
-
require(
|
|
117
|
-
FHE.isAllowed(amount, msg.sender),
|
|
118
|
-
ConfidentialFungibleTokenUnauthorizedUseOfEncryptedAmount(amount, msg.sender)
|
|
119
|
-
);
|
|
115
|
+
require(FHE.isAllowed(amount, msg.sender), ERC7984UnauthorizedUseOfEncryptedAmount(amount, msg.sender));
|
|
120
116
|
return _transfer(msg.sender, to, amount);
|
|
121
117
|
}
|
|
122
118
|
|
|
123
|
-
/// @inheritdoc
|
|
119
|
+
/// @inheritdoc IERC7984
|
|
124
120
|
function confidentialTransferFrom(
|
|
125
121
|
address from,
|
|
126
122
|
address to,
|
|
127
123
|
externalEuint64 encryptedAmount,
|
|
128
124
|
bytes calldata inputProof
|
|
129
125
|
) public virtual returns (euint64 transferred) {
|
|
130
|
-
require(isOperator(from, msg.sender),
|
|
126
|
+
require(isOperator(from, msg.sender), ERC7984UnauthorizedSpender(from, msg.sender));
|
|
131
127
|
transferred = _transfer(from, to, FHE.fromExternal(encryptedAmount, inputProof));
|
|
132
128
|
FHE.allowTransient(transferred, msg.sender);
|
|
133
129
|
}
|
|
134
130
|
|
|
135
|
-
/// @inheritdoc
|
|
131
|
+
/// @inheritdoc IERC7984
|
|
136
132
|
function confidentialTransferFrom(
|
|
137
133
|
address from,
|
|
138
134
|
address to,
|
|
139
135
|
euint64 amount
|
|
140
136
|
) public virtual returns (euint64 transferred) {
|
|
141
|
-
require(
|
|
142
|
-
|
|
143
|
-
ConfidentialFungibleTokenUnauthorizedUseOfEncryptedAmount(amount, msg.sender)
|
|
144
|
-
);
|
|
145
|
-
require(isOperator(from, msg.sender), ConfidentialFungibleTokenUnauthorizedSpender(from, msg.sender));
|
|
137
|
+
require(FHE.isAllowed(amount, msg.sender), ERC7984UnauthorizedUseOfEncryptedAmount(amount, msg.sender));
|
|
138
|
+
require(isOperator(from, msg.sender), ERC7984UnauthorizedSpender(from, msg.sender));
|
|
146
139
|
transferred = _transfer(from, to, amount);
|
|
147
140
|
FHE.allowTransient(transferred, msg.sender);
|
|
148
141
|
}
|
|
149
142
|
|
|
150
|
-
/// @inheritdoc
|
|
143
|
+
/// @inheritdoc IERC7984
|
|
151
144
|
function confidentialTransferAndCall(
|
|
152
145
|
address to,
|
|
153
146
|
externalEuint64 encryptedAmount,
|
|
@@ -158,21 +151,18 @@ abstract contract ConfidentialFungibleToken is IConfidentialFungibleToken {
|
|
|
158
151
|
FHE.allowTransient(transferred, msg.sender);
|
|
159
152
|
}
|
|
160
153
|
|
|
161
|
-
/// @inheritdoc
|
|
154
|
+
/// @inheritdoc IERC7984
|
|
162
155
|
function confidentialTransferAndCall(
|
|
163
156
|
address to,
|
|
164
157
|
euint64 amount,
|
|
165
158
|
bytes calldata data
|
|
166
159
|
) public virtual returns (euint64 transferred) {
|
|
167
|
-
require(
|
|
168
|
-
FHE.isAllowed(amount, msg.sender),
|
|
169
|
-
ConfidentialFungibleTokenUnauthorizedUseOfEncryptedAmount(amount, msg.sender)
|
|
170
|
-
);
|
|
160
|
+
require(FHE.isAllowed(amount, msg.sender), ERC7984UnauthorizedUseOfEncryptedAmount(amount, msg.sender));
|
|
171
161
|
transferred = _transferAndCall(msg.sender, to, amount, data);
|
|
172
162
|
FHE.allowTransient(transferred, msg.sender);
|
|
173
163
|
}
|
|
174
164
|
|
|
175
|
-
/// @inheritdoc
|
|
165
|
+
/// @inheritdoc IERC7984
|
|
176
166
|
function confidentialTransferFromAndCall(
|
|
177
167
|
address from,
|
|
178
168
|
address to,
|
|
@@ -180,29 +170,26 @@ abstract contract ConfidentialFungibleToken is IConfidentialFungibleToken {
|
|
|
180
170
|
bytes calldata inputProof,
|
|
181
171
|
bytes calldata data
|
|
182
172
|
) public virtual returns (euint64 transferred) {
|
|
183
|
-
require(isOperator(from, msg.sender),
|
|
173
|
+
require(isOperator(from, msg.sender), ERC7984UnauthorizedSpender(from, msg.sender));
|
|
184
174
|
transferred = _transferAndCall(from, to, FHE.fromExternal(encryptedAmount, inputProof), data);
|
|
185
175
|
FHE.allowTransient(transferred, msg.sender);
|
|
186
176
|
}
|
|
187
177
|
|
|
188
|
-
/// @inheritdoc
|
|
178
|
+
/// @inheritdoc IERC7984
|
|
189
179
|
function confidentialTransferFromAndCall(
|
|
190
180
|
address from,
|
|
191
181
|
address to,
|
|
192
182
|
euint64 amount,
|
|
193
183
|
bytes calldata data
|
|
194
184
|
) public virtual returns (euint64 transferred) {
|
|
195
|
-
require(
|
|
196
|
-
|
|
197
|
-
ConfidentialFungibleTokenUnauthorizedUseOfEncryptedAmount(amount, msg.sender)
|
|
198
|
-
);
|
|
199
|
-
require(isOperator(from, msg.sender), ConfidentialFungibleTokenUnauthorizedSpender(from, msg.sender));
|
|
185
|
+
require(FHE.isAllowed(amount, msg.sender), ERC7984UnauthorizedUseOfEncryptedAmount(amount, msg.sender));
|
|
186
|
+
require(isOperator(from, msg.sender), ERC7984UnauthorizedSpender(from, msg.sender));
|
|
200
187
|
transferred = _transferAndCall(from, to, amount, data);
|
|
201
188
|
FHE.allowTransient(transferred, msg.sender);
|
|
202
189
|
}
|
|
203
190
|
|
|
204
191
|
/**
|
|
205
|
-
* @dev Discloses an encrypted amount `encryptedAmount` publicly via an {
|
|
192
|
+
* @dev Discloses an encrypted amount `encryptedAmount` publicly via an {IERC7984-AmountDisclosed}
|
|
206
193
|
* event. The caller and this contract must be authorized to use the encrypted amount on the ACL.
|
|
207
194
|
*
|
|
208
195
|
* NOTE: This is an asynchronous operation where the actual decryption happens off-chain and
|
|
@@ -210,29 +197,34 @@ abstract contract ConfidentialFungibleToken is IConfidentialFungibleToken {
|
|
|
210
197
|
*/
|
|
211
198
|
function discloseEncryptedAmount(euint64 encryptedAmount) public virtual {
|
|
212
199
|
require(
|
|
213
|
-
FHE.isAllowed(encryptedAmount, msg.sender)
|
|
214
|
-
|
|
200
|
+
FHE.isAllowed(encryptedAmount, msg.sender),
|
|
201
|
+
ERC7984UnauthorizedUseOfEncryptedAmount(encryptedAmount, msg.sender)
|
|
215
202
|
);
|
|
216
203
|
|
|
217
204
|
bytes32[] memory cts = new bytes32[](1);
|
|
218
205
|
cts[0] = euint64.unwrap(encryptedAmount);
|
|
219
|
-
|
|
220
|
-
_requestHandles[requestID] = encryptedAmount;
|
|
206
|
+
FHE.requestDecryption(cts, this.finalizeDiscloseEncryptedAmount.selector);
|
|
221
207
|
}
|
|
222
208
|
|
|
223
|
-
|
|
209
|
+
/**
|
|
210
|
+
* @dev Finalizes a disclose encrypted amount request.
|
|
211
|
+
* For gas saving purposes, the `requestId` might not be related to a
|
|
212
|
+
* {discloseEncryptedAmount} request. As a result, the current {finalizeDiscloseEncryptedAmount}
|
|
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
|
+
*/
|
|
224
220
|
function finalizeDiscloseEncryptedAmount(
|
|
225
221
|
uint256 requestId,
|
|
226
|
-
|
|
227
|
-
bytes
|
|
222
|
+
bytes calldata cleartexts,
|
|
223
|
+
bytes calldata decryptionProof
|
|
228
224
|
) public virtual {
|
|
229
|
-
FHE.checkSignatures(requestId,
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
require(FHE.isInitialized(requestHandle), ConfidentialFungibleTokenInvalidGatewayRequest(requestId));
|
|
233
|
-
emit AmountDisclosed(requestHandle, amount);
|
|
234
|
-
|
|
235
|
-
_requestHandles[requestId] = euint64.wrap(0);
|
|
225
|
+
FHE.checkSignatures(requestId, cleartexts, decryptionProof);
|
|
226
|
+
euint64 requestHandle = euint64.wrap(FHE.loadRequestedHandles(requestId)[0]);
|
|
227
|
+
emit AmountDisclosed(requestHandle, abi.decode(cleartexts, (uint64)));
|
|
236
228
|
}
|
|
237
229
|
|
|
238
230
|
function _setOperator(address holder, address operator, uint48 until) internal virtual {
|
|
@@ -241,18 +233,18 @@ abstract contract ConfidentialFungibleToken is IConfidentialFungibleToken {
|
|
|
241
233
|
}
|
|
242
234
|
|
|
243
235
|
function _mint(address to, euint64 amount) internal returns (euint64 transferred) {
|
|
244
|
-
require(to != address(0),
|
|
236
|
+
require(to != address(0), ERC7984InvalidReceiver(address(0)));
|
|
245
237
|
return _update(address(0), to, amount);
|
|
246
238
|
}
|
|
247
239
|
|
|
248
240
|
function _burn(address from, euint64 amount) internal returns (euint64 transferred) {
|
|
249
|
-
require(from != address(0),
|
|
241
|
+
require(from != address(0), ERC7984InvalidSender(address(0)));
|
|
250
242
|
return _update(from, address(0), amount);
|
|
251
243
|
}
|
|
252
244
|
|
|
253
245
|
function _transfer(address from, address to, euint64 amount) internal returns (euint64 transferred) {
|
|
254
|
-
require(from != address(0),
|
|
255
|
-
require(to != address(0),
|
|
246
|
+
require(from != address(0), ERC7984InvalidSender(address(0)));
|
|
247
|
+
require(to != address(0), ERC7984InvalidReceiver(address(0)));
|
|
256
248
|
return _update(from, to, amount);
|
|
257
249
|
}
|
|
258
250
|
|
|
@@ -266,7 +258,7 @@ abstract contract ConfidentialFungibleToken is IConfidentialFungibleToken {
|
|
|
266
258
|
euint64 sent = _transfer(from, to, amount);
|
|
267
259
|
|
|
268
260
|
// Perform callback
|
|
269
|
-
ebool success =
|
|
261
|
+
ebool success = ERC7984Utils.checkOnTransferReceived(msg.sender, from, to, sent, data);
|
|
270
262
|
|
|
271
263
|
// Try to refund if callback fails
|
|
272
264
|
euint64 refund = _update(to, from, FHE.select(success, FHE.asEuint64(0), sent));
|
|
@@ -283,7 +275,7 @@ abstract contract ConfidentialFungibleToken is IConfidentialFungibleToken {
|
|
|
283
275
|
_totalSupply = ptr;
|
|
284
276
|
} else {
|
|
285
277
|
euint64 fromBalance = _balances[from];
|
|
286
|
-
require(FHE.isInitialized(fromBalance),
|
|
278
|
+
require(FHE.isInitialized(fromBalance), ERC7984ZeroBalance(from));
|
|
287
279
|
(success, ptr) = FHESafeMath.tryDecrease(fromBalance, amount);
|
|
288
280
|
FHE.allowThis(ptr);
|
|
289
281
|
FHE.allow(ptr, from);
|