@cofhe/mock-contracts 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,432 @@
1
+ // SPDX-License-Identifier: UNLICENSED
2
+ pragma solidity ^0.8.13;
3
+
4
+ import { Test } from 'forge-std/Test.sol';
5
+ import { MockTaskManager } from '../MockTaskManager.sol';
6
+ import { MockACL } from '../MockACL.sol';
7
+ import '@fhenixprotocol/cofhe-contracts/FHE.sol';
8
+ import { MockZkVerifier } from '../MockZkVerifier.sol';
9
+ import { MockZkVerifierSigner } from './MockZkVerifierSigner.sol';
10
+ import { MessageHashUtils } from '@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol';
11
+ import { Permission, PermissionUtils } from '../Permissioned.sol';
12
+ import { MockQueryDecrypter } from '../MockQueryDecrypter.sol';
13
+ import { SIGNER_ADDRESS } from '../MockCoFHE.sol';
14
+
15
+ abstract contract CoFheTest is Test {
16
+ MockTaskManager public mockTaskManager;
17
+ MockZkVerifier public mockZkVerifier;
18
+ MockZkVerifierSigner public mockZkVerifierSigner;
19
+ MockACL public mockAcl;
20
+ MockQueryDecrypter public mockQueryDecrypter;
21
+
22
+ address constant QUERY_DECRYPTER_ADDRESS = address(512);
23
+ address constant ZK_VERIFIER_ADDRESS = address(256);
24
+ address constant ZK_VERIFIER_SIGNER_ADDRESS = address(257);
25
+ address public constant ACL_ADDRESS = 0xa6Ea4b5291d044D93b73b3CFf3109A1128663E8B;
26
+
27
+ bool private _log = false;
28
+
29
+ address public constant TM_ADMIN = address(128);
30
+
31
+ constructor() {
32
+ etchFhenixMocks();
33
+ }
34
+
35
+ function setLog(bool log) internal {
36
+ _log = log;
37
+ }
38
+
39
+ // SETUP
40
+
41
+ function etchFhenixMocks() internal {
42
+ // Override chain id (uncomment to enable)
43
+ // vm.chainId(421614); // Arb Sepolia
44
+ // vm.chainId(31337); // Anvil
45
+ vm.chainId(420105); // Localfhenix host 1
46
+
47
+ // TASK MANAGER
48
+ deployCodeTo('MockTaskManager.sol:MockTaskManager', TASK_MANAGER_ADDRESS);
49
+ mockTaskManager = MockTaskManager(TASK_MANAGER_ADDRESS);
50
+ mockTaskManager.initialize(TM_ADMIN);
51
+ vm.label(address(mockTaskManager), 'MockTaskManager');
52
+
53
+ vm.startPrank(TM_ADMIN);
54
+ mockTaskManager.setSecurityZoneMin(0);
55
+ mockTaskManager.setSecurityZoneMax(1);
56
+ mockTaskManager.setVerifierSigner(SIGNER_ADDRESS);
57
+ vm.stopPrank();
58
+
59
+ // ACL
60
+ deployCodeTo('MockACL.sol:MockACL', abi.encode(TM_ADMIN), ACL_ADDRESS);
61
+
62
+ mockAcl = MockACL(ACL_ADDRESS);
63
+ vm.label(address(mockAcl), 'MockACL');
64
+
65
+ vm.prank(TM_ADMIN);
66
+ mockTaskManager.setACLContract(address(mockAcl));
67
+
68
+ // ZK VERIFIER
69
+
70
+ deployCodeTo('MockZkVerifier.sol:MockZkVerifier', ZK_VERIFIER_ADDRESS);
71
+ mockZkVerifier = MockZkVerifier(ZK_VERIFIER_ADDRESS);
72
+ vm.label(address(mockZkVerifier), 'MockZkVerifier');
73
+
74
+ deployCodeTo('MockZkVerifierSigner.sol:MockZkVerifierSigner', ZK_VERIFIER_SIGNER_ADDRESS);
75
+ mockZkVerifierSigner = MockZkVerifierSigner(ZK_VERIFIER_SIGNER_ADDRESS);
76
+ vm.label(address(mockZkVerifierSigner), 'MockZkVerifierSigner');
77
+
78
+ // QUERY DECRYPTER
79
+
80
+ deployCodeTo('MockQueryDecrypter.sol:MockQueryDecrypter', QUERY_DECRYPTER_ADDRESS);
81
+ mockQueryDecrypter = MockQueryDecrypter(QUERY_DECRYPTER_ADDRESS);
82
+ vm.label(address(mockQueryDecrypter), 'MockQueryDecrypter');
83
+ mockQueryDecrypter.initialize(TASK_MANAGER_ADDRESS, address(mockAcl));
84
+
85
+ // SET LOG OPS
86
+
87
+ mockTaskManager.setLogOps(_log);
88
+ }
89
+
90
+ // EXPOSED FUNCTIONS
91
+
92
+ /**
93
+ * @notice Returns the value of a given encrypted value from the mocked task manager.
94
+ * @param ctHash Hash of the encrypted value.
95
+ * @return Value of the encrypted value.
96
+ */
97
+ function mockStorage(uint256 ctHash) public view returns (uint256) {
98
+ return mockTaskManager.mockStorage(ctHash);
99
+ }
100
+
101
+ /**
102
+ * @notice Returns whether a given encrypted value is in the mocked task manager.
103
+ * @param ctHash Hash of the encrypted value.
104
+ * @return Whether the encrypted value is in the mocked task manager.
105
+ */
106
+ function inMockStorage(uint256 ctHash) public view returns (bool) {
107
+ return mockTaskManager.inMockStorage(ctHash);
108
+ }
109
+
110
+ // ASSERTIONS
111
+
112
+ // Hash
113
+
114
+ /**
115
+ * @notice Asserts that the value of a given encrypted value is equal to the expected value.
116
+ * @param ctHash Hash of the encrypted value.
117
+ * @param value Expected value.
118
+ */
119
+ function assertHashValue(uint256 ctHash, uint256 value) public view {
120
+ assertEq(mockTaskManager.inMockStorage(ctHash), true);
121
+ assertEq(mockTaskManager.mockStorage(ctHash), value);
122
+ }
123
+ function assertHashValue(uint256 ctHash, uint256 value, string memory message) public view {
124
+ assertEq(mockTaskManager.inMockStorage(ctHash), true, message);
125
+ assertEq(mockTaskManager.mockStorage(ctHash), value, message);
126
+ }
127
+
128
+ // Encrypted types (no message)
129
+
130
+ function assertHashValue(ebool eValue, bool value) public view {
131
+ assertHashValue(ebool.unwrap(eValue), value ? 1 : 0);
132
+ }
133
+ function assertHashValue(euint8 eValue, uint8 value) public view {
134
+ assertHashValue(euint8.unwrap(eValue), value);
135
+ }
136
+ function assertHashValue(euint16 eValue, uint16 value) public view {
137
+ assertHashValue(euint16.unwrap(eValue), value);
138
+ }
139
+ function assertHashValue(euint32 eValue, uint32 value) public view {
140
+ assertHashValue(euint32.unwrap(eValue), value);
141
+ }
142
+ function assertHashValue(euint64 eValue, uint64 value) public view {
143
+ assertHashValue(euint64.unwrap(eValue), value);
144
+ }
145
+ function assertHashValue(euint128 eValue, uint128 value) public view {
146
+ assertHashValue(euint128.unwrap(eValue), value);
147
+ }
148
+ function assertHashValue(eaddress eValue, address value) public view {
149
+ assertHashValue(eaddress.unwrap(eValue), uint256(uint160(value)));
150
+ }
151
+
152
+ // Encrypted types (with message)
153
+
154
+ function assertHashValue(ebool eValue, bool value, string memory message) public view {
155
+ assertHashValue(ebool.unwrap(eValue), value ? 1 : 0, message);
156
+ }
157
+ function assertHashValue(euint8 eValue, uint8 value, string memory message) public view {
158
+ assertHashValue(euint8.unwrap(eValue), value, message);
159
+ }
160
+ function assertHashValue(euint16 eValue, uint16 value, string memory message) public view {
161
+ assertHashValue(euint16.unwrap(eValue), value, message);
162
+ }
163
+ function assertHashValue(euint32 eValue, uint32 value, string memory message) public view {
164
+ assertHashValue(euint32.unwrap(eValue), value, message);
165
+ }
166
+ function assertHashValue(euint64 eValue, uint64 value, string memory message) public view {
167
+ assertHashValue(euint64.unwrap(eValue), value, message);
168
+ }
169
+ function assertHashValue(euint128 eValue, uint128 value, string memory message) public view {
170
+ assertHashValue(euint128.unwrap(eValue), value, message);
171
+ }
172
+ function assertHashValue(eaddress eValue, address value, string memory message) public view {
173
+ assertHashValue(eaddress.unwrap(eValue), uint256(uint160(value)), message);
174
+ }
175
+
176
+ // UTILS
177
+
178
+ // struct EncryptedInput {
179
+ // uint256 ctHash;
180
+ // uint8 securityZone;
181
+ // uint8 utype;
182
+ // bytes signature;
183
+ // }
184
+
185
+ function createEncryptedInput(
186
+ uint8 utype,
187
+ uint256 value,
188
+ uint8 securityZone,
189
+ address sender
190
+ ) internal returns (EncryptedInput memory input) {
191
+ // Create encrypted input (also inserts the encrypted input into the mock storage)
192
+ input = mockZkVerifier.zkVerify(value, utype, sender, securityZone, block.chainid);
193
+
194
+ // Sign input
195
+ input = mockZkVerifierSigner.zkVerifySign(input, sender);
196
+ }
197
+
198
+ // Derived functions that use the generic create
199
+
200
+ /**
201
+ * @notice Creates an InEbool to be used as FHE input. Value is stored in MockCoFHE contract, hash is a pointer to that value.
202
+ * @param value Value to encrypt.
203
+ * @param securityZone Security zone of the encrypted value.
204
+ * @return InEbool.
205
+ */
206
+ function createInEbool(bool value, uint8 securityZone, address sender) public returns (InEbool memory) {
207
+ return
208
+ abi.decode(abi.encode(createEncryptedInput(Utils.EBOOL_TFHE, value ? 1 : 0, securityZone, sender)), (InEbool));
209
+ }
210
+
211
+ /**
212
+ * @notice Creates an InEuint8 to be used as FHE input. Value is stored in MockCoFHE contract, hash is a pointer to that value.
213
+ * @param value Value to encrypt.
214
+ * @param securityZone Security zone of the encrypted value.
215
+ * @return InEuint8.
216
+ */
217
+ function createInEuint8(uint8 value, uint8 securityZone, address sender) public returns (InEuint8 memory) {
218
+ return abi.decode(abi.encode(createEncryptedInput(Utils.EUINT8_TFHE, value, securityZone, sender)), (InEuint8));
219
+ }
220
+
221
+ /**
222
+ * @notice Creates an InEuint16 to be used as FHE input. Value is stored in MockCoFHE contract, hash is a pointer to that value.
223
+ * @param value Value to encrypt.
224
+ * @param securityZone Security zone of the encrypted value.
225
+ * @return InEuint16.
226
+ */
227
+ function createInEuint16(uint16 value, uint8 securityZone, address sender) public returns (InEuint16 memory) {
228
+ return abi.decode(abi.encode(createEncryptedInput(Utils.EUINT16_TFHE, value, securityZone, sender)), (InEuint16));
229
+ }
230
+
231
+ /**
232
+ * @notice Creates an InEuint32 to be used as FHE input. Value is stored in MockCoFHE contract, hash is a pointer to that value.
233
+ * @param value Value to encrypt.
234
+ * @param securityZone Security zone of the encrypted value.
235
+ * @return InEuint32.
236
+ */
237
+ function createInEuint32(uint32 value, uint8 securityZone, address sender) public returns (InEuint32 memory) {
238
+ return abi.decode(abi.encode(createEncryptedInput(Utils.EUINT32_TFHE, value, securityZone, sender)), (InEuint32));
239
+ }
240
+
241
+ /**
242
+ * @notice Creates an InEuint64 to be used as FHE input. Value is stored in MockCoFHE contract, hash is a pointer to that value.
243
+ * @param value Value to encrypt.
244
+ * @param securityZone Security zone of the encrypted value.
245
+ * @return InEuint64.
246
+ */
247
+ function createInEuint64(uint64 value, uint8 securityZone, address sender) public returns (InEuint64 memory) {
248
+ return abi.decode(abi.encode(createEncryptedInput(Utils.EUINT64_TFHE, value, securityZone, sender)), (InEuint64));
249
+ }
250
+
251
+ /**
252
+ * @notice Creates an InEuint128 to be used as FHE input. Value is stored in MockCoFHE contract, hash is a pointer to that value.
253
+ * @param value Value to encrypt.
254
+ * @param securityZone Security zone of the encrypted value.
255
+ * @return InEuint128.
256
+ */
257
+ function createInEuint128(uint128 value, uint8 securityZone, address sender) public returns (InEuint128 memory) {
258
+ return abi.decode(abi.encode(createEncryptedInput(Utils.EUINT128_TFHE, value, securityZone, sender)), (InEuint128));
259
+ }
260
+
261
+ /**
262
+ * @notice Creates an InEuint256 to be used as FHE input. Value is stored in MockCoFHE contract, hash is a pointer to that value.
263
+ * @param value Value to encrypt.
264
+ * @param securityZone Security zone of the encrypted value.
265
+ * @return InEuint256.
266
+ */
267
+ function createInEuint256(uint256 value, uint8 securityZone, address sender) public returns (InEuint256 memory) {
268
+ return abi.decode(abi.encode(createEncryptedInput(Utils.EUINT256_TFHE, value, securityZone, sender)), (InEuint256));
269
+ }
270
+
271
+ /**
272
+ * @notice Creates an InEaddress to be used as FHE input. Value is stored in MockCoFHE contract, hash is a pointer to that value.
273
+ * @param value Value to encrypt.
274
+ * @param securityZone Security zone of the encrypted value.
275
+ * @return InEaddress.
276
+ */
277
+ function createInEaddress(address value, uint8 securityZone, address sender) public returns (InEaddress memory) {
278
+ return
279
+ abi.decode(
280
+ abi.encode(createEncryptedInput(Utils.EADDRESS_TFHE, uint256(uint160(value)), securityZone, sender)),
281
+ (InEaddress)
282
+ );
283
+ }
284
+
285
+ // Overloads with default securityZone=0 for backward compatibility
286
+
287
+ function createInEbool(bool value, address sender) public returns (InEbool memory) {
288
+ return createInEbool(value, 0, sender);
289
+ }
290
+
291
+ function createInEuint8(uint8 value, address sender) public returns (InEuint8 memory) {
292
+ return createInEuint8(value, 0, sender);
293
+ }
294
+
295
+ function createInEuint16(uint16 value, address sender) public returns (InEuint16 memory) {
296
+ return createInEuint16(value, 0, sender);
297
+ }
298
+
299
+ function createInEuint32(uint32 value, address sender) public returns (InEuint32 memory) {
300
+ return createInEuint32(value, 0, sender);
301
+ }
302
+
303
+ function createInEuint64(uint64 value, address sender) public returns (InEuint64 memory) {
304
+ return createInEuint64(value, 0, sender);
305
+ }
306
+
307
+ function createInEuint128(uint128 value, address sender) public returns (InEuint128 memory) {
308
+ return createInEuint128(value, 0, sender);
309
+ }
310
+
311
+ function createInEuint256(uint256 value, address sender) public returns (InEuint256 memory) {
312
+ return createInEuint256(value, 0, sender);
313
+ }
314
+
315
+ function createInEaddress(address value, address sender) public returns (InEaddress memory) {
316
+ return createInEaddress(value, 0, sender);
317
+ }
318
+
319
+ // PERMISSIONS
320
+
321
+ bytes32 private constant PERMISSION_TYPE_HASH =
322
+ keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)');
323
+
324
+ function permissionDomainSeparator() internal view returns (bytes32) {
325
+ string memory name;
326
+ string memory version;
327
+ uint256 chainId;
328
+ address verifyingContract;
329
+
330
+ (, name, version, chainId, verifyingContract, , ) = mockAcl.eip712Domain();
331
+
332
+ return
333
+ keccak256(
334
+ abi.encode(PERMISSION_TYPE_HASH, keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract)
335
+ );
336
+ }
337
+
338
+ function permissionHashTypedDataV4(bytes32 structHash) public view returns (bytes32) {
339
+ return MessageHashUtils.toTypedDataHash(permissionDomainSeparator(), structHash);
340
+ }
341
+
342
+ function signPermission(bytes32 structHash, uint256 pkey) public pure returns (bytes memory signature) {
343
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(pkey, structHash);
344
+ return abi.encodePacked(r, s, v); // note the order here is different from line above.
345
+ }
346
+
347
+ function signPermissionSelf(
348
+ Permission memory permission,
349
+ uint256 pkey
350
+ ) public view returns (Permission memory signedPermission) {
351
+ signedPermission = permission;
352
+
353
+ bytes32 permissionHash = PermissionUtils.issuerSelfHash(permission);
354
+ bytes32 structHash = permissionHashTypedDataV4(permissionHash);
355
+
356
+ signedPermission.issuerSignature = signPermission(structHash, pkey);
357
+ }
358
+
359
+ function signPermissionShared(
360
+ Permission memory permission,
361
+ uint256 pkey
362
+ ) public view returns (Permission memory signedPermission) {
363
+ signedPermission = permission;
364
+ bytes32 permissionHash = PermissionUtils.issuerSharedHash(permission);
365
+ bytes32 structHash = permissionHashTypedDataV4(permissionHash);
366
+
367
+ signedPermission.issuerSignature = signPermission(structHash, pkey);
368
+ }
369
+
370
+ function signPermissionRecipient(
371
+ Permission memory permission,
372
+ uint256 pkey
373
+ ) public view returns (Permission memory signedPermission) {
374
+ signedPermission = permission;
375
+
376
+ bytes32 permissionHash = PermissionUtils.recipientHash(permission);
377
+ bytes32 structHash = permissionHashTypedDataV4(permissionHash);
378
+
379
+ signedPermission.recipientSignature = signPermission(structHash, pkey);
380
+ }
381
+
382
+ function createBasePermission() public pure returns (Permission memory permission) {
383
+ permission = Permission({
384
+ issuer: address(0),
385
+ expiration: 1000000000000,
386
+ recipient: address(0),
387
+ validatorId: 0,
388
+ validatorContract: address(0),
389
+ sealingKey: bytes32(0),
390
+ issuerSignature: new bytes(0),
391
+ recipientSignature: new bytes(0)
392
+ });
393
+ }
394
+
395
+ function createPermissionSelf(address issuer) public pure returns (Permission memory permission) {
396
+ permission = createBasePermission();
397
+ permission.issuer = issuer;
398
+ }
399
+
400
+ function createPermissionShared(
401
+ address issuer,
402
+ address recipient
403
+ ) public pure returns (Permission memory permission) {
404
+ permission = createBasePermission();
405
+ permission.issuer = issuer;
406
+ permission.recipient = recipient;
407
+ }
408
+
409
+ function createSealingKey(uint256 seed) public pure returns (bytes32) {
410
+ return keccak256(abi.encodePacked(seed));
411
+ }
412
+
413
+ function queryDecrypt(
414
+ uint256 ctHash,
415
+ uint256 hostChainId,
416
+ Permission memory permission
417
+ ) public view returns (bool, string memory error, uint256) {
418
+ return mockQueryDecrypter.queryDecrypt(ctHash, hostChainId, permission);
419
+ }
420
+
421
+ function querySealOutput(
422
+ uint256 ctHash,
423
+ uint256 hostChainId,
424
+ Permission memory permission
425
+ ) public view returns (bool, string memory error, bytes32) {
426
+ return mockQueryDecrypter.querySealOutput(ctHash, hostChainId, permission);
427
+ }
428
+
429
+ function unseal(bytes32 hashed, bytes32 key) public view returns (uint256) {
430
+ return mockQueryDecrypter.unseal(hashed, key);
431
+ }
432
+ }
@@ -0,0 +1,40 @@
1
+ // SPDX-License-Identifier: BSD-3-Clause-Clear
2
+ // solhint-disable one-contract-per-file
3
+
4
+ pragma solidity >=0.8.19 <0.9.0;
5
+
6
+ import { console } from 'forge-std/console.sol';
7
+ import { Test } from 'forge-std/Test.sol';
8
+ import { MessageHashUtils } from '@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol';
9
+ import { EncryptedInput } from '@fhenixprotocol/cofhe-contracts/ICofhe.sol';
10
+ import { SIGNER_PRIVATE_KEY } from '../MockCoFHE.sol';
11
+
12
+ /**
13
+ * @dev Generates valid signatures for encrypted inputs.
14
+ * Uses vm.sign to generate the signatures (only available in foundry tests)
15
+ * Should not need to be interacted with directly, is part of the `createEncryptedInput` function set
16
+ */
17
+ contract MockZkVerifierSigner is Test {
18
+ function zkVerifySignPacked(
19
+ EncryptedInput[] memory inputs,
20
+ address sender
21
+ ) public view returns (EncryptedInput[] memory) {
22
+ EncryptedInput[] memory signedInputs = new EncryptedInput[](inputs.length);
23
+ for (uint256 i = 0; i < inputs.length; i++) {
24
+ signedInputs[i] = zkVerifySign(inputs[i], sender);
25
+ }
26
+ return signedInputs;
27
+ }
28
+
29
+ function zkVerifySign(EncryptedInput memory input, address sender) public view returns (EncryptedInput memory) {
30
+ bytes memory combined = abi.encodePacked(input.ctHash, input.utype, input.securityZone, sender, block.chainid);
31
+
32
+ bytes32 expectedHash = keccak256(combined);
33
+
34
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(SIGNER_PRIVATE_KEY, expectedHash);
35
+ bytes memory signature = abi.encodePacked(r, s, v); // note the order here is different from line above.
36
+
37
+ input.signature = signature;
38
+ return input;
39
+ }
40
+ }