@openzeppelin/confidential-contracts 0.2.0-rc.1 → 0.2.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 +3 -9
- package/build/contracts/ConfidentialFungibleTokenUtils.json +2 -2
- package/build/contracts/ConfidentialFungibleTokenVotes.json +23 -0
- package/build/contracts/{TFHESafeMath.json → FHESafeMath.json} +4 -4
- package/build/contracts/HandleAccessManager.json +34 -0
- package/build/contracts/VestingWalletCliffConfidential.json +3 -3
- package/build/contracts/VestingWalletConfidential.json +3 -3
- package/build/contracts/VestingWalletConfidentialFactory.json +155 -0
- package/build/contracts/VotesConfidential.json +23 -0
- package/finance/ERC7821WithExecutor.sol +2 -2
- package/finance/VestingWalletCliffConfidential.sol +15 -4
- package/finance/VestingWalletConfidential.sol +28 -13
- package/finance/VestingWalletConfidentialFactory.sol +120 -0
- package/governance/utils/VotesConfidential.sol +18 -4
- package/interfaces/IConfidentialFungibleToken.sol +2 -2
- package/interfaces/IConfidentialFungibleTokenReceiver.sol +1 -1
- package/package.json +1 -1
- package/token/ConfidentialFungibleToken.sol +9 -12
- package/token/extensions/ConfidentialFungibleTokenERC20Wrapper.sol +19 -8
- package/token/extensions/ConfidentialFungibleTokenVotes.sol +9 -1
- package/token/utils/ConfidentialFungibleTokenUtils.sol +1 -1
- package/utils/{TFHESafeMath.sol → FHESafeMath.sol} +2 -2
- package/utils/HandleAccessManager.sol +29 -0
- package/utils/structs/CheckpointsConfidential.sol +1 -6
- package/utils/structs/temporary-Checkpoints.sol +1 -1
- package/build/contracts/VestingWalletCliffExecutorConfidential.json +0 -424
- package/build/contracts/VestingWalletCliffExecutorConfidentialFactory.json +0 -290
- package/finance/VestingWalletCliffExecutorConfidentialFactory.sol +0 -203
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"type": "error"
|
|
10
10
|
}
|
|
11
11
|
],
|
|
12
|
-
"bytecode": "
|
|
13
|
-
"deployedBytecode": "
|
|
12
|
+
"bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220a82f4123dc620a523cf32b417d00b9472eafbc138490892aba0950faef876e5f64736f6c634300081d0033",
|
|
13
|
+
"deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220a82f4123dc620a523cf32b417d00b9472eafbc138490892aba0950faef876e5f64736f6c634300081d0033",
|
|
14
14
|
"linkReferences": {},
|
|
15
15
|
"deployedLinkReferences": {}
|
|
16
16
|
}
|
|
@@ -2,15 +2,9 @@
|
|
|
2
2
|
"_format": "hh-sol-artifact-1",
|
|
3
3
|
"contractName": "CheckpointsConfidential",
|
|
4
4
|
"sourceName": "contracts/utils/structs/CheckpointsConfidential.sol",
|
|
5
|
-
"abi": [
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"name": "CheckpointUnorderedInsertion",
|
|
9
|
-
"type": "error"
|
|
10
|
-
}
|
|
11
|
-
],
|
|
12
|
-
"bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220364ffbf1ba7183f1c16596a69be847e39b8e467761b3ce24b8ce5f16c879b66764736f6c634300081d0033",
|
|
13
|
-
"deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220364ffbf1ba7183f1c16596a69be847e39b8e467761b3ce24b8ce5f16c879b66764736f6c634300081d0033",
|
|
5
|
+
"abi": [],
|
|
6
|
+
"bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122057a94665aa47e1eee66c46039103adce039864c0979c586fd3fca3eb7ee1340764736f6c634300081d0033",
|
|
7
|
+
"deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea264697066735822122057a94665aa47e1eee66c46039103adce039864c0979c586fd3fca3eb7ee1340764736f6c634300081d0033",
|
|
14
8
|
"linkReferences": {},
|
|
15
9
|
"deployedLinkReferences": {}
|
|
16
10
|
}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
"contractName": "ConfidentialFungibleTokenUtils",
|
|
4
4
|
"sourceName": "contracts/token/utils/ConfidentialFungibleTokenUtils.sol",
|
|
5
5
|
"abi": [],
|
|
6
|
-
"bytecode": "
|
|
7
|
-
"deployedBytecode": "
|
|
6
|
+
"bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b16578e84785381452ea9c7ec4dfc058f69cc926edb04fddadfe0ed26ee6f7d264736f6c634300081d0033",
|
|
7
|
+
"deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220b16578e84785381452ea9c7ec4dfc058f69cc926edb04fddadfe0ed26ee6f7d264736f6c634300081d0033",
|
|
8
8
|
"linkReferences": {},
|
|
9
9
|
"deployedLinkReferences": {}
|
|
10
10
|
}
|
|
@@ -832,6 +832,29 @@
|
|
|
832
832
|
"stateMutability": "nonpayable",
|
|
833
833
|
"type": "function"
|
|
834
834
|
},
|
|
835
|
+
{
|
|
836
|
+
"inputs": [
|
|
837
|
+
{
|
|
838
|
+
"internalType": "bytes32",
|
|
839
|
+
"name": "handle",
|
|
840
|
+
"type": "bytes32"
|
|
841
|
+
},
|
|
842
|
+
{
|
|
843
|
+
"internalType": "address",
|
|
844
|
+
"name": "account",
|
|
845
|
+
"type": "address"
|
|
846
|
+
},
|
|
847
|
+
{
|
|
848
|
+
"internalType": "bool",
|
|
849
|
+
"name": "persistent",
|
|
850
|
+
"type": "bool"
|
|
851
|
+
}
|
|
852
|
+
],
|
|
853
|
+
"name": "getHandleAllowance",
|
|
854
|
+
"outputs": [],
|
|
855
|
+
"stateMutability": "nonpayable",
|
|
856
|
+
"type": "function"
|
|
857
|
+
},
|
|
835
858
|
{
|
|
836
859
|
"inputs": [
|
|
837
860
|
{
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_format": "hh-sol-artifact-1",
|
|
3
|
-
"contractName": "
|
|
4
|
-
"sourceName": "contracts/utils/
|
|
3
|
+
"contractName": "FHESafeMath",
|
|
4
|
+
"sourceName": "contracts/utils/FHESafeMath.sol",
|
|
5
5
|
"abi": [],
|
|
6
|
-
"bytecode": "
|
|
7
|
-
"deployedBytecode": "
|
|
6
|
+
"bytecode": "0x60556032600b8282823980515f1a607314602657634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220169c9cbdfb2791e1d96b54361ac4446969846b7a58a8da1f7dba5af4fa757c7564736f6c634300081d0033",
|
|
7
|
+
"deployedBytecode": "0x730000000000000000000000000000000000000000301460806040525f5ffdfea2646970667358221220169c9cbdfb2791e1d96b54361ac4446969846b7a58a8da1f7dba5af4fa757c7564736f6c634300081d0033",
|
|
8
8
|
"linkReferences": {},
|
|
9
9
|
"deployedLinkReferences": {}
|
|
10
10
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_format": "hh-sol-artifact-1",
|
|
3
|
+
"contractName": "HandleAccessManager",
|
|
4
|
+
"sourceName": "contracts/utils/HandleAccessManager.sol",
|
|
5
|
+
"abi": [
|
|
6
|
+
{
|
|
7
|
+
"inputs": [
|
|
8
|
+
{
|
|
9
|
+
"internalType": "bytes32",
|
|
10
|
+
"name": "handle",
|
|
11
|
+
"type": "bytes32"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"internalType": "address",
|
|
15
|
+
"name": "account",
|
|
16
|
+
"type": "address"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"internalType": "bool",
|
|
20
|
+
"name": "persistent",
|
|
21
|
+
"type": "bool"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"name": "getHandleAllowance",
|
|
25
|
+
"outputs": [],
|
|
26
|
+
"stateMutability": "nonpayable",
|
|
27
|
+
"type": "function"
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
"bytecode": "0x",
|
|
31
|
+
"deployedBytecode": "0x",
|
|
32
|
+
"linkReferences": {},
|
|
33
|
+
"deployedLinkReferences": {}
|
|
34
|
+
}
|
|
@@ -202,7 +202,7 @@
|
|
|
202
202
|
"name": "released",
|
|
203
203
|
"outputs": [
|
|
204
204
|
{
|
|
205
|
-
"internalType": "
|
|
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": "
|
|
254
|
+
"internalType": "uint48",
|
|
255
255
|
"name": "timestamp",
|
|
256
|
-
"type": "
|
|
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": "
|
|
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": "
|
|
225
|
+
"internalType": "uint48",
|
|
226
226
|
"name": "timestamp",
|
|
227
|
-
"type": "
|
|
227
|
+
"type": "uint48"
|
|
228
228
|
}
|
|
229
229
|
],
|
|
230
230
|
"name": "vestedAmount",
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_format": "hh-sol-artifact-1",
|
|
3
|
+
"contractName": "VestingWalletConfidentialFactory",
|
|
4
|
+
"sourceName": "contracts/finance/VestingWalletConfidentialFactory.sol",
|
|
5
|
+
"abi": [
|
|
6
|
+
{
|
|
7
|
+
"inputs": [],
|
|
8
|
+
"name": "FailedDeployment",
|
|
9
|
+
"type": "error"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"inputs": [
|
|
13
|
+
{
|
|
14
|
+
"internalType": "uint256",
|
|
15
|
+
"name": "balance",
|
|
16
|
+
"type": "uint256"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"internalType": "uint256",
|
|
20
|
+
"name": "needed",
|
|
21
|
+
"type": "uint256"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"name": "InsufficientBalance",
|
|
25
|
+
"type": "error"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"anonymous": false,
|
|
29
|
+
"inputs": [
|
|
30
|
+
{
|
|
31
|
+
"indexed": true,
|
|
32
|
+
"internalType": "address",
|
|
33
|
+
"name": "vestingWalletConfidential",
|
|
34
|
+
"type": "address"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"indexed": false,
|
|
38
|
+
"internalType": "bytes",
|
|
39
|
+
"name": "initArgs",
|
|
40
|
+
"type": "bytes"
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"name": "VestingWalletConfidentialCreated",
|
|
44
|
+
"type": "event"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"anonymous": false,
|
|
48
|
+
"inputs": [
|
|
49
|
+
{
|
|
50
|
+
"indexed": true,
|
|
51
|
+
"internalType": "address",
|
|
52
|
+
"name": "vestingWalletConfidential",
|
|
53
|
+
"type": "address"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"indexed": true,
|
|
57
|
+
"internalType": "address",
|
|
58
|
+
"name": "confidentialFungibleToken",
|
|
59
|
+
"type": "address"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"indexed": false,
|
|
63
|
+
"internalType": "euint64",
|
|
64
|
+
"name": "transferredAmount",
|
|
65
|
+
"type": "bytes32"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"indexed": false,
|
|
69
|
+
"internalType": "bytes",
|
|
70
|
+
"name": "initArgs",
|
|
71
|
+
"type": "bytes"
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
"name": "VestingWalletConfidentialFunded",
|
|
75
|
+
"type": "event"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"inputs": [
|
|
79
|
+
{
|
|
80
|
+
"internalType": "address",
|
|
81
|
+
"name": "confidentialFungibleToken",
|
|
82
|
+
"type": "address"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"components": [
|
|
86
|
+
{
|
|
87
|
+
"internalType": "externalEuint64",
|
|
88
|
+
"name": "encryptedAmount",
|
|
89
|
+
"type": "bytes32"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"internalType": "bytes",
|
|
93
|
+
"name": "initArgs",
|
|
94
|
+
"type": "bytes"
|
|
95
|
+
}
|
|
96
|
+
],
|
|
97
|
+
"internalType": "struct VestingWalletConfidentialFactory.VestingPlan[]",
|
|
98
|
+
"name": "vestingPlans",
|
|
99
|
+
"type": "tuple[]"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"internalType": "bytes",
|
|
103
|
+
"name": "inputProof",
|
|
104
|
+
"type": "bytes"
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
"name": "batchFundVestingWalletConfidential",
|
|
108
|
+
"outputs": [],
|
|
109
|
+
"stateMutability": "nonpayable",
|
|
110
|
+
"type": "function"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"inputs": [
|
|
114
|
+
{
|
|
115
|
+
"internalType": "bytes",
|
|
116
|
+
"name": "initArgs",
|
|
117
|
+
"type": "bytes"
|
|
118
|
+
}
|
|
119
|
+
],
|
|
120
|
+
"name": "createVestingWalletConfidential",
|
|
121
|
+
"outputs": [
|
|
122
|
+
{
|
|
123
|
+
"internalType": "address",
|
|
124
|
+
"name": "",
|
|
125
|
+
"type": "address"
|
|
126
|
+
}
|
|
127
|
+
],
|
|
128
|
+
"stateMutability": "nonpayable",
|
|
129
|
+
"type": "function"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"inputs": [
|
|
133
|
+
{
|
|
134
|
+
"internalType": "bytes",
|
|
135
|
+
"name": "initArgs",
|
|
136
|
+
"type": "bytes"
|
|
137
|
+
}
|
|
138
|
+
],
|
|
139
|
+
"name": "predictVestingWalletConfidential",
|
|
140
|
+
"outputs": [
|
|
141
|
+
{
|
|
142
|
+
"internalType": "address",
|
|
143
|
+
"name": "",
|
|
144
|
+
"type": "address"
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
"stateMutability": "view",
|
|
148
|
+
"type": "function"
|
|
149
|
+
}
|
|
150
|
+
],
|
|
151
|
+
"bytecode": "0x",
|
|
152
|
+
"deployedBytecode": "0x",
|
|
153
|
+
"linkReferences": {},
|
|
154
|
+
"deployedLinkReferences": {}
|
|
155
|
+
}
|
|
@@ -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
|
|
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
|
|
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(
|
|
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,
|
|
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,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Confidential Contracts (last updated v0.2.0
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.2.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";
|
|
@@ -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 =>
|
|
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,7 +57,7 @@ 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 (
|
|
60
|
+
function released(address token) public view virtual returns (euint128) {
|
|
58
61
|
return _getVestingWalletStorage()._tokenReleased[token];
|
|
59
62
|
}
|
|
60
63
|
|
|
@@ -63,7 +66,10 @@ abstract contract VestingWalletConfidential is OwnableUpgradeable, ReentrancyGua
|
|
|
63
66
|
* {IConfidentialFungibleToken} contract.
|
|
64
67
|
*/
|
|
65
68
|
function releasable(address token) public virtual returns (euint64) {
|
|
66
|
-
|
|
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
|
/**
|
|
@@ -76,21 +82,22 @@ abstract contract VestingWalletConfidential is OwnableUpgradeable, ReentrancyGua
|
|
|
76
82
|
FHE.allowTransient(amount, token);
|
|
77
83
|
euint64 amountSent = IConfidentialFungibleToken(token).confidentialTransfer(owner(), amount);
|
|
78
84
|
|
|
79
|
-
|
|
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
|
-
|
|
87
|
-
|
|
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
99
|
_vestingSchedule(
|
|
90
|
-
FHE.add(
|
|
91
|
-
FHE.asEuint128(IConfidentialFungibleToken(token).confidentialBalanceOf(address(this))),
|
|
92
|
-
released(token)
|
|
93
|
-
),
|
|
100
|
+
FHE.add(released(token), IConfidentialFungibleToken(token).confidentialBalanceOf(address(this))),
|
|
94
101
|
timestamp
|
|
95
102
|
);
|
|
96
103
|
}
|
|
@@ -106,13 +113,21 @@ abstract contract VestingWalletConfidential is OwnableUpgradeable, ReentrancyGua
|
|
|
106
113
|
uint48 durationSeconds
|
|
107
114
|
) internal onlyInitializing {
|
|
108
115
|
__Ownable_init(beneficiary);
|
|
116
|
+
__VestingWalletConfidential_init_unchained(startTimestamp, durationSeconds);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// solhint-disable-next-line func-name-mixedcase
|
|
120
|
+
function __VestingWalletConfidential_init_unchained(
|
|
121
|
+
uint48 startTimestamp,
|
|
122
|
+
uint48 durationSeconds
|
|
123
|
+
) internal onlyInitializing {
|
|
109
124
|
VestingWalletStorage storage $ = _getVestingWalletStorage();
|
|
110
125
|
$._start = startTimestamp;
|
|
111
126
|
$._duration = durationSeconds;
|
|
112
127
|
}
|
|
113
128
|
|
|
114
129
|
/// @dev This returns the amount vested, as a function of time, for an asset given its total historical allocation.
|
|
115
|
-
function _vestingSchedule(euint128 totalAllocation,
|
|
130
|
+
function _vestingSchedule(euint128 totalAllocation, uint48 timestamp) internal virtual returns (euint128) {
|
|
116
131
|
if (timestamp < start()) {
|
|
117
132
|
return euint128.wrap(0);
|
|
118
133
|
} else if (timestamp >= end()) {
|
|
@@ -123,7 +138,7 @@ abstract contract VestingWalletConfidential is OwnableUpgradeable, ReentrancyGua
|
|
|
123
138
|
}
|
|
124
139
|
|
|
125
140
|
function _getVestingWalletStorage() private pure returns (VestingWalletStorage storage $) {
|
|
126
|
-
assembly {
|
|
141
|
+
assembly ("memory-safe") {
|
|
127
142
|
$.slot := VestingWalletStorageLocation
|
|
128
143
|
}
|
|
129
144
|
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// OpenZeppelin Confidential Contracts (last updated v0.2.0) (finance/VestingWalletConfidentialFactory.sol)
|
|
3
|
+
pragma solidity ^0.8.27;
|
|
4
|
+
|
|
5
|
+
import {FHE, euint64, externalEuint64} from "@fhevm/solidity/lib/FHE.sol";
|
|
6
|
+
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
|
|
7
|
+
import {IConfidentialFungibleToken} from "./../interfaces/IConfidentialFungibleToken.sol";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @dev A factory which enables batch funding of vesting wallets.
|
|
11
|
+
*
|
|
12
|
+
* The {_deployVestingWalletImplementation}, {_initializeVestingWallet}, and {_validateVestingWalletInitArgs}
|
|
13
|
+
* functions remain unimplemented to allow for custom implementations of the vesting wallet to be used.
|
|
14
|
+
*/
|
|
15
|
+
abstract contract VestingWalletConfidentialFactory {
|
|
16
|
+
struct VestingPlan {
|
|
17
|
+
externalEuint64 encryptedAmount;
|
|
18
|
+
bytes initArgs;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
address private immutable _vestingImplementation;
|
|
22
|
+
|
|
23
|
+
/// @dev Emitted for each vesting wallet funded within a batch.
|
|
24
|
+
event VestingWalletConfidentialFunded(
|
|
25
|
+
address indexed vestingWalletConfidential,
|
|
26
|
+
address indexed confidentialFungibleToken,
|
|
27
|
+
euint64 transferredAmount,
|
|
28
|
+
bytes initArgs
|
|
29
|
+
);
|
|
30
|
+
/// @dev Emitted when a vesting wallet is deployed.
|
|
31
|
+
event VestingWalletConfidentialCreated(address indexed vestingWalletConfidential, bytes initArgs);
|
|
32
|
+
|
|
33
|
+
constructor() {
|
|
34
|
+
_vestingImplementation = _deployVestingWalletImplementation();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @dev Batches the funding of multiple confidential vesting wallets.
|
|
39
|
+
*
|
|
40
|
+
* Funds are sent to deterministic wallet addresses. Wallets can be created either
|
|
41
|
+
* before or after this operation.
|
|
42
|
+
*
|
|
43
|
+
* Emits a {VestingWalletConfidentialFunded} event for each funded vesting plan.
|
|
44
|
+
*/
|
|
45
|
+
function batchFundVestingWalletConfidential(
|
|
46
|
+
address confidentialFungibleToken,
|
|
47
|
+
VestingPlan[] calldata vestingPlans,
|
|
48
|
+
bytes calldata inputProof
|
|
49
|
+
) public virtual {
|
|
50
|
+
uint256 vestingPlansLength = vestingPlans.length;
|
|
51
|
+
for (uint256 i = 0; i < vestingPlansLength; i++) {
|
|
52
|
+
VestingPlan memory vestingPlan = vestingPlans[i];
|
|
53
|
+
_validateVestingWalletInitArgs(vestingPlan.initArgs);
|
|
54
|
+
|
|
55
|
+
address vestingWalletAddress = predictVestingWalletConfidential(vestingPlan.initArgs);
|
|
56
|
+
|
|
57
|
+
euint64 encryptedAmount = FHE.fromExternal(vestingPlan.encryptedAmount, inputProof);
|
|
58
|
+
FHE.allowTransient(encryptedAmount, confidentialFungibleToken);
|
|
59
|
+
euint64 transferredAmount = IConfidentialFungibleToken(confidentialFungibleToken).confidentialTransferFrom(
|
|
60
|
+
msg.sender,
|
|
61
|
+
vestingWalletAddress,
|
|
62
|
+
encryptedAmount
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
emit VestingWalletConfidentialFunded(
|
|
66
|
+
vestingWalletAddress,
|
|
67
|
+
confidentialFungibleToken,
|
|
68
|
+
transferredAmount,
|
|
69
|
+
vestingPlan.initArgs
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @dev Creates a confidential vesting wallet.
|
|
76
|
+
*
|
|
77
|
+
* Emits a {VestingWalletConfidentialCreated}.
|
|
78
|
+
*/
|
|
79
|
+
function createVestingWalletConfidential(bytes calldata initArgs) public virtual returns (address) {
|
|
80
|
+
// Will revert if clone already created
|
|
81
|
+
address vestingWalletConfidentialAddress = Clones.cloneDeterministic(
|
|
82
|
+
_vestingImplementation,
|
|
83
|
+
_getCreate2VestingWalletConfidentialSalt(initArgs)
|
|
84
|
+
);
|
|
85
|
+
_initializeVestingWallet(vestingWalletConfidentialAddress, initArgs);
|
|
86
|
+
emit VestingWalletConfidentialCreated(vestingWalletConfidentialAddress, initArgs);
|
|
87
|
+
return vestingWalletConfidentialAddress;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @dev Predicts the deterministic address for a confidential vesting wallet.
|
|
92
|
+
*/
|
|
93
|
+
function predictVestingWalletConfidential(bytes memory initArgs) public view virtual returns (address) {
|
|
94
|
+
return
|
|
95
|
+
Clones.predictDeterministicAddress(
|
|
96
|
+
_vestingImplementation,
|
|
97
|
+
_getCreate2VestingWalletConfidentialSalt(initArgs)
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/// @dev Virtual function that must be implemented to validate the initArgs bytes.
|
|
102
|
+
function _validateVestingWalletInitArgs(bytes memory initArgs) internal virtual;
|
|
103
|
+
|
|
104
|
+
/// @dev Virtual function that must be implemented to initialize the vesting wallet at `vestingWalletAddress`.
|
|
105
|
+
function _initializeVestingWallet(address vestingWalletAddress, bytes calldata initArgs) internal virtual;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @dev Internal function that is called once to deploy the vesting wallet implementation.
|
|
109
|
+
*
|
|
110
|
+
* Vesting wallet clones will be initialized by calls to the {_initializeVestingWallet} function.
|
|
111
|
+
*/
|
|
112
|
+
function _deployVestingWalletImplementation() internal virtual returns (address);
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @dev Gets create2 salt for a confidential vesting wallet.
|
|
116
|
+
*/
|
|
117
|
+
function _getCreate2VestingWalletConfidentialSalt(bytes memory initArgs) internal pure virtual returns (bytes32) {
|
|
118
|
+
return keccak256(initArgs);
|
|
119
|
+
}
|
|
120
|
+
}
|