@inco/lightning 0.9.0-devnet-test-10 → 0.10.0-devnet-2
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/manifest.yaml +150 -0
- package/package.json +8 -8
- package/src/CreateXHelper.sol +1 -1
- package/src/DeployUtils.sol +22 -28
- package/src/IncoLightning.sol +27 -18
- package/src/IncoVerifier.sol +1 -1
- package/src/Lib.alphanet.sol +294 -13
- package/src/Lib.demonet.sol +294 -13
- package/src/Lib.devnet.sol +294 -13
- package/src/Lib.sol +294 -13
- package/src/Lib.template.sol +357 -13
- package/src/Lib.testnet.sol +294 -13
- package/src/Types.sol +44 -0
- package/src/interfaces/IIncoLightning.sol +8 -12
- package/src/interfaces/automata-interfaces/BELE.sol +1 -1
- package/src/interfaces/automata-interfaces/IPCCSRouter.sol +1 -1
- package/src/interfaces/automata-interfaces/IPcsDao.sol +1 -1
- package/src/interfaces/automata-interfaces/IQuoteVerifier.sol +1 -1
- package/src/interfaces/automata-interfaces/Types.sol +1 -1
- package/src/libs/incoLightning_alphanet_v0_297966649.sol +294 -13
- package/src/libs/incoLightning_alphanet_v1_725458969.sol +294 -13
- package/src/libs/incoLightning_alphanet_v2_976644394.sol +294 -13
- package/src/libs/incoLightning_demonet_v0_863421733.sol +294 -13
- package/src/libs/incoLightning_demonet_v2_467437523.sol +294 -13
- package/src/libs/incoLightning_devnet_v0_340846814.sol +294 -13
- package/src/libs/incoLightning_devnet_v10_266391127.sol +1223 -0
- package/src/libs/incoLightning_devnet_v1_904635675.sol +294 -13
- package/src/libs/incoLightning_devnet_v2_295237520.sol +294 -13
- package/src/libs/incoLightning_devnet_v3_976859633.sol +294 -13
- package/src/libs/incoLightning_devnet_v4_409204766.sol +294 -13
- package/src/libs/incoLightning_devnet_v5_203964628.sol +1223 -0
- package/src/libs/incoLightning_devnet_v6_281949651.sol +1223 -0
- package/src/libs/incoLightning_devnet_v7_24560427.sol +1223 -0
- package/src/libs/incoLightning_devnet_v8_985328058.sol +1223 -0
- package/src/libs/incoLightning_devnet_v9_269218568.sol +1223 -0
- package/src/libs/incoLightning_testnet_v0_183408998.sol +294 -13
- package/src/libs/incoLightning_testnet_v2_889158349.sol +294 -13
- package/src/lightning-parts/AccessControl/AdvancedAccessControl.sol +8 -3
- package/src/lightning-parts/AccessControl/BaseAccessControlList.sol +0 -16
- package/src/lightning-parts/AccessControl/interfaces/IAdvancedAccessControl.sol +1 -1
- package/src/lightning-parts/AccessControl/interfaces/IBaseAccessControlList.sol +3 -2
- package/src/lightning-parts/AccessControl/test/TestAdvancedAccessControl.t.sol +18 -1
- package/src/lightning-parts/AccessControl/test/TestBaseAccessControl.t.sol +0 -43
- package/src/lightning-parts/DecryptionAttester.sol +124 -2
- package/src/lightning-parts/DecryptionAttester.types.sol +20 -0
- package/src/lightning-parts/EList.sol +397 -0
- package/src/lightning-parts/EncryptedInput.sol +78 -8
- package/src/lightning-parts/EncryptedOperations.sol +40 -34
- package/src/lightning-parts/Fee.sol +29 -0
- package/src/lightning-parts/TEELifecycle.sol +38 -30
- package/src/lightning-parts/TEELifecycle.types.sol +1 -1
- package/src/lightning-parts/TrivialEncryption.sol +1 -2
- package/src/lightning-parts/interfaces/IDecryptionAttester.sol +16 -1
- package/src/lightning-parts/interfaces/IEList.sol +38 -0
- package/src/lightning-parts/interfaces/IEncryptedInput.sol +9 -1
- package/src/lightning-parts/interfaces/IEncryptedOperations.sol +3 -2
- package/src/lightning-parts/interfaces/ITEELifecycle.sol +1 -1
- package/src/lightning-parts/interfaces/ITrivialEncryption.sol +3 -1
- package/src/lightning-parts/primitives/EListHandleGeneration.sol +66 -0
- package/src/lightning-parts/primitives/EListHandleMetadata.sol +67 -0
- package/src/lightning-parts/primitives/HandleGeneration.sol +31 -8
- package/src/lightning-parts/primitives/HandleMetadata.sol +10 -3
- package/src/lightning-parts/primitives/interfaces/IEListHandleMetadata.sol +8 -0
- package/src/lightning-parts/primitives/test/SignatureVerifier.t.sol +1 -1
- package/src/lightning-parts/test/Elist.t.sol +218 -0
- package/src/lightning-parts/test/HandleMetadata.t.sol +66 -23
- package/src/lightning-parts/test/TestDecryptionAttestationInSynchronousFlow.t.sol +41 -13
- package/src/misc/ABIHelper.sol +15 -0
- package/src/pasted-dependencies/ICreateX.sol +1 -1
- package/src/periphery/IncoUtils.sol +1 -1
- package/src/periphery/SessionVerifier.sol +4 -4
- package/src/shared/IOwnable.sol +1 -1
- package/src/shared/IUUPSUpgradable.sol +1 -1
- package/src/shared/TestUtils.sol +8 -1
- package/src/test/EListTester.sol +171 -0
- package/src/test/FakeIncoInfra/FakeComputeServer.sol +2 -2
- package/src/test/FakeIncoInfra/FakeIncoInfraBase.sol +3 -3
- package/src/test/FakeIncoInfra/MockOpHandler.sol +7 -9
- package/src/test/FakeIncoInfra/MockRemoteAttestation.sol +2 -1
- package/src/test/FakeIncoInfra/getOpForSelector.sol +0 -2
- package/src/test/IncoTest.sol +17 -5
- package/src/test/OpsTest.sol +3 -2
- package/src/test/TEELifecycle/TEELifecycleMockTest.t.sol +85 -57
- package/src/test/TestDeploy.t.sol +73 -1
- package/src/test/TestFakeInfra.t.sol +32 -6
- package/src/test/TestLib.t.sol +986 -19
- package/src/test/TestReceive.t.sol +42 -0
- package/src/test/TestUpgrade.t.sol +34 -63
- package/src/version/IncoLightningConfig.sol +1 -1
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// SPDX-License-Identifier: No License
|
|
2
|
+
pragma solidity ^0.8;
|
|
3
|
+
|
|
4
|
+
import {ETypes, EOps, HANDLE_VERSION, SEP_ELIST_OP_RESULT} from "../../Types.sol";
|
|
5
|
+
import {HandleGeneration} from "./HandleGeneration.sol";
|
|
6
|
+
import {EListHandleMetadata} from "./EListHandleMetadata.sol";
|
|
7
|
+
|
|
8
|
+
/// @title EListHandleGeneration
|
|
9
|
+
/// @notice Generates deterministic handles for encrypted list operations
|
|
10
|
+
/// @dev Extends the base HandleGeneration with list-specific handle creation.
|
|
11
|
+
/// List handles incorporate additional metadata:
|
|
12
|
+
/// - List length (number of elements)
|
|
13
|
+
/// - Element type (encrypted type of individual elements)
|
|
14
|
+
/// - List marker (ETypes.List to identify as a list)
|
|
15
|
+
///
|
|
16
|
+
/// The handle is derived from:
|
|
17
|
+
/// - The operation type (EOps.NewEList for list creation)
|
|
18
|
+
/// - The packed input handles (for lists created from existing handles)
|
|
19
|
+
contract EListHandleGeneration is HandleGeneration, EListHandleMetadata {
|
|
20
|
+
|
|
21
|
+
/// @notice Creates a handle for a list operation result
|
|
22
|
+
/// @dev Generates a deterministic handle by hashing the operation and inputs,
|
|
23
|
+
/// then embedding list metadata (length, element type, list marker, version).
|
|
24
|
+
/// @param op The operation that produced this list (e.g., NewEList, Slice)
|
|
25
|
+
/// @param listType The encrypted type of individual list elements (euint8, euint64, etc.)
|
|
26
|
+
/// @param len The number of elements in the resulting list
|
|
27
|
+
/// @param packedInputs ABI-packed representation of the input handles
|
|
28
|
+
/// @return result The deterministic handle for this list
|
|
29
|
+
function createListResultHandle(EOps op, ETypes listType, uint16 len, bytes memory packedInputs)
|
|
30
|
+
internal
|
|
31
|
+
pure
|
|
32
|
+
returns (bytes32 result)
|
|
33
|
+
{
|
|
34
|
+
// Bind HANDLE_VERSION, listType (element type) and len into the preimage so the elist
|
|
35
|
+
// metadata stamped into bytes 27-29 is cryptographically committed, not just appended.
|
|
36
|
+
bytes32 baseHandle =
|
|
37
|
+
keccak256(abi.encodePacked(SEP_ELIST_OP_RESULT, HANDLE_VERSION, listType, len, op, packedInputs));
|
|
38
|
+
baseHandle = embedListLength(baseHandle, len);
|
|
39
|
+
baseHandle = embedListType(baseHandle, listType);
|
|
40
|
+
result = embedTypeVersion(baseHandle, ETypes.List);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/// @notice Creates a handle for a new list composed from individual encrypted handles
|
|
44
|
+
/// @dev This is the primary entry point for creating lists from existing encrypted values.
|
|
45
|
+
/// The handle is deterministically derived from the input handles, ensuring the same
|
|
46
|
+
/// inputs always produce the same list handle.
|
|
47
|
+
/// @param handles Array of encrypted value handles to combine into a list
|
|
48
|
+
/// @param listType The encrypted type of all elements (must be uniform)
|
|
49
|
+
/// @return newHandle The deterministic handle for the new list
|
|
50
|
+
function createListInputHandle(bytes32[] memory handles, ETypes listType)
|
|
51
|
+
internal
|
|
52
|
+
pure
|
|
53
|
+
returns (bytes32 newHandle)
|
|
54
|
+
{
|
|
55
|
+
newHandle = createListResultHandle(
|
|
56
|
+
EOps.NewEList,
|
|
57
|
+
listType,
|
|
58
|
+
uint16(handles.length),
|
|
59
|
+
abi.encodePacked(
|
|
60
|
+
//Since we're only dealing with handles, it should be sufficient to treat this operation as an operand on handles.
|
|
61
|
+
handles
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// SPDX-License-Identifier: No License
|
|
2
|
+
pragma solidity ^0.8;
|
|
3
|
+
|
|
4
|
+
import {ETypes} from "../../Types.sol";
|
|
5
|
+
import {IEListHandleMetadata} from "./interfaces/IEListHandleMetadata.sol";
|
|
6
|
+
|
|
7
|
+
/// @title EListHandleMetadata
|
|
8
|
+
/// @notice Utilities for embedding and extracting metadata from encrypted list handles
|
|
9
|
+
/// @dev Encrypted lists have additional metadata compared to scalar handles:
|
|
10
|
+
/// Handle structure (32 bytes / 256 bits):
|
|
11
|
+
/// - Bytes 0-26: Handle-specific data (hash, counters, etc.)
|
|
12
|
+
/// - Bytes 27-28: List length (uint16, max 65535 elements)
|
|
13
|
+
/// - Byte 29: Element type (ETypes enum value for individual elements)
|
|
14
|
+
/// - Byte 30: List type marker (identifies this as a list handle)
|
|
15
|
+
/// - Byte 31: Handle version
|
|
16
|
+
///
|
|
17
|
+
/// This allows efficient extraction of list metadata without external calls.
|
|
18
|
+
contract EListHandleMetadata is IEListHandleMetadata {
|
|
19
|
+
|
|
20
|
+
/// @notice Thrown when a handle contains an element type value outside the valid ETypes enum range.
|
|
21
|
+
/// @param raw The raw uint8 value extracted from the handle.
|
|
22
|
+
error InvalidListTypeValue(uint8 raw);
|
|
23
|
+
|
|
24
|
+
/// @notice Embeds the list length into a list handle
|
|
25
|
+
/// @dev Sets bytes 27-28 of the handle to the list length.
|
|
26
|
+
/// Clears existing length bits before setting new value.
|
|
27
|
+
/// @param prehandle The 32-byte handle before length embedding
|
|
28
|
+
/// @param len The number of elements in the list (max 65535)
|
|
29
|
+
/// @return result The handle with embedded list length
|
|
30
|
+
function embedListLength(bytes32 prehandle, uint16 len) internal pure returns (bytes32 result) {
|
|
31
|
+
// 27 and 28 bits are used for the list length
|
|
32
|
+
result = prehandle & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffff;
|
|
33
|
+
result = bytes32(uint256(result) | (uint256(len) << 24)); // append length
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/// @notice Extracts the list length from a list handle
|
|
37
|
+
/// @dev Reads bytes 27-28 of the handle as a uint16
|
|
38
|
+
/// @param handle The encrypted list handle to inspect
|
|
39
|
+
/// @return The number of elements in the list
|
|
40
|
+
function lengthOf(bytes32 handle) public pure returns (uint16) {
|
|
41
|
+
return uint16(uint256(handle) >> 24);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/// @notice Embeds the element type into a list handle
|
|
45
|
+
/// @dev Sets byte 29 of the handle to the element type.
|
|
46
|
+
/// This indicates the encrypted type of individual elements (euint8, euint64, etc.).
|
|
47
|
+
/// @param prehandle The 32-byte handle before type embedding
|
|
48
|
+
/// @param listType The encrypted type of list elements
|
|
49
|
+
/// @return result The handle with embedded element type
|
|
50
|
+
function embedListType(bytes32 prehandle, ETypes listType) internal pure returns (bytes32 result) {
|
|
51
|
+
result = prehandle & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff;
|
|
52
|
+
result = bytes32(uint256(result) | (uint256(listType) << 16)); // append element type
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/// @notice Extracts the element type from a list handle
|
|
56
|
+
/// @dev Reads byte 29 of the handle and casts to ETypes enum.
|
|
57
|
+
/// This is the type of individual elements, not the list container type.
|
|
58
|
+
/// Reverts with InvalidListTypeValue if the raw byte exceeds the valid ETypes range.
|
|
59
|
+
/// @param handle The encrypted list handle to inspect
|
|
60
|
+
/// @return The encrypted type of list elements (ebool, euint160, euint256, etc.)
|
|
61
|
+
function listTypeOf(bytes32 handle) internal pure returns (ETypes) {
|
|
62
|
+
uint8 raw = uint8(uint256(handle) >> 16);
|
|
63
|
+
require(raw <= uint8(type(ETypes).max), InvalidListTypeValue(raw));
|
|
64
|
+
return ETypes(raw);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
// SPDX-License-Identifier: No License
|
|
2
2
|
pragma solidity ^0.8;
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
ETypes,
|
|
6
|
+
EOps,
|
|
7
|
+
EVM_HOST_CHAIN_PREFIX,
|
|
8
|
+
HANDLE_INDEX,
|
|
9
|
+
HANDLE_VERSION,
|
|
10
|
+
SEP_INPUT_PREHANDLE,
|
|
11
|
+
SEP_INPUT_HANDLE,
|
|
12
|
+
SEP_OP_RESULT
|
|
13
|
+
} from "../../Types.sol";
|
|
5
14
|
import {HandleMetadata} from "./HandleMetadata.sol";
|
|
6
15
|
import {IHandleGeneration} from "./interfaces/IHandleGeneration.sol";
|
|
7
16
|
|
|
@@ -24,7 +33,12 @@ contract HandleGeneration is IHandleGeneration, HandleMetadata {
|
|
|
24
33
|
pure
|
|
25
34
|
returns (bytes32 generatedHandle)
|
|
26
35
|
{
|
|
27
|
-
|
|
36
|
+
// Trivial encrypt shares the op-result domain — uniqueness within the family is guaranteed
|
|
37
|
+
// by EOps.TrivialEncrypt's unique op byte, and the DS prefix prevents cross-family collisions.
|
|
38
|
+
// HANDLE_VERSION and handleType are folded into the preimage so the full handle is bound to
|
|
39
|
+
// its claimed metadata, not just stamped onto bytes 30/31 after the fact.
|
|
40
|
+
generatedHandle =
|
|
41
|
+
keccak256(abi.encodePacked(SEP_OP_RESULT, HANDLE_VERSION, handleType, EOps.TrivialEncrypt, plaintextBytes));
|
|
28
42
|
generatedHandle = embedTypeVersion(generatedHandle, handleType);
|
|
29
43
|
}
|
|
30
44
|
|
|
@@ -41,7 +55,7 @@ contract HandleGeneration is IHandleGeneration, HandleMetadata {
|
|
|
41
55
|
bytes memory ciphertext,
|
|
42
56
|
address user,
|
|
43
57
|
address contractAddress,
|
|
44
|
-
|
|
58
|
+
uint16 version,
|
|
45
59
|
ETypes inputType
|
|
46
60
|
) internal view returns (bytes32 generatedHandle) {
|
|
47
61
|
return getInputHandle(ciphertext, address(this), user, contractAddress, version, inputType);
|
|
@@ -61,17 +75,24 @@ contract HandleGeneration is IHandleGeneration, HandleMetadata {
|
|
|
61
75
|
address executorAddress,
|
|
62
76
|
address user,
|
|
63
77
|
address contractAddress,
|
|
64
|
-
|
|
78
|
+
uint16 version,
|
|
65
79
|
ETypes inputType
|
|
66
80
|
) internal view returns (bytes32 generatedHandle) {
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
|
|
81
|
+
// Prehandle is a legacy concept inherited by an earlier design where we had a preflight system for uploading ciphertexts to an L1 before they could be used.
|
|
82
|
+
// This is no longer the case and prehandle was mainly kept for compatibility and consistency with the intrernal design docs.
|
|
83
|
+
// To avoid calling keccak256 twice and save gas the prehandle concept will be dropped in a future PR.
|
|
84
|
+
bytes32 ctIndexHash = keccak256(
|
|
85
|
+
// We don't encode the length of the ciphertext because it's the only variable length field which should prevent collisions.
|
|
86
|
+
abi.encodePacked(SEP_INPUT_PREHANDLE, keccak256(ciphertext), HANDLE_INDEX)
|
|
87
|
+
);
|
|
70
88
|
bytes32 prehandle = embedIndexTypeVersion(ctIndexHash, inputType);
|
|
71
89
|
// We must also propagate the handle metadata to the final handle
|
|
72
90
|
generatedHandle = embedIndexTypeVersion(
|
|
73
91
|
keccak256(
|
|
74
92
|
abi.encodePacked(
|
|
93
|
+
SEP_INPUT_HANDLE,
|
|
94
|
+
HANDLE_VERSION,
|
|
95
|
+
inputType,
|
|
75
96
|
prehandle,
|
|
76
97
|
EVM_HOST_CHAIN_PREFIX,
|
|
77
98
|
block.chainid, // todo cache this
|
|
@@ -97,7 +118,9 @@ contract HandleGeneration is IHandleGeneration, HandleMetadata {
|
|
|
97
118
|
pure
|
|
98
119
|
returns (bytes32 generatedHandle)
|
|
99
120
|
{
|
|
100
|
-
generatedHandle = embedTypeVersion(
|
|
121
|
+
generatedHandle = embedTypeVersion(
|
|
122
|
+
keccak256(abi.encodePacked(SEP_OP_RESULT, HANDLE_VERSION, returnType, op, packedInputs)), returnType
|
|
123
|
+
);
|
|
101
124
|
}
|
|
102
125
|
|
|
103
126
|
}
|
|
@@ -12,6 +12,10 @@ import {HANDLE_VERSION, HANDLE_INDEX, ETypes} from "../../Types.sol";
|
|
|
12
12
|
/// - Byte 31: Handle version
|
|
13
13
|
contract HandleMetadata {
|
|
14
14
|
|
|
15
|
+
/// @notice Thrown when a handle contains a type value outside the valid ETypes enum range.
|
|
16
|
+
/// @param raw The raw uint8 value extracted from the handle.
|
|
17
|
+
error InvalidTypeValue(uint8 raw);
|
|
18
|
+
|
|
15
19
|
/// @notice Embeds the handle index, encrypted type, and protocol version into a prehandle
|
|
16
20
|
/// @dev Used for input handles where the index distinguishes the source.
|
|
17
21
|
/// Clears bytes 29-31 of the prehandle, then sets:
|
|
@@ -46,11 +50,14 @@ contract HandleMetadata {
|
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
/// @notice Extracts the encrypted type from a handle
|
|
49
|
-
/// @dev Reads byte 30 of the handle and casts to ETypes enum
|
|
53
|
+
/// @dev Reads byte 30 of the handle and casts to ETypes enum.
|
|
54
|
+
/// Reverts with InvalidTypeValue if the raw byte exceeds the valid ETypes range.
|
|
50
55
|
/// @param handle The encrypted value handle to inspect
|
|
51
|
-
/// @return The encrypted type (ebool,
|
|
56
|
+
/// @return The encrypted type (ebool, euint160, euint256, etc.)
|
|
52
57
|
function typeOf(bytes32 handle) internal pure returns (ETypes) {
|
|
53
|
-
|
|
58
|
+
uint8 raw = uint8(uint256(handle) >> 8);
|
|
59
|
+
require(raw <= uint8(type(ETypes).max), InvalidTypeValue(raw));
|
|
60
|
+
return ETypes(raw);
|
|
54
61
|
}
|
|
55
62
|
|
|
56
63
|
}
|
|
@@ -17,7 +17,7 @@ contract TestSignatureVerifier is TestUtils, SignatureVerifier {
|
|
|
17
17
|
// Helper function to create sorted signatures
|
|
18
18
|
// Takes a digest and an array of private keys, generates signatures,
|
|
19
19
|
// and returns them sorted by signer address in ascending order
|
|
20
|
-
function getSortedSignatures(bytes32 digest, uint256[] memory privKeys) internal returns (bytes[] memory) {
|
|
20
|
+
function getSortedSignatures(bytes32 digest, uint256[] memory privKeys) internal pure returns (bytes[] memory) {
|
|
21
21
|
bytes[] memory signatures = new bytes[](privKeys.length);
|
|
22
22
|
address[] memory signers = new address[](privKeys.length);
|
|
23
23
|
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// SPDX-License-Identifier: No License
|
|
2
|
+
pragma solidity ^0.8;
|
|
3
|
+
|
|
4
|
+
import {IncoTest} from "../../test/IncoTest.sol";
|
|
5
|
+
import {ElistTester} from "../../test/EListTester.sol";
|
|
6
|
+
import {ETypes, ListTooLong, elist, typeBitSize} from "../../Types.sol";
|
|
7
|
+
import {inco} from "../../Lib.sol";
|
|
8
|
+
import {FEE, BIT_FEE, Fee} from "../Fee.sol";
|
|
9
|
+
import {EList, MAX_LIST_LENGTH} from "../EList.sol";
|
|
10
|
+
import {VerifierAddressGetter} from "../primitives/VerifierAddressGetter.sol";
|
|
11
|
+
import {stdError} from "forge-std/StdError.sol";
|
|
12
|
+
|
|
13
|
+
contract ElistFeeTester is EList {
|
|
14
|
+
|
|
15
|
+
constructor() VerifierAddressGetter(address(0)) {}
|
|
16
|
+
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
contract TestEList is IncoTest {
|
|
20
|
+
|
|
21
|
+
ElistTester tester;
|
|
22
|
+
ElistFeeTester feeTester;
|
|
23
|
+
|
|
24
|
+
function setUp() public virtual override {
|
|
25
|
+
super.setUp();
|
|
26
|
+
tester = new ElistTester(inco);
|
|
27
|
+
vm.deal(address(tester), 100 ether);
|
|
28
|
+
vm.deal(address(this), 100 ether);
|
|
29
|
+
feeTester = new ElistFeeTester();
|
|
30
|
+
vm.deal(address(feeTester), 100 ether);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function _listRange(uint16 start, uint16 end, ETypes listType) internal returns (elist) {
|
|
34
|
+
return inco.listRange{value: uint256(end - start) * typeBitSize(listType) * BIT_FEE}(start, end, listType);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function _listAppend(elist list, bytes32 value) internal returns (elist) {
|
|
38
|
+
uint256 typeBits = typeBitSize(ETypes.Uint256);
|
|
39
|
+
return inco.listAppend{value: (uint256(inco.lengthOf(elist.unwrap(list))) * typeBits + typeBits) * BIT_FEE}(
|
|
40
|
+
list, value
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function _listInsert(elist list, bytes32 idx, bytes32 val) internal returns (elist) {
|
|
45
|
+
uint256 typeBits = typeBitSize(ETypes.Uint256);
|
|
46
|
+
return inco.listInsert{value: (uint256(inco.lengthOf(elist.unwrap(list))) * typeBits + typeBits) * BIT_FEE}(
|
|
47
|
+
list, idx, val
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function _listConcat(elist a, elist b) internal returns (elist) {
|
|
52
|
+
uint256 bitsA = uint256(inco.lengthOf(elist.unwrap(a))) * typeBitSize(ETypes.Uint256);
|
|
53
|
+
uint256 bitsB = uint256(inco.lengthOf(elist.unwrap(b))) * typeBitSize(ETypes.Uint256);
|
|
54
|
+
return inco.listConcat{value: (bitsA + bitsB) * BIT_FEE}(a, b);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function _newEList(bytes32[] memory handles, ETypes listType) internal returns (elist) {
|
|
58
|
+
return inco.newEList{value: uint256(handles.length) * typeBitSize(listType) * BIT_FEE}(handles, listType);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function testNewElistFromInputs() public {
|
|
62
|
+
createList();
|
|
63
|
+
// todo test read the created list
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function testListAppend() public {
|
|
67
|
+
createList();
|
|
68
|
+
bytes memory ctValue = fakePrepareEuint256Ciphertext(40, address(this), address(tester));
|
|
69
|
+
tester.listAppend(ctValue);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function createList() internal returns (elist list) {
|
|
73
|
+
bytes[] memory inputs = new bytes[](3);
|
|
74
|
+
inputs[0] = fakePrepareEuint256Ciphertext(10, address(this), address(tester));
|
|
75
|
+
inputs[1] = fakePrepareEuint256Ciphertext(20, address(this), address(tester));
|
|
76
|
+
inputs[2] = fakePrepareEuint256Ciphertext(30, address(this), address(tester));
|
|
77
|
+
list = tester.newEList(inputs, ETypes.Uint256, address(this));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function testRevertsOnBadFeeAmount() public {
|
|
81
|
+
// Construct a handle with length=1, type=Uint256 so fee = 1 * 256 * BIT_FEE
|
|
82
|
+
elist nonZeroList = elist.wrap(bytes32((uint256(1) << 24) | (uint256(uint8(ETypes.Uint256)) << 16)));
|
|
83
|
+
uint256 correctFee = 256 * BIT_FEE;
|
|
84
|
+
|
|
85
|
+
// should fail if no fee
|
|
86
|
+
vm.expectRevert(Fee.FeeNotPaid.selector);
|
|
87
|
+
feeTester.listShuffle(nonZeroList);
|
|
88
|
+
|
|
89
|
+
// should fail if not enough fee
|
|
90
|
+
vm.expectRevert(Fee.FeeNotPaid.selector);
|
|
91
|
+
feeTester.listShuffle{value: correctFee - 1}(nonZeroList);
|
|
92
|
+
|
|
93
|
+
// should fail if too much fee
|
|
94
|
+
vm.expectRevert(Fee.FeeNotPaid.selector);
|
|
95
|
+
feeTester.listShuffle{value: correctFee + 1}(nonZeroList);
|
|
96
|
+
|
|
97
|
+
// newEList(inputs): uses payingElistFee, so 3 * 256 * BIT_FEE needed, sending less
|
|
98
|
+
vm.expectRevert(Fee.FeeNotPaid.selector);
|
|
99
|
+
bytes[] memory inputs = new bytes[](3);
|
|
100
|
+
feeTester.newEList{value: 3 * 256 * BIT_FEE - 1}(inputs, ETypes.Uint256, address(this));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function testListAppend_SucceedsAtMaxLength() public {
|
|
104
|
+
elist almostMaxList = _listRange(0, MAX_LIST_LENGTH - 1, ETypes.Uint256);
|
|
105
|
+
|
|
106
|
+
bytes32 validHandle = inco.listGet(almostMaxList, 0);
|
|
107
|
+
|
|
108
|
+
elist result = _listAppend(almostMaxList, validHandle);
|
|
109
|
+
assert(elist.unwrap(result) != bytes32(0));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function testListInsert_SucceedsAtMaxLength() public {
|
|
113
|
+
elist almostMaxList = _listRange(0, MAX_LIST_LENGTH - 1, ETypes.Uint256);
|
|
114
|
+
|
|
115
|
+
// Get valid handles from the list (listGet returns handles with transient permissions)
|
|
116
|
+
bytes32 validIndex = inco.listGet(almostMaxList, 0);
|
|
117
|
+
bytes32 validValue = inco.listGet(almostMaxList, 1);
|
|
118
|
+
|
|
119
|
+
elist result = _listInsert(almostMaxList, validIndex, validValue);
|
|
120
|
+
assert(elist.unwrap(result) != bytes32(0));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function testListConcat_SucceedsAtMaxLength() public {
|
|
124
|
+
uint16 half = MAX_LIST_LENGTH / 2;
|
|
125
|
+
uint16 otherHalf = MAX_LIST_LENGTH - half;
|
|
126
|
+
elist list1 = _listRange(0, half, ETypes.Uint256);
|
|
127
|
+
elist list2 = _listRange(0, otherHalf, ETypes.Uint256);
|
|
128
|
+
|
|
129
|
+
// Should succeed
|
|
130
|
+
elist combined = _listConcat(list1, list2);
|
|
131
|
+
assert(elist.unwrap(combined) != bytes32(0));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function testListRange_SucceedsAtMaxLength() public {
|
|
135
|
+
elist maxList = _listRange(0, MAX_LIST_LENGTH, ETypes.Uint256);
|
|
136
|
+
assert(elist.unwrap(maxList) != bytes32(0));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ==================== Overflow Tests ====================
|
|
140
|
+
// These tests verify that exceeding MAX_LIST_LENGTH reverts appropriately.
|
|
141
|
+
// Operations use uint16 arithmetic which auto-reverts on overflow in Solidity 0.8+.
|
|
142
|
+
|
|
143
|
+
function testListAppend_RevertsOnOverflow() public {
|
|
144
|
+
elist maxList = _listRange(0, MAX_LIST_LENGTH, ETypes.Uint256);
|
|
145
|
+
|
|
146
|
+
bytes32 validHandle = inco.listGet(maxList, 0);
|
|
147
|
+
|
|
148
|
+
// Appending to a max-length list should revert with arithmetic overflow
|
|
149
|
+
// Fee: (65535*256 + 256) * BIT_FEE = 65536*32*FEE
|
|
150
|
+
uint256 typeBits = typeBitSize(ETypes.Uint256);
|
|
151
|
+
vm.expectRevert(stdError.arithmeticError);
|
|
152
|
+
inco.listAppend{value: (uint256(MAX_LIST_LENGTH) * typeBits + typeBits) * BIT_FEE}(maxList, validHandle);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function testListInsert_RevertsOnOverflow() public {
|
|
156
|
+
elist maxList = _listRange(0, MAX_LIST_LENGTH, ETypes.Uint256);
|
|
157
|
+
|
|
158
|
+
bytes32 validIndex = inco.listGet(maxList, 0);
|
|
159
|
+
bytes32 validValue = inco.listGet(maxList, 1);
|
|
160
|
+
|
|
161
|
+
// Inserting into a max-length list should revert with arithmetic overflow
|
|
162
|
+
uint256 typeBits = typeBitSize(ETypes.Uint256);
|
|
163
|
+
vm.expectRevert(stdError.arithmeticError);
|
|
164
|
+
inco.listInsert{value: (uint256(MAX_LIST_LENGTH) * typeBits + typeBits) * BIT_FEE}(
|
|
165
|
+
maxList, validIndex, validValue
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function testListConcat_RevertsOnOverflow() public {
|
|
170
|
+
uint16 half = MAX_LIST_LENGTH / 2 + 1;
|
|
171
|
+
elist list1 = _listRange(0, half, ETypes.Uint256);
|
|
172
|
+
elist list2 = _listRange(0, half, ETypes.Uint256);
|
|
173
|
+
|
|
174
|
+
// Concatenating should revert with arithmetic overflow
|
|
175
|
+
uint256 bitsPerList = uint256(half) * typeBitSize(ETypes.Uint256);
|
|
176
|
+
vm.expectRevert(stdError.arithmeticError);
|
|
177
|
+
inco.listConcat{value: (bitsPerList + bitsPerList) * BIT_FEE}(list1, list2);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function testNewEList_RevertsOnTooManyHandles() public {
|
|
181
|
+
uint256 tooMany = uint256(MAX_LIST_LENGTH) + 1;
|
|
182
|
+
bytes32[] memory handles = new bytes32[](tooMany);
|
|
183
|
+
|
|
184
|
+
// Fee check runs before length check, so we must pay the required fee
|
|
185
|
+
uint256 requiredFee = tooMany * typeBitSize(ETypes.Uint256) * BIT_FEE;
|
|
186
|
+
|
|
187
|
+
// Should revert with ListTooLong error
|
|
188
|
+
vm.expectRevert(abi.encodeWithSelector(ListTooLong.selector, uint32(tooMany), MAX_LIST_LENGTH));
|
|
189
|
+
inco.newEList{value: requiredFee}(handles, ETypes.Uint256);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function testNewEList_RevertsOnTooManyInputs() public {
|
|
193
|
+
uint256 tooMany = uint256(MAX_LIST_LENGTH) + 1;
|
|
194
|
+
bytes[] memory inputs = new bytes[](tooMany);
|
|
195
|
+
|
|
196
|
+
// Fee check runs before length check, so we must pay the required fee
|
|
197
|
+
uint256 requiredFee = tooMany * typeBitSize(ETypes.Uint256) * BIT_FEE;
|
|
198
|
+
|
|
199
|
+
// Should revert with ListTooLong error
|
|
200
|
+
vm.expectRevert(abi.encodeWithSelector(ListTooLong.selector, uint32(tooMany), MAX_LIST_LENGTH));
|
|
201
|
+
inco.newEList{value: requiredFee}(inputs, ETypes.Uint256, address(this));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function testNewEListFromHandles() public {
|
|
205
|
+
elist sourceList = _listRange(0, 3, ETypes.Uint256);
|
|
206
|
+
|
|
207
|
+
// Extract handles from the source list
|
|
208
|
+
bytes32[] memory handles = new bytes32[](3);
|
|
209
|
+
handles[0] = inco.listGet(sourceList, 0);
|
|
210
|
+
handles[1] = inco.listGet(sourceList, 1);
|
|
211
|
+
handles[2] = inco.listGet(sourceList, 2);
|
|
212
|
+
|
|
213
|
+
// Create a new list from these handles
|
|
214
|
+
elist newList = _newEList(handles, ETypes.Uint256);
|
|
215
|
+
assert(elist.unwrap(newList) != bytes32(0));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
}
|
|
@@ -22,6 +22,7 @@ import {VerifierAddressGetter} from "../primitives/VerifierAddressGetter.sol";
|
|
|
22
22
|
import {FEE} from "../Fee.sol";
|
|
23
23
|
import {HandleAlreadyExists} from "../../Errors.sol";
|
|
24
24
|
import {ExternalHandleDoesNotMatchComputedHandle} from "../EncryptedInput.sol";
|
|
25
|
+
import {IEncryptedInput} from "../interfaces/IEncryptedInput.sol";
|
|
25
26
|
|
|
26
27
|
contract TestHandleMetadata is
|
|
27
28
|
EIP712,
|
|
@@ -32,7 +33,9 @@ contract TestHandleMetadata is
|
|
|
32
33
|
EncryptedInput
|
|
33
34
|
{
|
|
34
35
|
|
|
35
|
-
constructor() EIP712("", "") VerifierAddressGetter(address(0)) {
|
|
36
|
+
constructor() EIP712("", "") VerifierAddressGetter(address(0)) {
|
|
37
|
+
_setAcceptedVersion(2, true);
|
|
38
|
+
}
|
|
36
39
|
|
|
37
40
|
function testTypeAssignment() public pure {
|
|
38
41
|
bytes32 someHandle = bytes32(keccak256("someHandle"));
|
|
@@ -105,16 +108,16 @@ contract TestHandleMetadata is
|
|
|
105
108
|
{
|
|
106
109
|
// We need a single word here to get correct encoding
|
|
107
110
|
bytes memory ciphertext = abi.encode(word);
|
|
111
|
+
uint16 version = 2; // version - X-Wing
|
|
108
112
|
bytes32 handle = getInputHandle(
|
|
109
113
|
ciphertext,
|
|
110
114
|
address(this),
|
|
111
115
|
user,
|
|
112
116
|
contractAddress,
|
|
113
|
-
|
|
114
|
-
/* unspecified */
|
|
117
|
+
version, // version - X-Wing
|
|
115
118
|
inputType
|
|
116
119
|
);
|
|
117
|
-
input = abi.encodePacked(
|
|
120
|
+
input = abi.encodePacked(uint32(version), abi.encode(handle, ciphertext));
|
|
118
121
|
}
|
|
119
122
|
|
|
120
123
|
// ============ Tests for HandleGeneration functions ============
|
|
@@ -155,6 +158,53 @@ contract TestHandleMetadata is
|
|
|
155
158
|
return newInputNotPaying(input, user, inputType);
|
|
156
159
|
}
|
|
157
160
|
|
|
161
|
+
function testNewInputUnwhitelistedVersion() public {
|
|
162
|
+
address self = address(this);
|
|
163
|
+
bytes32 ciphertextData = keccak256(abi.encodePacked("unwhitelisted_version"));
|
|
164
|
+
bytes memory ciphertext = abi.encode(ciphertextData);
|
|
165
|
+
uint16 unwhitelistedVersion = 0;
|
|
166
|
+
bytes32 handle =
|
|
167
|
+
getInputHandle(ciphertext, address(this), self, address(this), unwhitelistedVersion, ETypes.Uint256);
|
|
168
|
+
bytes memory badInput = abi.encodePacked(uint32(unwhitelistedVersion), abi.encode(handle, ciphertext));
|
|
169
|
+
|
|
170
|
+
vm.expectRevert(abi.encodeWithSelector(IEncryptedInput.InvalidInputVersion.selector, unwhitelistedVersion));
|
|
171
|
+
this.exposedNewInputNotPaying(badInput, self, ETypes.Uint256);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function testNewInputVersionAddedThenRemoved() public {
|
|
175
|
+
address self = address(this);
|
|
176
|
+
bytes32 ciphertextData = keccak256(abi.encodePacked("version_toggle"));
|
|
177
|
+
bytes memory ciphertext = abi.encode(ciphertextData);
|
|
178
|
+
uint16 version = 3;
|
|
179
|
+
|
|
180
|
+
bytes32 handle = getInputHandle(ciphertext, address(this), self, address(this), version, ETypes.Uint256);
|
|
181
|
+
bytes memory input = abi.encodePacked(uint32(version), abi.encode(handle, ciphertext));
|
|
182
|
+
|
|
183
|
+
// Version 3 is not accepted yet
|
|
184
|
+
vm.expectRevert(abi.encodeWithSelector(IEncryptedInput.InvalidInputVersion.selector, version));
|
|
185
|
+
this.exposedNewInputNotPaying(input, self, ETypes.Uint256);
|
|
186
|
+
|
|
187
|
+
// Whitelist version 3
|
|
188
|
+
_setAcceptedVersion(3, true);
|
|
189
|
+
|
|
190
|
+
// Now it should succeed
|
|
191
|
+
bytes32 resultHandle = this.exposedNewInputNotPaying(input, self, ETypes.Uint256);
|
|
192
|
+
assert(typeOf(resultHandle) == ETypes.Uint256);
|
|
193
|
+
|
|
194
|
+
// Remove version 3
|
|
195
|
+
_setAcceptedVersion(3, false);
|
|
196
|
+
|
|
197
|
+
// Use different ciphertext to avoid HandleAlreadyExists
|
|
198
|
+
bytes32 ciphertextData2 = keccak256(abi.encodePacked("version_toggle_2"));
|
|
199
|
+
bytes memory ciphertext2 = abi.encode(ciphertextData2);
|
|
200
|
+
bytes32 handle2 = getInputHandle(ciphertext2, address(this), self, address(this), version, ETypes.Uint256);
|
|
201
|
+
bytes memory input2 = abi.encodePacked(uint32(version), abi.encode(handle2, ciphertext2));
|
|
202
|
+
|
|
203
|
+
// Should revert again
|
|
204
|
+
vm.expectRevert(abi.encodeWithSelector(IEncryptedInput.InvalidInputVersion.selector, version));
|
|
205
|
+
this.exposedNewInputNotPaying(input2, self, ETypes.Uint256);
|
|
206
|
+
}
|
|
207
|
+
|
|
158
208
|
function testNewInputNotPaying() public {
|
|
159
209
|
address self = address(this);
|
|
160
210
|
bytes32 ciphertextData = keccak256(abi.encodePacked("notpaying_ciphertext"));
|
|
@@ -172,10 +222,10 @@ contract TestHandleMetadata is
|
|
|
172
222
|
returns (bytes memory input)
|
|
173
223
|
{
|
|
174
224
|
bytes memory ciphertext = abi.encode(word);
|
|
175
|
-
|
|
225
|
+
uint16 version = 2; // version - X-Wing
|
|
176
226
|
// For external calls via this., msg.sender is address(this)
|
|
177
227
|
bytes32 handle = getInputHandle(ciphertext, address(this), user, address(this), version, inputType);
|
|
178
|
-
input = abi.encodePacked(version, abi.encode(handle, ciphertext));
|
|
228
|
+
input = abi.encodePacked(uint32(version), abi.encode(handle, ciphertext));
|
|
179
229
|
}
|
|
180
230
|
|
|
181
231
|
// ============ Tests for EncryptedInput error branches ============
|
|
@@ -184,7 +234,7 @@ contract TestHandleMetadata is
|
|
|
184
234
|
address self = address(this);
|
|
185
235
|
// Input less than 64 bytes should revert
|
|
186
236
|
bytes memory shortInput = hex"deadbeef";
|
|
187
|
-
vm.expectRevert(
|
|
237
|
+
vm.expectRevert(abi.encodeWithSelector(IEncryptedInput.InputLengthTooShort.selector, shortInput.length));
|
|
188
238
|
this.exposedNewInputNotPaying(shortInput, self, ETypes.Uint256);
|
|
189
239
|
}
|
|
190
240
|
|
|
@@ -194,8 +244,8 @@ contract TestHandleMetadata is
|
|
|
194
244
|
bytes memory ciphertext = abi.encode(ciphertextData);
|
|
195
245
|
// Create input with wrong handle (just a random bytes32)
|
|
196
246
|
bytes32 wrongHandle = bytes32(uint256(12345));
|
|
197
|
-
|
|
198
|
-
bytes memory badInput = abi.encodePacked(version, abi.encode(wrongHandle, ciphertext));
|
|
247
|
+
uint16 version = 2; // version - X-Wing
|
|
248
|
+
bytes memory badInput = abi.encodePacked(uint32(version), abi.encode(wrongHandle, ciphertext));
|
|
199
249
|
|
|
200
250
|
// Compute the expected handle for the error message
|
|
201
251
|
bytes32 expectedHandle = getInputHandle(ciphertext, address(this), self, address(this), version, ETypes.Uint256);
|
|
@@ -234,35 +284,35 @@ contract TestHandleMetadata is
|
|
|
234
284
|
function testEBitAndTypeMismatch() public {
|
|
235
285
|
euint256 a = this.asEuint256(42);
|
|
236
286
|
ebool b = this.asEbool(true);
|
|
237
|
-
// Error: UnexpectedType(
|
|
238
|
-
// With lhs=Uint256, rhs=Bool: UnexpectedType(
|
|
287
|
+
// Error: UnexpectedType(typeOf(rhs), typeToBitMask(lhsType))
|
|
288
|
+
// With lhs=Uint256, rhs=Bool: UnexpectedType(Bool, typeToBitMask(Uint256))
|
|
239
289
|
vm.expectRevert(
|
|
240
290
|
abi.encodeWithSelector(
|
|
241
|
-
EncryptedOperations.UnexpectedType.selector, ETypes.
|
|
291
|
+
EncryptedOperations.UnexpectedType.selector, ETypes.Bool, typeToBitMask(ETypes.Uint256)
|
|
242
292
|
)
|
|
243
293
|
);
|
|
244
294
|
this.eBitAnd(euint256.unwrap(a), ebool.unwrap(b));
|
|
245
295
|
}
|
|
246
296
|
|
|
247
|
-
/// @notice Test eBitOr with mismatched types
|
|
297
|
+
/// @notice Test eBitOr with mismatched types
|
|
248
298
|
function testEBitOrTypeMismatch() public {
|
|
249
299
|
euint256 a = this.asEuint256(42);
|
|
250
300
|
ebool b = this.asEbool(true);
|
|
251
301
|
vm.expectRevert(
|
|
252
302
|
abi.encodeWithSelector(
|
|
253
|
-
EncryptedOperations.UnexpectedType.selector, ETypes.
|
|
303
|
+
EncryptedOperations.UnexpectedType.selector, ETypes.Bool, typeToBitMask(ETypes.Uint256)
|
|
254
304
|
)
|
|
255
305
|
);
|
|
256
306
|
this.eBitOr(euint256.unwrap(a), ebool.unwrap(b));
|
|
257
307
|
}
|
|
258
308
|
|
|
259
|
-
/// @notice Test eBitXor with mismatched types
|
|
309
|
+
/// @notice Test eBitXor with mismatched types
|
|
260
310
|
function testEBitXorTypeMismatch() public {
|
|
261
311
|
euint256 a = this.asEuint256(42);
|
|
262
312
|
ebool b = this.asEbool(true);
|
|
263
313
|
vm.expectRevert(
|
|
264
314
|
abi.encodeWithSelector(
|
|
265
|
-
EncryptedOperations.UnexpectedType.selector, ETypes.
|
|
315
|
+
EncryptedOperations.UnexpectedType.selector, ETypes.Bool, typeToBitMask(ETypes.Uint256)
|
|
266
316
|
)
|
|
267
317
|
);
|
|
268
318
|
this.eBitXor(euint256.unwrap(a), ebool.unwrap(b));
|
|
@@ -276,13 +326,6 @@ contract TestHandleMetadata is
|
|
|
276
326
|
this.eCast(euint256.unwrap(a), unsupportedType);
|
|
277
327
|
}
|
|
278
328
|
|
|
279
|
-
/// @notice Test eRand with unsupported type (line 282)
|
|
280
|
-
function testERandUnsupportedType() public {
|
|
281
|
-
ETypes unsupportedType = ETypes.Uint4UNSUPPORTED;
|
|
282
|
-
vm.expectRevert(abi.encodeWithSelector(EncryptedOperations.UnsupportedType.selector, unsupportedType));
|
|
283
|
-
this.eRand{value: FEE}(unsupportedType);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
329
|
/// @notice Test eRandBounded with unsupported type (line 291)
|
|
287
330
|
function testERandBoundedUnsupportedType() public {
|
|
288
331
|
euint256 bound = this.asEuint256(100);
|