@inco/lightning 0.8.0-devnet-3 → 0.8.0-devnet-5

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.
Files changed (46) hide show
  1. package/README.md +59 -1
  2. package/manifest.yaml +22 -0
  3. package/package.json +1 -1
  4. package/src/DeployUtils.sol +71 -25
  5. package/src/IncoLightning.sol +27 -7
  6. package/src/IncoVerifier.sol +18 -1
  7. package/src/Lib.alphanet.sol +390 -3
  8. package/src/Lib.demonet.sol +390 -3
  9. package/src/Lib.devnet.sol +391 -4
  10. package/src/Lib.sol +391 -4
  11. package/src/Lib.template.sol +387 -0
  12. package/src/Lib.testnet.sol +390 -3
  13. package/src/libs/incoLightning_alphanet_v0_297966649.sol +390 -3
  14. package/src/libs/incoLightning_alphanet_v1_725458969.sol +390 -3
  15. package/src/libs/incoLightning_alphanet_v2_976644394.sol +390 -3
  16. package/src/libs/incoLightning_demonet_v0_863421733.sol +390 -3
  17. package/src/libs/incoLightning_demonet_v2_467437523.sol +390 -3
  18. package/src/libs/incoLightning_devnet_v0_340846814.sol +390 -3
  19. package/src/libs/incoLightning_devnet_v1_904635675.sol +390 -3
  20. package/src/libs/incoLightning_devnet_v2_295237520.sol +390 -3
  21. package/src/libs/incoLightning_devnet_v3_976859633.sol +390 -3
  22. package/src/libs/incoLightning_devnet_v4_409204766.sol +921 -0
  23. package/src/libs/incoLightning_testnet_v0_183408998.sol +390 -3
  24. package/src/libs/incoLightning_testnet_v2_889158349.sol +390 -3
  25. package/src/lightning-parts/AccessControl/AdvancedAccessControl.sol +65 -4
  26. package/src/lightning-parts/AccessControl/BaseAccessControlList.sol +71 -5
  27. package/src/lightning-parts/DecryptionAttester.sol +16 -3
  28. package/src/lightning-parts/EncryptedInput.sol +80 -17
  29. package/src/lightning-parts/EncryptedOperations.sol +134 -1
  30. package/src/lightning-parts/Fee.sol +29 -6
  31. package/src/lightning-parts/interfaces/IEncryptedInput.sol +3 -3
  32. package/src/lightning-parts/primitives/EventCounter.sol +36 -5
  33. package/src/lightning-parts/primitives/HandleGeneration.sol +49 -13
  34. package/src/lightning-parts/primitives/HandleMetadata.sol +28 -0
  35. package/src/lightning-parts/primitives/LightningAddressGetter.sol +10 -0
  36. package/src/lightning-parts/primitives/VerifierAddressGetter.sol +10 -0
  37. package/src/lightning-parts/primitives/test/SignatureVerifier.t.sol +0 -2
  38. package/src/lightning-parts/test/HandleMetadata.t.sol +21 -13
  39. package/src/periphery/IncoUtils.sol +1 -0
  40. package/src/periphery/SessionVerifier.sol +35 -7
  41. package/src/test/FakeIncoInfra/FakeIncoInfraBase.sol +10 -2
  42. package/src/test/FakeIncoInfra/MockOpHandler.sol +1 -1
  43. package/src/test/TestFakeInfra.t.sol +536 -1
  44. package/src/version/IncoLightningConfig.sol +2 -2
  45. package/src/libs/incoLightning_devnet_v1_887305889.sol +0 -453
  46. package/src/libs/incoLightning_testnet_v1_938327937.sol +0 -453
@@ -7,9 +7,21 @@ import {HandleGeneration} from "./primitives/HandleGeneration.sol";
7
7
  import {IEncryptedOperations} from "./interfaces/IEncryptedOperations.sol";
8
8
  import {Fee} from "./Fee.sol";
9
9
 
10
+ /// @title EncryptedOperations
11
+ /// @notice Provides operations on encrypted values.
12
+ /// @dev All operations require the caller to have access to the input handles. Results are granted
13
+ /// transient access to the caller. Each operation emits an event that is processed by the covalidator
14
+ /// to perform the actual computation off-chain. The result handle is deterministically derived
15
+ /// from the operation and inputs, enabling consistent state across chains.
10
16
  abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControlList, HandleGeneration, Fee {
11
17
 
18
+ /// @notice Thrown when an operation receives a handle of an unexpected type.
19
+ /// @param actual The actual type of the handle.
20
+ /// @param expectedTypes A bitmask of the expected types.
12
21
  error UnexpectedType(ETypes actual, bytes32 expectedTypes);
22
+
23
+ /// @notice Thrown when an operation receives an unsupported type.
24
+ /// @param actual The unsupported type.
13
25
  error UnsupportedType(ETypes actual);
14
26
 
15
27
  uint256 internal randCounter;
@@ -55,17 +67,26 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
55
67
  event ENot(ebool indexed operand, ebool indexed result, uint256 eventId);
56
68
  event ECast(bytes32 indexed ct, uint8 indexed toType, bytes32 indexed result, uint256 eventId);
57
69
 
70
+ /// @dev Validates that both inputs are euint256 and the caller has access to them.
58
71
  modifier checked(euint256 lhs, euint256 rhs) {
59
72
  checkInput(euint256.unwrap(lhs), typeToBitMask(ETypes.Uint256));
60
73
  checkInput(euint256.unwrap(rhs), typeToBitMask(ETypes.Uint256));
61
74
  _;
62
75
  }
63
76
 
77
+ /// @dev Validates that the caller has access to the input handle and that its type matches the required types.
78
+ /// @param input The handle to validate.
79
+ /// @param requiredTypes A bitmask of acceptable types for this input.
64
80
  function checkInput(bytes32 input, bytes32 requiredTypes) internal view {
65
81
  require(isAllowed(input, msg.sender), SenderNotAllowedForHandle(input, msg.sender));
66
82
  require(requiredTypes & typeToBitMask(typeOf(input)) != 0, UnexpectedType(typeOf(input), requiredTypes));
67
83
  }
68
84
 
85
+ /// @dev Creates a result handle for an operation and grants transient access to the caller.
86
+ /// @param op The operation type.
87
+ /// @param returnType The type of the result handle.
88
+ /// @param packedInputs The packed input handles.
89
+ /// @return result The generated result handle.
69
90
  function createResultHandle(EOps op, ETypes returnType, bytes memory packedInputs)
70
91
  internal
71
92
  returns (bytes32 result)
@@ -74,6 +95,10 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
74
95
  allowTransientInternal(result, msg.sender);
75
96
  }
76
97
 
98
+ /// @notice Adds two encrypted uint256 values.
99
+ /// @param lhs The left-hand side encrypted operand.
100
+ /// @param rhs The right-hand side encrypted operand.
101
+ /// @return result The encrypted sum (lhs + rhs).
77
102
  function eAdd(euint256 lhs, euint256 rhs) external checked(lhs, rhs) returns (euint256 result) {
78
103
  result = euint256.wrap(
79
104
  createResultHandle(EOps.Add, ETypes.Uint256, abi.encodePacked(euint256.unwrap(lhs), euint256.unwrap(rhs)))
@@ -83,6 +108,10 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
83
108
  setDigest(abi.encodePacked(result, id));
84
109
  }
85
110
 
111
+ /// @notice Subtracts one encrypted uint256 from another.
112
+ /// @param lhs The left-hand side encrypted operand.
113
+ /// @param rhs The right-hand side encrypted operand.
114
+ /// @return result The encrypted difference (lhs - rhs).
86
115
  function eSub(euint256 lhs, euint256 rhs) external checked(lhs, rhs) returns (euint256 result) {
87
116
  result = euint256.wrap(
88
117
  createResultHandle(EOps.Sub, ETypes.Uint256, abi.encodePacked(euint256.unwrap(lhs), euint256.unwrap(rhs)))
@@ -92,6 +121,10 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
92
121
  setDigest(abi.encodePacked(result, id));
93
122
  }
94
123
 
124
+ /// @notice Multiplies two encrypted uint256 values.
125
+ /// @param lhs The left-hand side encrypted operand.
126
+ /// @param rhs The right-hand side encrypted operand.
127
+ /// @return result The encrypted product (lhs * rhs).
95
128
  function eMul(euint256 lhs, euint256 rhs) external checked(lhs, rhs) returns (euint256 result) {
96
129
  result = euint256.wrap(
97
130
  createResultHandle(EOps.Mul, ETypes.Uint256, abi.encodePacked(euint256.unwrap(lhs), euint256.unwrap(rhs)))
@@ -101,6 +134,11 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
101
134
  setDigest(abi.encodePacked(result, id));
102
135
  }
103
136
 
137
+ /// @notice Divides one encrypted uint256 by another.
138
+ /// @dev Division by zero returns zero.
139
+ /// @param lhs The dividend (encrypted).
140
+ /// @param rhs The divisor (encrypted).
141
+ /// @return result The encrypted quotient (lhs / rhs).
104
142
  function eDiv(euint256 lhs, euint256 rhs) external checked(lhs, rhs) returns (euint256 result) {
105
143
  result = euint256.wrap(
106
144
  createResultHandle(EOps.Div, ETypes.Uint256, abi.encodePacked(euint256.unwrap(lhs), euint256.unwrap(rhs)))
@@ -110,6 +148,11 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
110
148
  setDigest(abi.encodePacked(result, id));
111
149
  }
112
150
 
151
+ /// @notice Computes the remainder of dividing one encrypted uint256 by another.
152
+ /// @dev Remainder by zero returns zero.
153
+ /// @param lhs The dividend (encrypted).
154
+ /// @param rhs The divisor (encrypted).
155
+ /// @return result The encrypted remainder (lhs % rhs).
113
156
  function eRem(euint256 lhs, euint256 rhs) external virtual checked(lhs, rhs) returns (euint256 result) {
114
157
  result = euint256.wrap(
115
158
  createResultHandle(EOps.Rem, ETypes.Uint256, abi.encodePacked(euint256.unwrap(lhs), euint256.unwrap(rhs)))
@@ -119,6 +162,10 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
119
162
  setDigest(abi.encodePacked(result, id));
120
163
  }
121
164
 
165
+ /// @notice Performs bitwise AND on two encrypted values of the same type.
166
+ /// @param lhs The left-hand side encrypted operand.
167
+ /// @param rhs The right-hand side encrypted operand (must be same type as lhs).
168
+ /// @return result The encrypted bitwise AND result.
122
169
  function eBitAnd(bytes32 lhs, bytes32 rhs) external returns (bytes32 result) {
123
170
  ETypes lhsType = typeOf(lhs);
124
171
  ETypes rhsType = typeOf(rhs);
@@ -131,6 +178,10 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
131
178
  setDigest(abi.encodePacked(result, id));
132
179
  }
133
180
 
181
+ /// @notice Performs bitwise OR on two encrypted values of the same type.
182
+ /// @param lhs The left-hand side encrypted operand.
183
+ /// @param rhs The right-hand side encrypted operand (must be same type as lhs).
184
+ /// @return result The encrypted bitwise OR result.
134
185
  function eBitOr(bytes32 lhs, bytes32 rhs) external returns (bytes32 result) {
135
186
  ETypes lhsType = typeOf(lhs);
136
187
  ETypes rhsType = typeOf(rhs);
@@ -143,6 +194,10 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
143
194
  setDigest(abi.encodePacked(result, id));
144
195
  }
145
196
 
197
+ /// @notice Performs bitwise XOR on two encrypted values of the same type.
198
+ /// @param lhs The left-hand side encrypted operand.
199
+ /// @param rhs The right-hand side encrypted operand (must be same type as lhs).
200
+ /// @return result The encrypted bitwise XOR result.
146
201
  function eBitXor(bytes32 lhs, bytes32 rhs) external returns (bytes32 result) {
147
202
  ETypes lhsType = typeOf(lhs);
148
203
  ETypes rhsType = typeOf(rhs);
@@ -155,6 +210,10 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
155
210
  setDigest(abi.encodePacked(result, id));
156
211
  }
157
212
 
213
+ /// @notice Shifts an encrypted uint256 left by an encrypted number of bits.
214
+ /// @param lhs The value to shift (encrypted).
215
+ /// @param rhs The number of bits to shift by (encrypted).
216
+ /// @return result The encrypted left-shifted result.
158
217
  function eShl(euint256 lhs, euint256 rhs) external checked(lhs, rhs) returns (euint256 result) {
159
218
  result = euint256.wrap(
160
219
  createResultHandle(EOps.Shl, ETypes.Uint256, abi.encodePacked(euint256.unwrap(lhs), euint256.unwrap(rhs)))
@@ -164,6 +223,10 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
164
223
  setDigest(abi.encodePacked(result, id));
165
224
  }
166
225
 
226
+ /// @notice Shifts an encrypted uint256 right by an encrypted number of bits.
227
+ /// @param lhs The value to shift (encrypted).
228
+ /// @param rhs The number of bits to shift by (encrypted).
229
+ /// @return result The encrypted right-shifted result.
167
230
  function eShr(euint256 lhs, euint256 rhs) external checked(lhs, rhs) returns (euint256 result) {
168
231
  result = euint256.wrap(
169
232
  createResultHandle(EOps.Shr, ETypes.Uint256, abi.encodePacked(euint256.unwrap(lhs), euint256.unwrap(rhs)))
@@ -173,6 +236,10 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
173
236
  setDigest(abi.encodePacked(result, id));
174
237
  }
175
238
 
239
+ /// @notice Rotates an encrypted uint256 left by an encrypted number of bits.
240
+ /// @param lhs The value to rotate (encrypted).
241
+ /// @param rhs The number of bits to rotate by (encrypted).
242
+ /// @return result The encrypted left-rotated result.
176
243
  function eRotl(euint256 lhs, euint256 rhs) external checked(lhs, rhs) returns (euint256 result) {
177
244
  result = euint256.wrap(
178
245
  createResultHandle(EOps.Rotl, ETypes.Uint256, abi.encodePacked(euint256.unwrap(lhs), euint256.unwrap(rhs)))
@@ -182,6 +249,10 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
182
249
  setDigest(abi.encodePacked(result, id));
183
250
  }
184
251
 
252
+ /// @notice Rotates an encrypted uint256 right by an encrypted number of bits.
253
+ /// @param lhs The value to rotate (encrypted).
254
+ /// @param rhs The number of bits to rotate by (encrypted).
255
+ /// @return result The encrypted right-rotated result.
185
256
  function eRotr(euint256 lhs, euint256 rhs) external checked(lhs, rhs) returns (euint256 result) {
186
257
  result = euint256.wrap(
187
258
  createResultHandle(EOps.Rotr, ETypes.Uint256, abi.encodePacked(euint256.unwrap(lhs), euint256.unwrap(rhs)))
@@ -191,6 +262,11 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
191
262
  setDigest(abi.encodePacked(result, id));
192
263
  }
193
264
 
265
+ /// @notice Checks if two encrypted values are equal.
266
+ /// @dev Supports euint256, ebool, and eaddress types.
267
+ /// @param lhs The left-hand side encrypted operand.
268
+ /// @param rhs The right-hand side encrypted operand.
269
+ /// @return result An encrypted boolean (true if lhs == rhs).
194
270
  function eEq(bytes32 lhs, bytes32 rhs) external returns (ebool result) {
195
271
  checkInput(lhs, SUPPORTED_TYPES_MASK);
196
272
  checkInput(rhs, SUPPORTED_TYPES_MASK);
@@ -201,6 +277,11 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
201
277
  setDigest(abi.encodePacked(result, id));
202
278
  }
203
279
 
280
+ /// @notice Checks if two encrypted values are not equal.
281
+ /// @dev Supports euint256, ebool, and eaddress types.
282
+ /// @param lhs The left-hand side encrypted operand.
283
+ /// @param rhs The right-hand side encrypted operand.
284
+ /// @return result An encrypted boolean (true if lhs != rhs).
204
285
  function eNe(bytes32 lhs, bytes32 rhs) external returns (ebool result) {
205
286
  checkInput(lhs, SUPPORTED_TYPES_MASK);
206
287
  checkInput(rhs, SUPPORTED_TYPES_MASK);
@@ -211,6 +292,10 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
211
292
  setDigest(abi.encodePacked(result, id));
212
293
  }
213
294
 
295
+ /// @notice Checks if lhs is greater than or equal to rhs.
296
+ /// @param lhs The left-hand side encrypted operand.
297
+ /// @param rhs The right-hand side encrypted operand.
298
+ /// @return result An encrypted boolean (true if lhs >= rhs).
214
299
  function eGe(euint256 lhs, euint256 rhs) external checked(lhs, rhs) returns (ebool result) {
215
300
  result = ebool.wrap(
216
301
  createResultHandle(EOps.Ge, ETypes.Bool, abi.encodePacked(euint256.unwrap(lhs), euint256.unwrap(rhs)))
@@ -220,6 +305,10 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
220
305
  setDigest(abi.encodePacked(result, id));
221
306
  }
222
307
 
308
+ /// @notice Checks if lhs is greater than rhs.
309
+ /// @param lhs The left-hand side encrypted operand.
310
+ /// @param rhs The right-hand side encrypted operand.
311
+ /// @return result An encrypted boolean (true if lhs > rhs).
223
312
  function eGt(euint256 lhs, euint256 rhs) external checked(lhs, rhs) returns (ebool result) {
224
313
  result = ebool.wrap(
225
314
  createResultHandle(EOps.Gt, ETypes.Bool, abi.encodePacked(euint256.unwrap(lhs), euint256.unwrap(rhs)))
@@ -229,6 +318,10 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
229
318
  setDigest(abi.encodePacked(result, id));
230
319
  }
231
320
 
321
+ /// @notice Checks if lhs is less than or equal to rhs.
322
+ /// @param lhs The left-hand side encrypted operand.
323
+ /// @param rhs The right-hand side encrypted operand.
324
+ /// @return result An encrypted boolean (true if lhs <= rhs).
232
325
  function eLe(euint256 lhs, euint256 rhs) external checked(lhs, rhs) returns (ebool result) {
233
326
  result = ebool.wrap(
234
327
  createResultHandle(EOps.Le, ETypes.Bool, abi.encodePacked(euint256.unwrap(lhs), euint256.unwrap(rhs)))
@@ -238,6 +331,10 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
238
331
  setDigest(abi.encodePacked(result, id));
239
332
  }
240
333
 
334
+ /// @notice Checks if lhs is less than rhs.
335
+ /// @param lhs The left-hand side encrypted operand.
336
+ /// @param rhs The right-hand side encrypted operand.
337
+ /// @return result An encrypted boolean (true if lhs < rhs).
241
338
  function eLt(euint256 lhs, euint256 rhs) external checked(lhs, rhs) returns (ebool result) {
242
339
  result = ebool.wrap(
243
340
  createResultHandle(EOps.Lt, ETypes.Bool, abi.encodePacked(euint256.unwrap(lhs), euint256.unwrap(rhs)))
@@ -247,6 +344,10 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
247
344
  setDigest(abi.encodePacked(result, id));
248
345
  }
249
346
 
347
+ /// @notice Returns the minimum of two encrypted uint256 values.
348
+ /// @param lhs The first encrypted value.
349
+ /// @param rhs The second encrypted value.
350
+ /// @return result The encrypted minimum value.
250
351
  function eMin(euint256 lhs, euint256 rhs) external checked(lhs, rhs) returns (euint256 result) {
251
352
  result = euint256.wrap(
252
353
  createResultHandle(EOps.Min, ETypes.Uint256, abi.encodePacked(euint256.unwrap(lhs), euint256.unwrap(rhs)))
@@ -256,6 +357,10 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
256
357
  setDigest(abi.encodePacked(result, id));
257
358
  }
258
359
 
360
+ /// @notice Returns the maximum of two encrypted uint256 values.
361
+ /// @param lhs The first encrypted value.
362
+ /// @param rhs The second encrypted value.
363
+ /// @return result The encrypted maximum value.
259
364
  function eMax(euint256 lhs, euint256 rhs) external checked(lhs, rhs) returns (euint256 result) {
260
365
  result = euint256.wrap(
261
366
  createResultHandle(EOps.Max, ETypes.Uint256, abi.encodePacked(euint256.unwrap(lhs), euint256.unwrap(rhs)))
@@ -265,6 +370,9 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
265
370
  setDigest(abi.encodePacked(result, id));
266
371
  }
267
372
 
373
+ /// @notice Performs logical NOT on an encrypted boolean.
374
+ /// @param operand The encrypted boolean to negate.
375
+ /// @return result The negated encrypted boolean.
268
376
  function eNot(ebool operand) external returns (ebool result) {
269
377
  checkInput(ebool.unwrap(operand), typeToBitMask(ETypes.Bool));
270
378
  result = ebool.wrap(createResultHandle(EOps.Not, ETypes.Bool, abi.encodePacked(ebool.unwrap(operand))));
@@ -273,6 +381,11 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
273
381
  setDigest(abi.encodePacked(result, id));
274
382
  }
275
383
 
384
+ /// @notice Casts an encrypted value to a different encrypted type.
385
+ /// @dev Supports casting between euint256, ebool, and eaddress.
386
+ /// @param ct The encrypted value to cast.
387
+ /// @param toType The target type to cast to.
388
+ /// @return result The casted encrypted value.
276
389
  function eCast(bytes32 ct, ETypes toType) external returns (bytes32 result) {
277
390
  checkInput(ct, SUPPORTED_TYPES_MASK);
278
391
  require(isTypeSupported(toType), UnsupportedType(toType));
@@ -283,6 +396,10 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
283
396
  setDigest(abi.encodePacked(result, id));
284
397
  }
285
398
 
399
+ /// @notice Generates an encrypted random value of the specified type.
400
+ /// @dev This is a paid operation.
401
+ /// @param randType The type of random value to generate.
402
+ /// @return result An encrypted random value.
286
403
  function eRand(ETypes randType) external payable paying returns (bytes32 result) {
287
404
  require(isTypeSupported(randType), UnsupportedType(randType));
288
405
  randCounter++;
@@ -292,6 +409,11 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
292
409
  setDigest(abi.encodePacked(result, id));
293
410
  }
294
411
 
412
+ /// @notice Generates an encrypted random value bounded by an upper limit.
413
+ /// @dev This is a paid operation. The result is in the range [0, upperBound).
414
+ /// @param upperBound The encrypted upper bound (exclusive).
415
+ /// @param randType The type of random value to generate.
416
+ /// @return result An encrypted random value less than upperBound.
295
417
  function eRandBounded(bytes32 upperBound, ETypes randType) external payable paying returns (bytes32 result) {
296
418
  require(isTypeSupported(randType), UnsupportedType(randType));
297
419
  checkInput(upperBound, typeToBitMask(ETypes.Uint256));
@@ -302,7 +424,13 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
302
424
  setDigest(abi.encodePacked(result, id));
303
425
  }
304
426
 
305
- // todo add support in testing framework
427
+ /// @notice Selects between two encrypted values based on an encrypted condition.
428
+ /// @dev Returns ifTrue if control is true, otherwise returns ifFalse.
429
+ /// Both ifTrue and ifFalse must be the same type.
430
+ /// @param control The encrypted boolean condition.
431
+ /// @param ifTrue The value to return if control is true.
432
+ /// @param ifFalse The value to return if control is false.
433
+ /// @return result The selected encrypted value.
306
434
  function eIfThenElse(ebool control, bytes32 ifTrue, bytes32 ifFalse) external returns (bytes32 result) {
307
435
  ETypes returnType = checkEIfThenElseInputs(control, ifTrue, ifFalse);
308
436
  result =
@@ -313,6 +441,11 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
313
441
  setDigest(abi.encodePacked(result, id));
314
442
  }
315
443
 
444
+ /// @dev Validates inputs for eIfThenElse operation.
445
+ /// @param control The encrypted boolean condition (must be ebool).
446
+ /// @param ifTrue The value to return if control is true.
447
+ /// @param ifFalse The value to return if control is false (must match ifTrue type).
448
+ /// @return ifTrueType The type of the ifTrue/ifFalse values.
316
449
  function checkEIfThenElseInputs(ebool control, bytes32 ifTrue, bytes32 ifFalse)
317
450
  internal
318
451
  view
@@ -1,34 +1,57 @@
1
1
  // SPDX-License-Identifier: No License
2
2
  pragma solidity ^0.8;
3
3
 
4
- // the fee should be modified through upgrades to limit gas cost
4
+ /// @dev The current fee required for paid encryption operations.
5
+ /// This constant may be modified through contract upgrades.
6
+ /// Developers should call getFee() rather than hardcoding this value.
5
7
  uint256 constant FEE = 0.000001 ether;
6
8
 
7
- /// @notice Fee utils for lightning functions that require a fee
8
- /// @dev the fee may be changed through upgrades, develop your apps accordingly!
9
+ /// @title Fee
10
+ /// @notice Fee management utilities for encryption operations that require payment
11
+ /// @dev Certain operations (encrypted inputs, randomness) require a fee to cover covalidator costs.
12
+ /// The fee is paid via msg.value and accumulates in the contract balance.
13
+ /// The contract owner can withdraw accumulated fees via withdrawFees() in IncoLightning.
14
+ ///
15
+ /// Important: The fee amount may change through contract upgrades. Always use getFee()
16
+ /// to determine the current fee rather than hardcoding values.
9
17
  abstract contract Fee {
10
18
 
19
+ /// @notice Thrown when the exact required fee is not paid
11
20
  error FeeNotPaid();
21
+
22
+ /// @notice Thrown when the ETH transfer during fee withdrawal fails
12
23
  error FeeWithdrawalFailed();
24
+
25
+ /// @notice Thrown when attempting to withdraw with zero balance
13
26
  error NoFeesToWithdraw();
14
27
 
15
- /// @notice the fee to pay through msg.value for inputs and randomness IT MAY CHANGE
28
+ /// @notice Returns the fee required for paid operations
29
+ /// @dev The fee may change through contract upgrades. Always query this function
30
+ /// to get the current fee rather than caching the value.
31
+ /// @return The fee amount in wei
16
32
  function getFee() public pure returns (uint256) {
17
33
  return FEE;
18
34
  }
19
35
 
36
+ /// @notice Modifier that requires the exact fee to be paid via msg.value
37
+ /// @dev Use this modifier on functions that require a single fee payment (e.g., single input)
20
38
  modifier paying() {
21
39
  require(msg.value == FEE, FeeNotPaid());
22
40
  _;
23
41
  }
24
42
 
43
+ /// @notice Modifier that requires multiple fees to be paid via msg.value
44
+ /// @dev Use this modifier on functions that require payment for multiple operations (e.g., batch inputs)
45
+ /// @param nbOfFees The number of fee units required (total cost = FEE * nbOfFees)
25
46
  modifier payingMultiple(uint256 nbOfFees) {
26
47
  require(msg.value == FEE * nbOfFees, FeeNotPaid());
27
48
  _;
28
49
  }
29
50
 
30
- /// @notice Internal helper to withdraw accumulated fees to a recipient
31
- /// @param recipient The address to send the fees to
51
+ /// @notice Withdraws all accumulated fees to the specified recipient
52
+ /// @dev Internal function called by IncoLightning.withdrawFees(). Transfers the entire
53
+ /// contract balance to the recipient.
54
+ /// @param recipient The address to send the accumulated fees to
32
55
  function _withdrawFeesTo(address recipient) internal {
33
56
  uint256 fees = address(this).balance;
34
57
  require(fees > 0, NoFeesToWithdraw());
@@ -5,8 +5,8 @@ import {euint256, ebool, eaddress} from "../../Types.sol";
5
5
 
6
6
  interface IEncryptedInput {
7
7
 
8
- function newEuint256(bytes memory ciphertext, address user) external payable returns (euint256 newValue);
9
- function newEbool(bytes memory ciphertext, address user) external payable returns (ebool newValue);
10
- function newEaddress(bytes memory ciphertext, address user) external payable returns (eaddress newValue);
8
+ function newEuint256(bytes calldata ciphertext, address user) external payable returns (euint256 newValue);
9
+ function newEbool(bytes calldata ciphertext, address user) external payable returns (ebool newValue);
10
+ function newEaddress(bytes calldata ciphertext, address user) external payable returns (eaddress newValue);
11
11
 
12
12
  }
@@ -3,15 +3,25 @@ pragma solidity ^0.8;
3
3
 
4
4
  import {IEventCounter} from "./interfaces/IEventCounter.sol";
5
5
 
6
+ /// @title EventCounterStorage
7
+ /// @notice Diamond storage pattern for the event counter state
8
+ /// @dev Uses a unique storage slot to avoid conflicts with other contracts in the inheritance chain.
9
+ /// The event counter provides unique, sequential identifiers for encrypted operations within a transaction.
6
10
  contract EventCounterStorage {
7
11
 
12
+ /// @notice Storage struct containing the event counter state
13
+ /// @dev eventCounter is incremented for each encrypted operation to ensure unique handle generation
8
14
  struct Storage {
9
- // TODO: change type to bytes32 when we rename away from "counter".
10
- uint256 eventCounter;
15
+ /// @notice Counter that increments for each event, or stores a digest for batch operations
16
+ uint256 eventCounter; // TODO: change type to bytes32 when we rename away from "counter".
11
17
  }
12
18
 
19
+ /// @notice Storage slot location using keccak256 of a unique namespace string
13
20
  bytes32 private constant EVENT_COUNTER_STORAGE_LOCATION = keccak256("lightning.storage.EventCounter");
14
21
 
22
+ /// @notice Retrieves the storage struct from its dedicated slot
23
+ /// @dev Uses assembly to directly access the storage slot for gas efficiency
24
+ /// @return $ Reference to the Storage struct
15
25
  function getEventCounterStorage() internal pure returns (Storage storage $) {
16
26
  bytes32 loc = EVENT_COUNTER_STORAGE_LOCATION;
17
27
  assembly {
@@ -21,23 +31,44 @@ contract EventCounterStorage {
21
31
 
22
32
  }
23
33
 
34
+ /// @title EventCounter
35
+ /// @notice Manages unique event identifiers for encrypted operation handle generation
36
+ /// @dev Each encrypted operation requires a unique identifier to generate deterministic handles.
37
+ /// This contract provides two modes:
38
+ /// 1. Sequential mode: getNewEventId() increments counter for each operation
39
+ /// 2. Digest mode: setDigest() sets counter to hash of serialized operations (for batching)
40
+ ///
41
+ /// The event ID is incorporated into handle generation to ensure uniqueness even when
42
+ /// the same operation is performed multiple times in the same transaction.
24
43
  contract EventCounter is IEventCounter, EventCounterStorage {
25
44
 
45
+ /// @notice Generates and returns a new unique event ID
46
+ /// @dev Post-increments the counter, so the returned value is the ID before incrementing.
47
+ /// This ensures each call returns a unique ID within the contract's lifetime.
48
+ /// @return newEventId The event ID to use for this operation
26
49
  function getNewEventId() internal returns (uint256 newEventId) {
27
50
  newEventId = getEventCounterStorage().eventCounter++;
28
51
  }
29
52
 
53
+ /// @notice Sets the event counter to a digest value for batch operation tracking
54
+ /// @dev Used when processing batched operations where a serialization hash
55
+ /// provides better uniqueness than sequential IDs
56
+ /// @param serialization The serialized batch data to hash
30
57
  function setDigest(bytes memory serialization) internal {
31
58
  getEventCounterStorage().eventCounter = uint256(keccak256(serialization));
32
59
  }
33
60
 
34
- // @notice Gives the next event ID value to use.
61
+ /// @notice Returns the next event ID that will be assigned
62
+ /// @dev View function that does not modify state. Useful for predicting handles
63
+ /// or verifying the current state of the counter.
64
+ /// @return The next event ID value
35
65
  function getNextEventId() public view returns (uint256) {
36
66
  return getEventCounterStorage().eventCounter;
37
67
  }
38
68
 
39
- // @notice Gives the current value of the event counter.
40
- // @dev DEPRECATED: use getNextEventId() instead.
69
+ /// @notice Returns the current value of the event counter
70
+ /// @dev Deprecated: Use getNextEventId() instead. Kept for backwards compatibility.
71
+ /// @return The current event counter value
41
72
  function getEventCounter() public view returns (uint256) {
42
73
  return getNextEventId();
43
74
  }
@@ -5,35 +5,63 @@ import {ETypes, EOps, EVM_HOST_CHAIN_PREFIX, HANDLE_INDEX} from "../../Types.sol
5
5
  import {HandleMetadata} from "./HandleMetadata.sol";
6
6
  import {IHandleGeneration} from "./interfaces/IHandleGeneration.sol";
7
7
 
8
+ /// @title HandleGeneration
9
+ /// @notice Generates deterministic handles for encrypted values.
10
+ /// @dev Handles are unique identifiers for encrypted ciphertexts. They are computed deterministically
11
+ /// from the operation type and inputs, ensuring the same encrypted operation always produces the same
12
+ /// handle. This enables consistent state across chains and allows the covalidator to map handles to
13
+ /// their corresponding ciphertexts. Handles embed type and version metadata in their lower bytes.
8
14
  contract HandleGeneration is IHandleGeneration, HandleMetadata {
9
15
 
16
+ /// @notice Generates a handle for a trivially encrypted value.
17
+ /// @dev Trivial encryption creates a handle from a known plaintext. The handle is deterministic
18
+ /// based on the plaintext value, allowing the same plaintext to always produce the same handle.
19
+ /// @param plaintextBytes The plaintext value as bytes32.
20
+ /// @param handleType The type of encrypted value (euint256, ebool, etc.).
21
+ /// @return generatedHandle The deterministic handle for this trivial encryption.
10
22
  function getTrivialEncryptHandle(bytes32 plaintextBytes, ETypes handleType)
11
23
  public
12
24
  pure
13
25
  returns (bytes32 generatedHandle)
14
26
  {
15
- generatedHandle = keccak256(
16
- abi.encodePacked(
17
- EOps.TrivialEncrypt, // !! Note[Silas]: I reordered this to be first element for greater regularity 26/08/2025 (remove this note after 1 month) !!
18
- plaintextBytes
19
- )
20
- );
27
+ generatedHandle = keccak256(abi.encodePacked(EOps.TrivialEncrypt, plaintextBytes));
21
28
  generatedHandle = embedTypeVersion(generatedHandle, handleType);
22
29
  }
23
30
 
24
- function getInputHandle(bytes memory ciphertext, address user, address contractAddress, ETypes inputType)
25
- internal
26
- view
27
- returns (bytes32 generatedHandle)
28
- {
29
- return getInputHandle(ciphertext, address(this), user, contractAddress, inputType);
31
+ /// @notice Generates a handle for a client-encrypted input.
32
+ /// @dev Internal version that uses the current contract as the executor address.
33
+ /// The handle is computed from the ciphertext and context (chain, executor, user, contract).
34
+ /// @param ciphertext The encrypted input data.
35
+ /// @param user The user address that encrypted the value.
36
+ /// @param contractAddress The contract submitting the input.
37
+ /// @param version The version of the handle format.
38
+ /// @param inputType The type of encrypted value.
39
+ /// @return generatedHandle The deterministic handle for this input.
40
+ function getInputHandle(
41
+ bytes memory ciphertext,
42
+ address user,
43
+ address contractAddress,
44
+ int32 version,
45
+ ETypes inputType
46
+ ) internal view returns (bytes32 generatedHandle) {
47
+ return getInputHandle(ciphertext, address(this), user, contractAddress, version, inputType);
30
48
  }
31
49
 
50
+ /// @notice Generates a handle for a client-encrypted input with explicit executor.
51
+ /// @dev The handle incorporates the full context (chain ID, executor, user, contract) to ensure
52
+ /// uniqueness across different chains and deployments. This prevents replay attacks.
53
+ /// @param ciphertext The encrypted input data.
54
+ /// @param executorAddress The executor contract address.
55
+ /// @param user The user address that encrypted the value.
56
+ /// @param contractAddress The contract submitting the input.
57
+ /// @param inputType The type of encrypted value.
58
+ /// @return generatedHandle The deterministic handle for this input.
32
59
  function getInputHandle(
33
60
  bytes memory ciphertext,
34
61
  address executorAddress,
35
62
  address user,
36
63
  address contractAddress,
64
+ int32 version,
37
65
  ETypes inputType
38
66
  ) internal view returns (bytes32 generatedHandle) {
39
67
  // Here we ensure that our hashing scheme is binary-compatible between IncoLightning and IncoFhevm, this helps
@@ -49,13 +77,21 @@ contract HandleGeneration is IHandleGeneration, HandleMetadata {
49
77
  block.chainid, // todo cache this
50
78
  executorAddress,
51
79
  user,
52
- contractAddress
80
+ contractAddress,
81
+ version
53
82
  )
54
83
  ),
55
84
  inputType
56
85
  );
57
86
  }
58
87
 
88
+ /// @notice Generates a handle for the result of an encrypted operation.
89
+ /// @dev The handle is deterministic based on the operation type and input handles.
90
+ /// This ensures that the same operation on the same inputs always produces the same result handle.
91
+ /// @param op The operation type (eAdd, eSub, etc.).
92
+ /// @param returnType The type of the result value.
93
+ /// @param packedInputs The packed input handles.
94
+ /// @return generatedHandle The deterministic handle for this operation result.
59
95
  function getOpResultHandle(EOps op, ETypes returnType, bytes memory packedInputs)
60
96
  public
61
97
  pure
@@ -3,8 +3,24 @@ pragma solidity ^0.8;
3
3
 
4
4
  import {HANDLE_VERSION, HANDLE_INDEX, ETypes} from "../../Types.sol";
5
5
 
6
+ /// @title HandleMetadata
7
+ /// @notice Utilities for embedding and extracting metadata from encrypted value handles
8
+ /// @dev Handle structure (32 bytes / 256 bits):
9
+ /// - Bytes 0-28: Handle-specific data (hash, counters, etc.)
10
+ /// - Byte 29: Handle index (distinguishes input vs operation handles)
11
+ /// - Byte 30: Encrypted type (ETypes enum value)
12
+ /// - Byte 31: Handle version
6
13
  contract HandleMetadata {
7
14
 
15
+ /// @notice Embeds the handle index, encrypted type, and protocol version into a prehandle
16
+ /// @dev Used for input handles where the index distinguishes the source.
17
+ /// Clears bytes 29-31 of the prehandle, then sets:
18
+ /// - Byte 29: HANDLE_INDEX constant
19
+ /// - Byte 30: inputType enum value
20
+ /// - Byte 31: HANDLE_VERSION constant
21
+ /// @param prehandle The 32-byte hash before metadata embedding
22
+ /// @param inputType The encrypted type to embed (ebool, euint8, etc.)
23
+ /// @return result The complete handle with embedded metadata
8
24
  function embedIndexTypeVersion(bytes32 prehandle, ETypes inputType) internal pure returns (bytes32 result) {
9
25
  // Create a mask to clear the last three bytes
10
26
  bytes32 mask = bytes32(uint256(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFF));
@@ -15,12 +31,24 @@ contract HandleMetadata {
15
31
  result = embedTypeVersion(result, inputType);
16
32
  }
17
33
 
34
+ /// @notice Embeds the encrypted type and protocol version into a prehandle
35
+ /// @dev Used for operation result handles and trivial encryptions.
36
+ /// Clears bytes 30-31 of the prehandle, then sets:
37
+ /// - Byte 30: handleType enum value
38
+ /// - Byte 31: HANDLE_VERSION constant
39
+ /// @param prehandle The 32-byte hash before metadata embedding
40
+ /// @param handleType The encrypted type to embed (ebool, euint8, etc.)
41
+ /// @return result The handle with type and version embedded
18
42
  function embedTypeVersion(bytes32 prehandle, ETypes handleType) internal pure returns (bytes32 result) {
19
43
  result = prehandle & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000;
20
44
  result = bytes32(uint256(result) | (uint256(handleType) << 8)); // append type
21
45
  result = bytes32(uint256(result) | HANDLE_VERSION);
22
46
  }
23
47
 
48
+ /// @notice Extracts the encrypted type from a handle
49
+ /// @dev Reads byte 30 of the handle and casts to ETypes enum
50
+ /// @param handle The encrypted value handle to inspect
51
+ /// @return The encrypted type (ebool, euint8, euint16, etc.)
24
52
  function typeOf(bytes32 handle) internal pure returns (ETypes) {
25
53
  return ETypes(uint8(uint256(handle) >> 8));
26
54
  }