@cofhe/mock-contracts 0.4.0 → 0.5.1
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/CHANGELOG.md +32 -0
- package/contracts/MockACL.sol +12 -34
- package/contracts/MockCoFHE.sol +5 -2
- package/contracts/MockTaskManager.sol +50 -1
- package/contracts/TestBed.sol +6 -1
- package/dist/index.d.mts +2250 -245
- package/dist/index.d.ts +2250 -245
- package/dist/index.js +63 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +63 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +16 -17
- package/src/MockACL.ts +1 -3
- package/src/MockTaskManager.ts +59 -3
- package/src/MockThresholdNetwork.ts +1 -3
- package/src/MockZkVerifier.ts +1 -3
- package/src/TestBed.ts +1 -3
- package/src/typechain-types/MockTaskManager.ts +38 -0
- package/src/types.ts +0 -2
- package/contracts/foundry/CoFheTest.sol +0 -452
- package/contracts/foundry/MockZkVerifierSigner.sol +0 -40
- package/test/TestBed.t.sol +0 -71
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# @cofhe/mock-contracts Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 342fd0f: Fix SSR compatibility (`@cofhe/sdk/web` no longer crashes Next.js builds with `self is not defined`) by lazy-loading `tfhe`. Align `@cofhe/mock-contracts` with `@fhenixprotocol/cofhe-contracts@^0.1.3` (updated `TestBed.sol` to use current decrypt API, added missing `ITaskManager` batch methods to `MockTaskManager.sol`).
|
|
8
|
+
|
|
9
|
+
## 0.5.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 50bb3e4: Decode custom errors from deployed mock contracts by name instead of raw hex selectors.
|
|
14
|
+
|
|
15
|
+
**`@cofhe/mock-contracts`**
|
|
16
|
+
|
|
17
|
+
- Replaced transient storage (`tstore`/`tload`) in `MockACL.sol` with block-number-based storage, removing the EVM `cancun` requirement and lowering the Solidity pragma to `>=0.8.19`.
|
|
18
|
+
- Removed `bytecode` and `deployedBytecode` fields from published artifacts — they are now sourced at runtime from Hardhat's own compilation output.
|
|
19
|
+
|
|
20
|
+
**`@cofhe/hardhat-plugin`**
|
|
21
|
+
|
|
22
|
+
- Overrides `TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS` to inject a stub file that imports all mock contracts, so Hardhat compiles them and registers their artifacts. This lets the Hardhat network decode mock contract custom errors by name (e.g. `PermissionInvalid_Expired`) rather than raw hex.
|
|
23
|
+
- Deployment bytecode is now fetched from `hre.artifacts.readArtifact()` instead of the pre-built artifact bundle.
|
|
24
|
+
|
|
25
|
+
**`@cofhe/hardhat-3-plugin`**
|
|
26
|
+
|
|
27
|
+
- Calls `hre.solidity.build()` during the `hre.created` hook to compile mock contracts once at startup, enabling the EDR to decode their custom errors by name.
|
|
28
|
+
- `deployFixed` and `deployVariable` now source bytecode from `hre.artifacts.readArtifact()`, ensuring the deployed bytecode matches Hardhat's build info — which is required for error decoding on variable-address contracts like `MockACL`.
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- a685cd4: **Breaking change: upgraded to tfhe v1.5.3.**
|
|
33
|
+
Previous cofhesdk versions will no longer function.
|
|
34
|
+
|
|
3
35
|
## 0.4.0
|
|
4
36
|
|
|
5
37
|
## 0.3.2
|
package/contracts/MockACL.sol
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
|
2
|
-
|
|
3
|
-
pragma solidity >=0.8.25 <0.9.0;
|
|
2
|
+
pragma solidity >=0.8.19 <0.9.0;
|
|
4
3
|
|
|
5
4
|
import { Strings } from '@openzeppelin/contracts/utils/Strings.sol';
|
|
6
5
|
import { MockPermissioned, Permission } from './Permissioned.sol';
|
|
@@ -44,6 +43,11 @@ contract MockACL is MockPermissioned {
|
|
|
44
43
|
mapping(uint256 handle => mapping(address account => bool isAllowed)) persistedAllowedPairs;
|
|
45
44
|
mapping(uint256 => bool) allowedForDecryption;
|
|
46
45
|
mapping(address account => mapping(address delegatee => mapping(address contractAddress => bool isDelegate))) delegates;
|
|
46
|
+
/// @dev Approximates EIP-1153 transient storage: stores the block.number when the allowance
|
|
47
|
+
/// was granted. An allowance is considered active only if it was set in the current block,
|
|
48
|
+
/// so it auto-expires when the block changes — no explicit cleanup required.
|
|
49
|
+
/// In Hardhat automine mode (one tx per block) this faithfully replicates per-tx transience.
|
|
50
|
+
mapping(bytes32 => uint256) transientAllowanceBlocks;
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
/// @notice Name of the contract.
|
|
@@ -152,17 +156,9 @@ contract MockACL is MockPermissioned {
|
|
|
152
156
|
revert SenderNotAllowed(requester);
|
|
153
157
|
}
|
|
154
158
|
|
|
159
|
+
ACLStorage storage $ = _getACLStorage();
|
|
155
160
|
bytes32 key = keccak256(abi.encodePacked(handle, account));
|
|
156
|
-
|
|
157
|
-
// solc-ignore-next-line transient-storage
|
|
158
|
-
tstore(key, 1)
|
|
159
|
-
let length := tload(0)
|
|
160
|
-
let lengthPlusOne := add(length, 1)
|
|
161
|
-
// solc-ignore-next-line transient-storage
|
|
162
|
-
tstore(lengthPlusOne, key)
|
|
163
|
-
// solc-ignore-next-line transient-storage
|
|
164
|
-
tstore(0, lengthPlusOne)
|
|
165
|
-
}
|
|
161
|
+
$.transientAllowanceBlocks[key] = block.number;
|
|
166
162
|
}
|
|
167
163
|
|
|
168
164
|
/**
|
|
@@ -217,12 +213,9 @@ contract MockACL is MockPermissioned {
|
|
|
217
213
|
* @return isAllowedTransient Whether the account can access transiently the handle.
|
|
218
214
|
*/
|
|
219
215
|
function allowedTransient(uint256 handle, address account) public view virtual returns (bool) {
|
|
220
|
-
|
|
216
|
+
ACLStorage storage $ = _getACLStorage();
|
|
221
217
|
bytes32 key = keccak256(abi.encodePacked(handle, account));
|
|
222
|
-
|
|
223
|
-
isAllowedTransient := tload(key)
|
|
224
|
-
}
|
|
225
|
-
return isAllowedTransient;
|
|
218
|
+
return $.transientAllowanceBlocks[key] == block.number;
|
|
226
219
|
}
|
|
227
220
|
|
|
228
221
|
/**
|
|
@@ -276,28 +269,13 @@ contract MockACL is MockPermissioned {
|
|
|
276
269
|
}
|
|
277
270
|
|
|
278
271
|
/**
|
|
279
|
-
* @dev
|
|
280
|
-
*
|
|
272
|
+
* @dev No-op in the mock: transient allowances auto-expire when the block changes, so explicit
|
|
273
|
+
* cleanup is not needed. Kept for interface compatibility with the production ACL.
|
|
281
274
|
*/
|
|
282
275
|
function cleanTransientStorage() external virtual {
|
|
283
276
|
if (msg.sender != TASK_MANAGER_ADDRESS_) {
|
|
284
277
|
revert DirectAllowForbidden(msg.sender);
|
|
285
278
|
}
|
|
286
|
-
|
|
287
|
-
assembly {
|
|
288
|
-
let length := tload(0)
|
|
289
|
-
tstore(0, 0)
|
|
290
|
-
let lengthPlusOne := add(length, 1)
|
|
291
|
-
for {
|
|
292
|
-
let i := 1
|
|
293
|
-
} lt(i, lengthPlusOne) {
|
|
294
|
-
i := add(i, 1)
|
|
295
|
-
} {
|
|
296
|
-
let handle := tload(i)
|
|
297
|
-
tstore(i, 0)
|
|
298
|
-
tstore(handle, 0)
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
279
|
}
|
|
302
280
|
|
|
303
281
|
/**
|
package/contracts/MockCoFHE.sol
CHANGED
|
@@ -6,8 +6,11 @@ import { FHE } from '@fhenixprotocol/cofhe-contracts/FHE.sol';
|
|
|
6
6
|
import { FunctionId, Utils } from '@fhenixprotocol/cofhe-contracts/ICofhe.sol';
|
|
7
7
|
import { console } from 'hardhat/console.sol';
|
|
8
8
|
|
|
9
|
-
address constant
|
|
10
|
-
uint256 constant
|
|
9
|
+
address constant ZK_VERIFIER_SIGNER_ADDRESS = 0x6E12D8C87503D4287c294f2Fdef96ACd9DFf6bd2;
|
|
10
|
+
uint256 constant ZK_VERIFIER_SIGNER_PRIVATE_KEY = 49099792800763675079532137679706322989817545357788440619111868498148356080914;
|
|
11
|
+
|
|
12
|
+
address constant DECRYPT_RESULT_SIGNER_ADDRESS = 0x70997970C51812dc3A010C7d01b50e0d17dc79C8;
|
|
13
|
+
uint256 constant DECRYPT_RESULT_SIGNER_PRIVATE_KEY = 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d;
|
|
11
14
|
|
|
12
15
|
/**
|
|
13
16
|
* @dev Mock implementation of the CoFHE coprocessor, used to test FHE ops in isolation.
|
|
@@ -38,6 +38,12 @@ library TMCommon {
|
|
|
38
38
|
uint256 private constant UINT_TYPE_MASK = (type(uint8).max >> 1); // 0x7f - 7 bits reserved for uint type in the one before last byte
|
|
39
39
|
uint256 private constant TRIVIALLY_ENCRYPTED_MASK = type(uint8).max - UINT_TYPE_MASK; //0x80 1 bit reserved for isTriviallyEncrypted
|
|
40
40
|
uint256 private constant SHIFTED_TYPE_MASK = UINT_TYPE_MASK << 8; // 0x7f007 bits reserved for uint type in the one before last byte
|
|
41
|
+
uint256 internal constant SHIFT_ENC_TYPE = 224;
|
|
42
|
+
uint256 internal constant SHIFT_CHAIN_ID = 192;
|
|
43
|
+
uint256 internal constant OFFSET_ENC_TYPE = 0x20;
|
|
44
|
+
uint256 internal constant OFFSET_CHAIN_ID = 0x24;
|
|
45
|
+
uint256 internal constant OFFSET_CT_HASH = 0x2c;
|
|
46
|
+
uint256 internal constant MESSAGE_LENGTH = 0x4c;
|
|
41
47
|
|
|
42
48
|
function uint256ToBytes32(uint256 value) internal pure returns (bytes memory) {
|
|
43
49
|
bytes memory result = new bytes(32);
|
|
@@ -155,6 +161,24 @@ library TMCommon {
|
|
|
155
161
|
function isTriviallyEncryptedFromHash(uint256 hash) internal pure returns (bool) {
|
|
156
162
|
return (hash & TRIVIALLY_ENCRYPTED_MASK) == TRIVIALLY_ENCRYPTED_MASK;
|
|
157
163
|
}
|
|
164
|
+
|
|
165
|
+
function computeDecryptResultHash(
|
|
166
|
+
uint256 ctHash,
|
|
167
|
+
uint256 result,
|
|
168
|
+
uint64 chainId
|
|
169
|
+
) internal pure returns (bytes32 messageHash) {
|
|
170
|
+
uint8 encryptionType = getUintTypeFromHash(ctHash);
|
|
171
|
+
|
|
172
|
+
assembly {
|
|
173
|
+
let ptr := mload(0x40)
|
|
174
|
+
mstore(ptr, result)
|
|
175
|
+
mstore(add(ptr, OFFSET_ENC_TYPE), shl(SHIFT_ENC_TYPE, encryptionType))
|
|
176
|
+
mstore(add(ptr, OFFSET_CHAIN_ID), shl(SHIFT_CHAIN_ID, chainId))
|
|
177
|
+
mstore(add(ptr, OFFSET_CT_HASH), ctHash)
|
|
178
|
+
messageHash := keccak256(ptr, MESSAGE_LENGTH)
|
|
179
|
+
mstore(0x40, add(ptr, MESSAGE_LENGTH))
|
|
180
|
+
}
|
|
181
|
+
}
|
|
158
182
|
}
|
|
159
183
|
|
|
160
184
|
contract MockTaskManager is ITaskManager, MockCoFHE {
|
|
@@ -512,7 +536,7 @@ contract MockTaskManager is ITaskManager, MockCoFHE {
|
|
|
512
536
|
return true;
|
|
513
537
|
}
|
|
514
538
|
|
|
515
|
-
bytes32 messageHash =
|
|
539
|
+
bytes32 messageHash = TMCommon.computeDecryptResultHash(ctHash, result, uint64(block.chainid));
|
|
516
540
|
(address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecover(messageHash, signature);
|
|
517
541
|
|
|
518
542
|
if (err != ECDSA.RecoverError.NoError || recovered == address(0)) {
|
|
@@ -673,4 +697,29 @@ contract MockTaskManager is ITaskManager, MockCoFHE {
|
|
|
673
697
|
function isPubliclyAllowed(uint256 ctHash) external view returns (bool) {
|
|
674
698
|
revert NotImplemented();
|
|
675
699
|
}
|
|
700
|
+
|
|
701
|
+
function verifyDecryptResultBatch(
|
|
702
|
+
uint256[] calldata ctHashes,
|
|
703
|
+
uint256[] calldata results,
|
|
704
|
+
bytes[] calldata signatures
|
|
705
|
+
) external view returns (bool) {
|
|
706
|
+
for (uint256 i = 0; i < ctHashes.length; i++) {
|
|
707
|
+
if (!_verifyDecryptResult(ctHashes[i], results[i], signatures[i], true)) {
|
|
708
|
+
return false;
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
return true;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
function verifyDecryptResultBatchSafe(
|
|
715
|
+
uint256[] calldata ctHashes,
|
|
716
|
+
uint256[] calldata results,
|
|
717
|
+
bytes[] calldata signatures
|
|
718
|
+
) external view returns (bool[] memory) {
|
|
719
|
+
bool[] memory out = new bool[](ctHashes.length);
|
|
720
|
+
for (uint256 i = 0; i < ctHashes.length; i++) {
|
|
721
|
+
out[i] = _verifyDecryptResult(ctHashes[i], results[i], signatures[i], false);
|
|
722
|
+
}
|
|
723
|
+
return out;
|
|
724
|
+
}
|
|
676
725
|
}
|
package/contracts/TestBed.sol
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// SPDX-License-Identifier: UNLICENSED
|
|
2
2
|
pragma solidity ^0.8.13;
|
|
3
3
|
|
|
4
|
+
import { TASK_MANAGER_ADDRESS } from '@fhenixprotocol/cofhe-contracts/FHE.sol';
|
|
5
|
+
import { ITaskManager } from '@fhenixprotocol/cofhe-contracts/ICofhe.sol';
|
|
4
6
|
import '@fhenixprotocol/cofhe-contracts/FHE.sol';
|
|
5
7
|
|
|
6
8
|
/// @title TestBed
|
|
@@ -78,7 +80,10 @@ contract TestBed {
|
|
|
78
80
|
/// @notice Requests decryption of `eNumber`.
|
|
79
81
|
/// @dev In real CoFHE this is asynchronous; in mocks it is simulated.
|
|
80
82
|
function decrypt() public {
|
|
81
|
-
FHE.decrypt(
|
|
83
|
+
// The standalone `FHE.decrypt(...)` helper was removed in
|
|
84
|
+
// fhenixprotocol/cofhe-contracts 0.1.3, so we now go through the
|
|
85
|
+
// task manager interface directly.
|
|
86
|
+
ITaskManager(TASK_MANAGER_ADDRESS).createDecryptTask(uint256(numberHash), msg.sender);
|
|
82
87
|
}
|
|
83
88
|
|
|
84
89
|
/// @notice Reads a decryption result (reverts if not ready depending on implementation).
|