create-fhevm-example 1.4.3 → 1.4.4
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/contracts/advanced/BlindAuction.sol +18 -57
- package/contracts/advanced/EncryptedEscrow.sol +2 -30
- package/contracts/advanced/HiddenVoting.sol +15 -54
- package/contracts/advanced/PrivateKYC.sol +3 -32
- package/contracts/advanced/PrivatePayroll.sol +4 -34
- package/contracts/basic/decryption/PublicDecryptMultipleValues.sol +9 -17
- package/contracts/basic/decryption/PublicDecryptSingleValue.sol +9 -16
- package/contracts/basic/decryption/UserDecryptMultipleValues.sol +7 -21
- package/contracts/basic/decryption/UserDecryptSingleValue.sol +11 -30
- package/contracts/basic/encryption/EncryptMultipleValues.sol +12 -21
- package/contracts/basic/encryption/EncryptSingleValue.sol +11 -17
- package/contracts/basic/encryption/FHECounter.sol +15 -16
- package/contracts/basic/fhe-operations/FHEAdd.sol +10 -16
- package/contracts/basic/fhe-operations/FHEArithmetic.sol +15 -31
- package/contracts/basic/fhe-operations/FHEComparison.sol +8 -29
- package/contracts/basic/fhe-operations/FHEIfThenElse.sol +4 -9
- package/contracts/concepts/FHEAccessControl.sol +23 -28
- package/contracts/concepts/FHEAntiPatterns.sol +4 -37
- package/contracts/concepts/FHEHandles.sol +10 -29
- package/contracts/concepts/FHEInputProof.sol +9 -33
- package/contracts/gaming/EncryptedLottery.sol +6 -37
- package/contracts/gaming/EncryptedPoker.sol +3 -33
- package/contracts/gaming/RockPaperScissors.sol +39 -64
- package/contracts/openzeppelin/VestingWallet.sol +8 -17
- package/package.json +1 -1
|
@@ -13,23 +13,11 @@ import {ZamaEthereumConfig} from "@fhevm/solidity/config/ZamaConfig.sol";
|
|
|
13
13
|
/**
|
|
14
14
|
* @notice Encrypted Lottery with private ticket numbers - fair and verifiable!
|
|
15
15
|
*
|
|
16
|
-
* @dev
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* - Winners identified via FHE.eq without revealing ticket numbers
|
|
20
|
-
* - Only winner's ticket revealed at end
|
|
21
|
-
*
|
|
22
|
-
* Flow:
|
|
23
|
-
* 1. Lottery created with ticket price and duration
|
|
24
|
-
* 2. Players buy tickets with encrypted numbers
|
|
25
|
-
* 3. Owner draws winning number at end
|
|
26
|
-
* 4. Winners can claim prizes
|
|
27
|
-
*
|
|
28
|
-
* ⚠️ IMPORTANT: Block randomness is predictable - use VRF in production!
|
|
16
|
+
* @dev Flow: buyTicket() → startDrawing() → checkAndClaim() → revealWinner()
|
|
17
|
+
* ⚡ Gas: Loop in checkAndClaim can be expensive with many tickets!
|
|
18
|
+
* ⚠️ Block randomness is predictable - use VRF in production!
|
|
29
19
|
*/
|
|
30
20
|
contract EncryptedLottery is ZamaEthereumConfig {
|
|
31
|
-
// ==================== TYPES ====================
|
|
32
|
-
|
|
33
21
|
enum LotteryState {
|
|
34
22
|
Open, // Accepting tickets
|
|
35
23
|
Drawing, // Drawing in progress
|
|
@@ -41,9 +29,6 @@ contract EncryptedLottery is ZamaEthereumConfig {
|
|
|
41
29
|
euint64 number;
|
|
42
30
|
}
|
|
43
31
|
|
|
44
|
-
// ==================== STATE ====================
|
|
45
|
-
|
|
46
|
-
/// Lottery owner
|
|
47
32
|
address public owner;
|
|
48
33
|
|
|
49
34
|
/// Current lottery state
|
|
@@ -73,9 +58,7 @@ contract EncryptedLottery is ZamaEthereumConfig {
|
|
|
73
58
|
/// Lottery round number
|
|
74
59
|
uint256 public roundNumber;
|
|
75
60
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
/// @notice Emitted when a ticket is purchased
|
|
61
|
+
/// Emitted when a ticket is purchased
|
|
79
62
|
/// @param buyer Address of ticket buyer
|
|
80
63
|
/// @param ticketIndex Index of the ticket
|
|
81
64
|
event TicketPurchased(address indexed buyer, uint256 indexed ticketIndex);
|
|
@@ -94,18 +77,11 @@ contract EncryptedLottery is ZamaEthereumConfig {
|
|
|
94
77
|
/// @param rollover Amount rolled to next round
|
|
95
78
|
event NoWinner(uint256 indexed roundNumber, uint256 rollover);
|
|
96
79
|
|
|
97
|
-
// ==================== MODIFIERS ====================
|
|
98
|
-
|
|
99
80
|
modifier onlyOwner() {
|
|
100
81
|
require(msg.sender == owner, "Only owner");
|
|
101
82
|
_;
|
|
102
83
|
}
|
|
103
84
|
|
|
104
|
-
// ==================== CONSTRUCTOR ====================
|
|
105
|
-
|
|
106
|
-
/// @notice Creates a new encrypted lottery
|
|
107
|
-
/// @param _ticketPrice Price per ticket in wei
|
|
108
|
-
/// @param _duration Duration in seconds
|
|
109
85
|
constructor(uint256 _ticketPrice, uint256 _duration) {
|
|
110
86
|
require(_ticketPrice > 0, "Ticket price must be > 0");
|
|
111
87
|
require(_duration > 0, "Duration must be > 0");
|
|
@@ -117,9 +93,7 @@ contract EncryptedLottery is ZamaEthereumConfig {
|
|
|
117
93
|
roundNumber = 1;
|
|
118
94
|
}
|
|
119
95
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
/// @notice Purchase a lottery ticket with an encrypted number
|
|
96
|
+
/// @notice Purchase a lottery ticket with encrypted number
|
|
123
97
|
/// @param encryptedNumber Your encrypted ticket number
|
|
124
98
|
/// @param inputProof Proof validating the encrypted input
|
|
125
99
|
function buyTicket(
|
|
@@ -130,7 +104,7 @@ contract EncryptedLottery is ZamaEthereumConfig {
|
|
|
130
104
|
require(block.timestamp < endTime, "Lottery ended");
|
|
131
105
|
require(msg.value >= ticketPrice, "Insufficient payment");
|
|
132
106
|
|
|
133
|
-
//
|
|
107
|
+
// Convert and store encrypted ticket number
|
|
134
108
|
euint64 ticketNumber = FHE.fromExternal(encryptedNumber, inputProof);
|
|
135
109
|
|
|
136
110
|
// ✅ Grant contract permission
|
|
@@ -146,8 +120,6 @@ contract EncryptedLottery is ZamaEthereumConfig {
|
|
|
146
120
|
emit TicketPurchased(msg.sender, ticketIndex);
|
|
147
121
|
}
|
|
148
122
|
|
|
149
|
-
// ==================== DRAWING ====================
|
|
150
|
-
|
|
151
123
|
/// @notice Start the drawing process
|
|
152
124
|
/// @dev Only owner can call after lottery ends
|
|
153
125
|
function startDrawing() external onlyOwner {
|
|
@@ -261,9 +233,6 @@ contract EncryptedLottery is ZamaEthereumConfig {
|
|
|
261
233
|
// prizePool carries over if no winner
|
|
262
234
|
}
|
|
263
235
|
|
|
264
|
-
// ==================== VIEW FUNCTIONS ====================
|
|
265
|
-
|
|
266
|
-
/// @notice Get total number of tickets sold
|
|
267
236
|
function getTicketCount() external view returns (uint256) {
|
|
268
237
|
return _tickets.length;
|
|
269
238
|
}
|
|
@@ -13,23 +13,11 @@ import {ZamaEthereumConfig} from "@fhevm/solidity/config/ZamaConfig.sol";
|
|
|
13
13
|
/**
|
|
14
14
|
* @notice Encrypted Poker - Texas Hold'em with hidden hole cards!
|
|
15
15
|
*
|
|
16
|
-
* @dev
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* - Winner determined by encrypted comparison
|
|
20
|
-
* - Only winning hand revealed, loser's cards stay private
|
|
21
|
-
*
|
|
22
|
-
* Simplified rules for demo:
|
|
23
|
-
* - 2 players (heads-up)
|
|
24
|
-
* - Cards encoded as 1-13 (Ace=1, King=13)
|
|
25
|
-
* - Hand strength = card1 + card2 (simplified for demo)
|
|
26
|
-
* - Higher total wins
|
|
27
|
-
*
|
|
28
|
-
* ⚠️ IMPORTANT: Production poker would need proper hand rankings!
|
|
16
|
+
* @dev Flow: joinGame() → bet()/fold() → showdown() → revealWinner()
|
|
17
|
+
* Hand strength = card1 + card2 (simplified for demo)
|
|
18
|
+
* ⚠️ Production needs proper hand rankings (flush, straight, etc.)
|
|
29
19
|
*/
|
|
30
20
|
contract EncryptedPoker is ZamaEthereumConfig {
|
|
31
|
-
// ==================== TYPES ====================
|
|
32
|
-
|
|
33
21
|
enum GameState {
|
|
34
22
|
WaitingForPlayers, // Waiting for 2 players
|
|
35
23
|
CardsDealt, // Both players have cards
|
|
@@ -47,8 +35,6 @@ contract EncryptedPoker is ZamaEthereumConfig {
|
|
|
47
35
|
bool folded;
|
|
48
36
|
}
|
|
49
37
|
|
|
50
|
-
// ==================== STATE ====================
|
|
51
|
-
|
|
52
38
|
/// Game state
|
|
53
39
|
GameState public state;
|
|
54
40
|
|
|
@@ -70,8 +56,6 @@ contract EncryptedPoker is ZamaEthereumConfig {
|
|
|
70
56
|
/// Encrypted comparison result (true if player 0 wins)
|
|
71
57
|
ebool private _player0Wins;
|
|
72
58
|
|
|
73
|
-
// ==================== EVENTS ====================
|
|
74
|
-
|
|
75
59
|
/// @notice Emitted when a player joins
|
|
76
60
|
/// @param player Address of joining player
|
|
77
61
|
/// @param seat Seat number (0 or 1)
|
|
@@ -97,8 +81,6 @@ contract EncryptedPoker is ZamaEthereumConfig {
|
|
|
97
81
|
/// @param pot Total pot won
|
|
98
82
|
event GameWon(address indexed winner, uint256 pot);
|
|
99
83
|
|
|
100
|
-
// ==================== CONSTRUCTOR ====================
|
|
101
|
-
|
|
102
84
|
/// @notice Creates a new poker game
|
|
103
85
|
/// @param _minBet Minimum bet amount in wei
|
|
104
86
|
constructor(uint256 _minBet) {
|
|
@@ -108,8 +90,6 @@ contract EncryptedPoker is ZamaEthereumConfig {
|
|
|
108
90
|
state = GameState.WaitingForPlayers;
|
|
109
91
|
}
|
|
110
92
|
|
|
111
|
-
// ==================== JOIN GAME ====================
|
|
112
|
-
|
|
113
93
|
/// @notice Join the game with encrypted hole cards
|
|
114
94
|
/// @param encCard1 First encrypted card (1-13)
|
|
115
95
|
/// @param encCard2 Second encrypted card (1-13)
|
|
@@ -173,8 +153,6 @@ contract EncryptedPoker is ZamaEthereumConfig {
|
|
|
173
153
|
emit PlayerJoined(msg.sender, seat);
|
|
174
154
|
}
|
|
175
155
|
|
|
176
|
-
// ==================== BETTING ====================
|
|
177
|
-
|
|
178
156
|
/// @notice Place a bet
|
|
179
157
|
function bet() external payable {
|
|
180
158
|
require(
|
|
@@ -220,8 +198,6 @@ contract EncryptedPoker is ZamaEthereumConfig {
|
|
|
220
198
|
emit GameWon(winner, winnings);
|
|
221
199
|
}
|
|
222
200
|
|
|
223
|
-
// ==================== SHOWDOWN ====================
|
|
224
|
-
|
|
225
201
|
/// @notice Initiate showdown - compare hands using FHE
|
|
226
202
|
function showdown() external {
|
|
227
203
|
require(
|
|
@@ -276,8 +252,6 @@ contract EncryptedPoker is ZamaEthereumConfig {
|
|
|
276
252
|
emit GameWon(winner, winnings);
|
|
277
253
|
}
|
|
278
254
|
|
|
279
|
-
// ==================== RESET ====================
|
|
280
|
-
|
|
281
255
|
/// @notice Reset for a new game
|
|
282
256
|
function resetGame() external {
|
|
283
257
|
require(state == GameState.Finished, "Game not finished");
|
|
@@ -290,8 +264,6 @@ contract EncryptedPoker is ZamaEthereumConfig {
|
|
|
290
264
|
gameId++;
|
|
291
265
|
}
|
|
292
266
|
|
|
293
|
-
// ==================== VIEW FUNCTIONS ====================
|
|
294
|
-
|
|
295
267
|
/// @notice Get game info
|
|
296
268
|
function getGameInfo()
|
|
297
269
|
external
|
|
@@ -327,8 +299,6 @@ contract EncryptedPoker is ZamaEthereumConfig {
|
|
|
327
299
|
return (_players[seat].card1, _players[seat].card2);
|
|
328
300
|
}
|
|
329
301
|
|
|
330
|
-
// ==================== INTERNAL ====================
|
|
331
|
-
|
|
332
302
|
function _getSeat(address player) internal view returns (uint8) {
|
|
333
303
|
if (_players[0].addr == player) return 0;
|
|
334
304
|
if (_players[1].addr == player) return 1;
|
|
@@ -1,39 +1,23 @@
|
|
|
1
1
|
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
|
2
2
|
pragma solidity ^0.8.24;
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
FHE,
|
|
6
|
-
euint8,
|
|
7
|
-
ebool,
|
|
8
|
-
externalEuint8
|
|
9
|
-
} from "@fhevm/solidity/lib/FHE.sol";
|
|
4
|
+
import {FHE, euint8, ebool, externalEuint8} from "@fhevm/solidity/lib/FHE.sol";
|
|
10
5
|
import {ZamaEthereumConfig} from "@fhevm/solidity/config/ZamaConfig.sol";
|
|
11
6
|
|
|
12
7
|
/**
|
|
13
|
-
* @notice Rock-Paper-Scissors game with encrypted moves - fair play guaranteed!
|
|
14
|
-
|
|
15
|
-
* @dev
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* - Loser's move revealed only after game concludes
|
|
19
|
-
*
|
|
20
|
-
* Move encoding: 0 = Rock, 1 = Paper, 2 = Scissors
|
|
21
|
-
* Win logic: (move1 - move2 + 3) % 3 → 1 = player1 wins, 2 = player2 wins
|
|
22
|
-
*
|
|
23
|
-
* ⚠️ IMPORTANT: Uses FHE.rem for modulo - computationally expensive but secure
|
|
8
|
+
* @notice Rock-Paper-Scissors game with encrypted moves - fair play guaranteed using FHE!
|
|
9
|
+
|
|
10
|
+
* @dev Commit-reveal pattern without trusted third party.
|
|
11
|
+
* Move encoding: 0=Rock, 1=Paper, 2=Scissors
|
|
12
|
+
* ⚡ Gas: FHE.rem() is computationally expensive (~300k gas)
|
|
24
13
|
*/
|
|
25
14
|
contract RockPaperScissors is ZamaEthereumConfig {
|
|
26
|
-
// ==================== TYPES ====================
|
|
27
|
-
|
|
28
15
|
enum GameState {
|
|
29
16
|
WaitingForPlayers, // 0 or 1 player joined
|
|
30
|
-
BothMoved,
|
|
31
|
-
Revealed
|
|
17
|
+
BothMoved, // Both players submitted moves
|
|
18
|
+
Revealed // Winner determined and revealed
|
|
32
19
|
}
|
|
33
20
|
|
|
34
|
-
// ==================== STATE ====================
|
|
35
|
-
|
|
36
|
-
/// Player 1 address
|
|
37
21
|
address public player1;
|
|
38
22
|
|
|
39
23
|
/// Player 2 address
|
|
@@ -52,9 +36,7 @@ contract RockPaperScissors is ZamaEthereumConfig {
|
|
|
52
36
|
/// Game ID for tracking multiple games
|
|
53
37
|
uint256 public gameId;
|
|
54
38
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
/// @notice Emitted when a player joins
|
|
39
|
+
/// Emitted when a player joins
|
|
58
40
|
/// @param player Address of joining player
|
|
59
41
|
/// @param playerNumber 1 or 2
|
|
60
42
|
event PlayerJoined(address indexed player, uint8 playerNumber);
|
|
@@ -67,34 +49,29 @@ contract RockPaperScissors is ZamaEthereumConfig {
|
|
|
67
49
|
/// @param gameId Current game ID
|
|
68
50
|
event GameResult(address indexed winner, uint256 indexed gameId);
|
|
69
51
|
|
|
70
|
-
// ==================== CONSTRUCTOR ====================
|
|
71
|
-
|
|
72
|
-
/// @notice Creates a new Rock-Paper-Scissors game
|
|
73
52
|
constructor() {
|
|
74
53
|
gameId = 1;
|
|
75
54
|
state = GameState.WaitingForPlayers;
|
|
76
55
|
}
|
|
77
56
|
|
|
78
|
-
// ==================== PLAY FUNCTIONS ====================
|
|
79
|
-
|
|
80
57
|
/// @notice Submit an encrypted move to play
|
|
81
58
|
/// @dev Move must be 0 (Rock), 1 (Paper), or 2 (Scissors)
|
|
82
|
-
/// @param encryptedMove Encrypted move value (0-2)
|
|
83
59
|
/// @param inputProof Proof validating the encrypted input
|
|
84
60
|
function play(
|
|
85
61
|
externalEuint8 encryptedMove,
|
|
86
62
|
bytes calldata inputProof
|
|
87
63
|
) external {
|
|
88
|
-
require(
|
|
64
|
+
require(
|
|
65
|
+
state == GameState.WaitingForPlayers,
|
|
66
|
+
"Game not accepting moves"
|
|
67
|
+
);
|
|
89
68
|
require(
|
|
90
69
|
msg.sender != player1 && msg.sender != player2,
|
|
91
70
|
"Already in this game"
|
|
92
71
|
);
|
|
93
72
|
|
|
94
|
-
//
|
|
73
|
+
// Convert and validate encrypted move
|
|
95
74
|
euint8 move = FHE.fromExternal(encryptedMove, inputProof);
|
|
96
|
-
|
|
97
|
-
// ✅ Grant contract permission to operate on this value
|
|
98
75
|
FHE.allowThis(move);
|
|
99
76
|
|
|
100
77
|
if (player1 == address(0)) {
|
|
@@ -117,31 +94,25 @@ contract RockPaperScissors is ZamaEthereumConfig {
|
|
|
117
94
|
function determineWinner() external {
|
|
118
95
|
require(state == GameState.BothMoved, "Not ready to determine winner");
|
|
119
96
|
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
euint8 diff = FHE.add(FHE.add(_move1, FHE.asEuint8(3)), FHE.neg(_move2));
|
|
97
|
+
// Winner calculation: (move1 - move2 + 3) % 3
|
|
98
|
+
// 0=tie, 1=player1 wins, 2=player2 wins
|
|
99
|
+
euint8 diff = FHE.add(
|
|
100
|
+
FHE.add(_move1, FHE.asEuint8(3)),
|
|
101
|
+
FHE.neg(_move2)
|
|
102
|
+
);
|
|
127
103
|
|
|
128
|
-
//
|
|
104
|
+
// 🎲 Why rem? Modulo keeps result in 0-2 range (tie/p1 wins/p2 wins)
|
|
105
|
+
// ⚡ rem is expensive (~300k gas) - consider alternatives for production
|
|
129
106
|
euint8 result = FHE.rem(diff, 3);
|
|
130
107
|
|
|
131
|
-
//
|
|
108
|
+
// Compare results to determine outcome
|
|
132
109
|
ebool isTie = FHE.eq(result, FHE.asEuint8(0));
|
|
133
110
|
ebool player1Wins = FHE.eq(result, FHE.asEuint8(1));
|
|
134
111
|
|
|
135
|
-
//
|
|
136
|
-
// In production, use public decryption pattern
|
|
137
|
-
|
|
138
|
-
// Make result publicly decryptable
|
|
112
|
+
// 🌐 Why makePubliclyDecryptable? Anyone can decrypt result with KMS proof
|
|
139
113
|
FHE.allowThis(result);
|
|
140
114
|
FHE.makePubliclyDecryptable(result);
|
|
141
115
|
|
|
142
|
-
// Store encrypted result for later reveal
|
|
143
|
-
// For this demo, we'll use select to pick winner
|
|
144
|
-
|
|
145
116
|
state = GameState.Revealed;
|
|
146
117
|
|
|
147
118
|
emit GameResult(address(0), gameId); // Placeholder - real winner after decryption
|
|
@@ -157,7 +128,10 @@ contract RockPaperScissors is ZamaEthereumConfig {
|
|
|
157
128
|
require(state == GameState.Revealed, "Game not ready for reveal");
|
|
158
129
|
|
|
159
130
|
// Build ciphertext list for verification
|
|
160
|
-
euint8 diff = FHE.add(
|
|
131
|
+
euint8 diff = FHE.add(
|
|
132
|
+
FHE.add(_move1, FHE.asEuint8(3)),
|
|
133
|
+
FHE.neg(_move2)
|
|
134
|
+
);
|
|
161
135
|
euint8 result = FHE.rem(diff, 3);
|
|
162
136
|
|
|
163
137
|
bytes32[] memory cts = new bytes32[](1);
|
|
@@ -193,16 +167,17 @@ contract RockPaperScissors is ZamaEthereumConfig {
|
|
|
193
167
|
gameId++;
|
|
194
168
|
}
|
|
195
169
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
170
|
+
function getGameState()
|
|
171
|
+
external
|
|
172
|
+
view
|
|
173
|
+
returns (
|
|
174
|
+
address p1,
|
|
175
|
+
address p2,
|
|
176
|
+
GameState currentState,
|
|
177
|
+
address currentWinner,
|
|
178
|
+
uint256 currentGameId
|
|
179
|
+
)
|
|
180
|
+
{
|
|
206
181
|
return (player1, player2, state, winner, gameId);
|
|
207
182
|
}
|
|
208
183
|
|
|
@@ -12,19 +12,17 @@ import {
|
|
|
12
12
|
} from "@openzeppelin/confidential-contracts/interfaces/IERC7984.sol";
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* @notice Linear vesting wallet for ERC7984 tokens
|
|
16
|
-
|
|
17
|
-
* @dev Timeline: |--START--|---VESTING---|--END--|
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* All vesting calculations are performed on encrypted values using FHE operations.
|
|
15
|
+
* @notice Linear vesting wallet for ERC7984 tokens with fully encrypted amounts and schedules.
|
|
16
|
+
|
|
17
|
+
* @dev Timeline: |--START--|---VESTING---|--END--| (0% → linear → 100%)
|
|
18
|
+
* All vesting calculations performed on encrypted values using FHE.
|
|
19
|
+
* ⚡ Gas: FHE.div/mul operations are expensive (~200k gas each)
|
|
21
20
|
*/
|
|
22
21
|
contract VestingWalletExample is
|
|
23
22
|
Ownable,
|
|
24
23
|
ReentrancyGuardTransient,
|
|
25
24
|
ZamaEthereumConfig
|
|
26
25
|
{
|
|
27
|
-
// 🔐 Track released amounts per token (encrypted)
|
|
28
26
|
mapping(address token => euint128) private _tokenReleased;
|
|
29
27
|
uint64 private _start;
|
|
30
28
|
uint64 private _duration;
|
|
@@ -50,8 +48,6 @@ contract VestingWalletExample is
|
|
|
50
48
|
_duration = durationSeconds;
|
|
51
49
|
}
|
|
52
50
|
|
|
53
|
-
// ==================== VIEW FUNCTIONS ====================
|
|
54
|
-
|
|
55
51
|
function start() public view virtual returns (uint64) {
|
|
56
52
|
return _start;
|
|
57
53
|
}
|
|
@@ -77,9 +73,7 @@ contract VestingWalletExample is
|
|
|
77
73
|
euint128 vestedAmount_ = vestedAmount(token, uint48(block.timestamp));
|
|
78
74
|
euint128 releasedAmount = released(token);
|
|
79
75
|
|
|
80
|
-
//
|
|
81
|
-
// If vested >= released: return (vested - released)
|
|
82
|
-
// Else: return 0
|
|
76
|
+
// Encrypted comparison: if vested >= released → return difference, else 0
|
|
83
77
|
ebool canRelease = FHE.ge(vestedAmount_, releasedAmount);
|
|
84
78
|
return
|
|
85
79
|
FHE.select(
|
|
@@ -89,11 +83,10 @@ contract VestingWalletExample is
|
|
|
89
83
|
);
|
|
90
84
|
}
|
|
91
85
|
|
|
92
|
-
/// @notice Release vested tokens to beneficiary
|
|
93
86
|
function release(address token) public virtual nonReentrant {
|
|
94
87
|
euint64 amount = releasable(token);
|
|
95
88
|
|
|
96
|
-
// Transfer encrypted amount
|
|
89
|
+
// Transfer encrypted amount using allowTransient (cheaper!)
|
|
97
90
|
FHE.allowTransient(amount, token);
|
|
98
91
|
euint64 amountSent = IERC7984(token).confidentialTransfer(
|
|
99
92
|
owner(),
|
|
@@ -122,8 +115,6 @@ contract VestingWalletExample is
|
|
|
122
115
|
return _vestingSchedule(totalAllocation, timestamp);
|
|
123
116
|
}
|
|
124
117
|
|
|
125
|
-
// ==================== INTERNAL ====================
|
|
126
|
-
|
|
127
118
|
/// @dev Linear vesting: (total * elapsed) / duration
|
|
128
119
|
function _vestingSchedule(
|
|
129
120
|
euint128 totalAllocation,
|
|
@@ -136,7 +127,7 @@ contract VestingWalletExample is
|
|
|
136
127
|
// After end: 100% vested
|
|
137
128
|
return totalAllocation;
|
|
138
129
|
} else {
|
|
139
|
-
//
|
|
130
|
+
// ⚡ Gas warning: FHE.mul + FHE.div cost ~400k gas combined!
|
|
140
131
|
return
|
|
141
132
|
FHE.div(
|
|
142
133
|
FHE.mul(totalAllocation, (timestamp - start())),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-fhevm-example",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.4",
|
|
4
4
|
"description": "Create FHEVM example projects with a single command - A comprehensive toolkit for building privacy-preserving smart contracts",
|
|
5
5
|
"bin": {
|
|
6
6
|
"create-fhevm-example": "./dist/scripts/index.js"
|