@cofhe/mock-contracts 0.4.0 → 0.5.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @cofhe/mock-contracts Changelog
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 50bb3e4: Decode custom errors from deployed mock contracts by name instead of raw hex selectors.
8
+
9
+ **`@cofhe/mock-contracts`**
10
+
11
+ - 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`.
12
+ - Removed `bytecode` and `deployedBytecode` fields from published artifacts — they are now sourced at runtime from Hardhat's own compilation output.
13
+
14
+ **`@cofhe/hardhat-plugin`**
15
+
16
+ - 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.
17
+ - Deployment bytecode is now fetched from `hre.artifacts.readArtifact()` instead of the pre-built artifact bundle.
18
+
19
+ **`@cofhe/hardhat-3-plugin`**
20
+
21
+ - 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.
22
+ - `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`.
23
+
24
+ ### Patch Changes
25
+
26
+ - a685cd4: **Breaking change: upgraded to tfhe v1.5.3.**
27
+ Previous cofhesdk versions will no longer function.
28
+
3
29
  ## 0.4.0
4
30
 
5
31
  ## 0.3.2
@@ -1,6 +1,5 @@
1
1
  // SPDX-License-Identifier: BSD-3-Clause-Clear
2
- // solhint-disable-next-line transient-storage
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
- assembly {
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
- bool isAllowedTransient;
216
+ ACLStorage storage $ = _getACLStorage();
221
217
  bytes32 key = keccak256(abi.encodePacked(handle, account));
222
- assembly {
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 This function removes the transient allowances, which could be useful for integration with
280
- * Account Abstraction when bundling several UserOps calling the TaskManagerCoprocessor.
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
  /**
@@ -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 SIGNER_ADDRESS = 0x6E12D8C87503D4287c294f2Fdef96ACd9DFf6bd2;
10
- uint256 constant SIGNER_PRIVATE_KEY = 49099792800763675079532137679706322989817545357788440619111868498148356080914;
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 = keccak256(abi.encodePacked(ctHash, result));
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)) {