Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
ab410b4
partially migrated hardhat package from cofhejs to cofhesdk
alexshchur Oct 27, 2025
90effd3
tmp: trying to solve permit
alexshchur Oct 27, 2025
f2f7fda
more attempts to tackle permit
alexshchur Oct 27, 2025
e40ff27
more attempts
alexshchur Oct 27, 2025
325a111
working tests
alexshchur Oct 29, 2025
99dbc3a
add missing lock file
alexshchur Oct 29, 2025
391273c
cleanup dev code
alexshchur Oct 29, 2025
3353967
use more compact hardhat plugin API for encrypt test
alexshchur Oct 29, 2025
53bf1e6
upd few annotations
alexshchur Oct 29, 2025
e1e2665
all hardhat tests migrated
alexshchur Oct 29, 2025
9086432
finished migrating hardhat tests and updating annotations
alexshchur Oct 29, 2025
dab9a84
cleanup unused config setting
alexshchur Oct 29, 2025
01dfe1e
cleanup old mock contracts from hardhat package
alexshchur Oct 30, 2025
917d636
get rid of old cofhejs package - no happy path yet
alexshchur Oct 30, 2025
9a58a64
update lock after packages cleanups
alexshchur Oct 30, 2025
4d15bd8
chore: cleanup
alexshchur Oct 30, 2025
2723daa
fix: pass zkWalletClient to avoid explicit approval upon sealing
alexshchur Oct 30, 2025
ec8f27b
get back mock settings and reduce noize in the code increment
alexshchur Oct 30, 2025
4be5cde
chore: preserve some annotations and cleanup
alexshchur Oct 30, 2025
3ecc8c0
chore: more cleanups
alexshchur Oct 30, 2025
11044cc
fix: synching with FHE SDK stores: permits portal working
alexshchur Oct 30, 2025
ce3a355
upd permit modal heading
alexshchur Oct 31, 2025
10e574d
fix: uncomment permits list
alexshchur Oct 31, 2025
faaf28c
fix: uncomment permit activation and removal in the list
alexshchur Oct 31, 2025
2b2f10f
cleanup
alexshchur Oct 31, 2025
ab82641
replace cofhejs to cofhe
alexshchur Oct 31, 2025
6e1d23f
rename hook file
alexshchur Oct 31, 2025
175a2e0
more renames
alexshchur Oct 31, 2025
dd5b848
partially updated the README from cofhejs to sdk
alexshchur Oct 31, 2025
0403ec1
chore: more updates in the readme - the sol/test part
alexshchur Oct 31, 2025
4b4630d
update some more annotations regarding cofhe init
alexshchur Oct 31, 2025
3b1b8c1
chore: finish readme updates
alexshchur Oct 31, 2025
5512bbb
cleanup: no need for initializationResults checks
alexshchur Nov 3, 2025
2cdd965
simplify mockHardhatZkvSigner
alexshchur Nov 3, 2025
658dcd6
chore: add annotation
alexshchur Nov 3, 2025
b389c8a
chore: take MOCK PK from hardhat-plugin
alexshchur Nov 3, 2025
8033647
chore: no need to wait for initialization result
alexshchur Nov 3, 2025
bae35ec
fix: correct import
alexshchur Nov 3, 2025
bf2eb91
chore: fix returned types
alexshchur Nov 3, 2025
52a8e14
chore: fix some types in Readme
alexshchur Nov 3, 2025
de7e8ea
fix: const name
alexshchur Nov 3, 2025
4858737
refactor: with new version of sdk mock signer is built into _internal
alexshchur Nov 3, 2025
766ba75
fix: no need to deserialize
alexshchur Nov 3, 2025
7c95854
better naming - useConnectCofheClient
alexshchur Nov 3, 2025
6cc1d93
fix: conditional success notification
alexshchur Nov 4, 2025
79d19f8
chore: typo
alexshchur Nov 4, 2025
701eae4
microopt and simplification
alexshchur Nov 4, 2025
0c12ecf
fix networks config
alexshchur Nov 4, 2025
0d6f4ff
fix: rely on useWatchBlockNumber instead of useBlockNumber (which doe…
alexshchur Nov 4, 2025
039a619
fix: lint
alexshchur Nov 4, 2025
e80435a
chore: initialized -> connected
alexshchur Nov 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 76 additions & 85 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/hardhat/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { task } from "hardhat/config";
import generateTsAbis from "./scripts/generateTsAbis";

import "@nomicfoundation/hardhat-toolbox";
import "cofhe-hardhat-plugin";
import "@cofhe/hardhat-plugin";

// If not set, it uses ours Alchemy's default API key.
// You can get your own at https://dashboard.alchemyapi.io
Expand Down
5 changes: 2 additions & 3 deletions packages/hardhat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@
"qrcode": "~1.5.4"
},
"devDependencies": {
"@cofhe/hardhat-plugin": "0.0.0-beta-20251103142716",
"@cofhe/sdk": "0.0.0-beta-20251103142716",
"@ethersproject/abi": "~5.7.0",
"@ethersproject/providers": "~5.7.2",
"@fhenixprotocol/cofhe-contracts": "0.0.13",
"@fhenixprotocol/cofhe-mock-contracts": "^0.3.0",
"@nomicfoundation/hardhat-chai-matchers": "~2.0.7",
"@nomicfoundation/hardhat-ethers": "~3.0.8",
"@nomicfoundation/hardhat-ignition": "^0.15.11",
Expand All @@ -52,8 +53,6 @@
"@typescript-eslint/eslint-plugin": "~8.27.0",
"@typescript-eslint/parser": "~8.27.0",
"chai": "~4.5.0",
"cofhe-hardhat-plugin": "^0.3.0",
"cofhejs": "^0.3.0",
"eslint": "~9.23.0",
"eslint-config-prettier": "~10.1.1",
"eslint-plugin-prettier": "~5.2.4",
Expand Down
109 changes: 55 additions & 54 deletions packages/hardhat/test/FHECounter.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { loadFixture } from "@nomicfoundation/hardhat-toolbox/network-helpers";
import hre from "hardhat";
import { cofhejs, Encryptable, FheTypes } from "cofhejs/node";
import { Encryptable, FheTypes } from "@cofhe/sdk";

/**
* @file FHECounter.test.ts
* @description Test suite for the FHECounter contract demonstrating FHE operations and testing utilities
*
* This test suite showcases the use of FHE testing tools and utilities:
* - hre.cofhe: Internal FHE testing utilities
* - cofhejs: FHE operations library
* - hre.cofhesdk: Internal FHE testing utilities
* - cofhe client: FHE operations interface
* - Mock environment testing for FHE operations
*/

Expand All @@ -35,119 +35,120 @@ describe("Counter", function () {
* - Provides options for enabling/disabling FHE operation logging
*/
beforeEach(function () {
if (!hre.cofhe.isPermittedEnvironment("MOCK")) this.skip();

// NOTE: Uncomment for global logging
// hre.cofhe.mocks.enableLogs()
// hre.cofhesdk.mocks.enableLogs();
});

afterEach(function () {
if (!hre.cofhe.isPermittedEnvironment("MOCK")) return;

// NOTE: Uncomment for global logging
// hre.cofhe.mocks.disableLogs()
// hre.cofhesdk.mocks.disableLogs()
});

/**
* @dev Tests the basic increment functionality
* Demonstrates:
* - Reading encrypted values using hre.cofhe.mocks.expectPlaintext
* - Logging FHE operations using hre.cofhe.mocks.withLogs
* - Reading encrypted values using hre.cofhesdk.mocks.expectPlaintext
* - Logging FHE operations using hre.cofhesdk.mocks.withLogs
*/
it("Should increment the counter", async function () {
const { counter, bob } = await loadFixture(deployCounterFixture);
const count = await counter.count();

// `hre.cofhe.mocks.expectPlaintext` is used to verify that the encrypted value is 0
// `hre.cofhesdk.mocks.expectPlaintext` is used to verify that the encrypted value is 0
// This uses the encrypted variable `count` and retrieves the plaintext value from the on-chain mock contracts
// This kind of test can only be done in a mock environment where the plaintext value is known
await hre.cofhe.mocks.expectPlaintext(count, 0n);
await hre.cofhesdk.mocks.expectPlaintext(count, 0n);

// `hre.cofhe.mocks.withLogs` is used to log the FHE operations
// `hre.cofhesdk.mocks.withLogs` is used to log the FHE operations
// This is useful for debugging and understanding the FHE operations
// It will log the FHE operations to the console
await hre.cofhe.mocks.withLogs("counter.increment()", async () => {
await hre.cofhesdk.mocks.withLogs("counter.increment()", async () => {
await counter.connect(bob).increment();
});

const count2 = await counter.count();
await hre.cofhe.mocks.expectPlaintext(count2, 1n);
await hre.cofhesdk.mocks.expectPlaintext(count2, 1n);
});

/**
* @dev Tests the cofhejs unseal functionality in mock environment
* @dev Tests the cofhesdk unseal functionality in mock environment
* Demonstrates:
* - Initializing FHE with a Hardhat signer
* - Reading and unsealing encrypted values
* - Reading with transparently unsealing encrypted values
* - Verifying unsealed values match expectations
*/
it("cofhejs unseal (mocks)", async function () {
await hre.cofhe.mocks.enableLogs("cofhejs unseal (mocks)");
it("cofhesdk decrypt (mocks)", async function () {
await hre.cofhesdk.mocks.enableLogs("cofhesdk decrypt (mocks)");
const { counter, bob } = await loadFixture(deployCounterFixture);

// `hre.cofhe.initializeWithHardhatSigner` is used to initialize FHE with a Hardhat signer
// Initialization is required before any `cofhejs.unseal` or `cofhejs.encrypt` operations can be performed
// `initializeWithHardhatSigner` is a helper function that initializes FHE with a Hardhat signer
// It returns a `Promise<Result<>>` type.
// `hre.cofhesdk.createBatteriesIncludedCofhesdkClient` is used to initialize FHE with a Hardhat signer
// Initialization is required before any `encrypt` or `decrypt` operations can be performed
// `createBatteriesIncludedCofhesdkClient` is a helper function that initializes FHE with a Hardhat signer
// Returns a `Promise<CofhesdkClient>` type.

const client = await hre.cofhesdk.createBatteriesIncludedCofhesdkClient(bob);

const count = await counter.count();

// `decryptHandle` is used to unseal the encrypted value
// the client must be initialized and connected before `unseal` can be called
// `decrypt` returns a `Promise<Result<T>>` type.
const unsealedResult = await client.decryptHandle(count, FheTypes.Uint32).decrypt();
// The `Result<T>` type looks like this:
// {
// success: boolean,
// data: T (Permit | undefined in the case of initializeWithHardhatSigner),
// error: CofhejsError | null,
// error: CofhesdkError | null,
// }
const initializeResult = await hre.cofhe.initializeWithHardhatSigner(bob);

// `hre.cofhe.expectResultSuccess` is used to verify that the `Result` is successful (success: true)
// If the `Result` is not successful, the test will fail
await hre.cofhe.expectResultSuccess(initializeResult);

const count = await counter.count();

// `cofhejs.unseal` is used to unseal the encrypted value
// cofhejs must be initialized before `unseal` can be called
const unsealedResult = await cofhejs.unseal(count, FheTypes.Uint32);

// `hre.cofhe.expectResultValue` is used to verify that the `Result.data` is the expected value
// `hre.cofhesdk.expectResultValue` is used to verify that the `Result.data` is the expected value
// If the `Result.data` is not the expected value, the test will fail
await hre.cofhe.expectResultValue(unsealedResult, 0n);
await hre.cofhesdk.expectResultValue(unsealedResult, 0n);

await counter.connect(bob).increment();

const count2 = await counter.count();
const unsealedResult2 = await cofhejs.unseal(count2, FheTypes.Uint32);
await hre.cofhe.expectResultValue(unsealedResult2, 1n);
const unsealedResult2 = await client.decryptHandle(count2, FheTypes.Uint32).decrypt();
await hre.cofhesdk.expectResultValue(unsealedResult2, 1n);

await hre.cofhe.mocks.disableLogs();
await hre.cofhesdk.mocks.disableLogs();
});

/**
* @dev Tests the cofhejs encryption and value setting functionality
* @dev Tests the cofhesdk encryption and value setting functionality
* Demonstrates:
* - Encrypting values using cofhejs
* - Encrypting values using cofhesdk
* - Setting encrypted values in the contract
* - Verifying encrypted values using both mocks and unsealing
*/
it("cofhejs encrypt (mocks)", async function () {
it("cofhesdk encrypt (mocks)", async function () {
const { counter, bob } = await loadFixture(deployCounterFixture);

const initializeResult = await hre.cofhe.initializeWithHardhatSigner(bob);
await hre.cofhe.expectResultSuccess(initializeResult);
const client = await hre.cofhesdk.createBatteriesIncludedCofhesdkClient(bob);

// `encryptInputs` is used to encrypt the value
// the client must be initialized and connected before `encryptInputs` can be called
// `encrypt` returns a `Promise<Result<T>>` type.

// `cofhejs.encrypt` is used to encrypt the value
// cofhejs must be initialized before `encrypt` can be called
const encryptResult = await cofhejs.encrypt([Encryptable.uint32(5n)] as const);
const encryptResult = await client.encryptInputs([Encryptable.uint32(5n)]).encrypt();
// The `Result<T>` type looks like this:
// {
// success: boolean,
// data: T (Permit | undefined in the case of initializeWithHardhatSigner),
// error: CofhesdkError | null,
// }

const [encryptedInput] = await hre.cofhe.expectResultSuccess(encryptResult);
await hre.cofhe.mocks.expectPlaintext(encryptedInput.ctHash, 5n);
const [encryptedInput] = await hre.cofhesdk.expectResultSuccess(encryptResult);
await hre.cofhesdk.mocks.expectPlaintext(encryptedInput.ctHash, 5n);

await counter.connect(bob).set(encryptedInput);

const count = await counter.count();
await hre.cofhe.mocks.expectPlaintext(count, 5n);
await hre.cofhesdk.mocks.expectPlaintext(count, 5n);

const unsealedResult = await client.decryptHandle(count, FheTypes.Uint32).decrypt();

const unsealedResult = await cofhejs.unseal(count, FheTypes.Uint32);
await hre.cofhe.expectResultValue(unsealedResult, 5n);
await hre.cofhesdk.expectResultValue(unsealedResult, 5n);
});
});
});
4 changes: 2 additions & 2 deletions packages/nextjs/app/FHECounterComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { useCallback, useState } from "react";
import { useEncryptInput } from "./useEncryptInput";
import { FheTypes } from "cofhejs/web";
import { FheTypes } from "@cofhe/sdk";
import { IntegerInput, IntegerVariant } from "~~/components/scaffold-eth";
import { EncryptedValue } from "~~/components/scaffold-eth/EncryptedValueCard";
import { useScaffoldReadContract, useScaffoldWriteContract } from "~~/hooks/scaffold-eth";
Expand Down Expand Up @@ -40,7 +40,7 @@ export const FHECounterComponent = () => {
*
* Demonstrates the process of encrypting user input before sending it to the blockchain:
* 1. User enters a number in the input field
* 2. When "Set" is clicked, the number is encrypted using cofhejs
* 2. When "Set" is clicked, the number is encrypted using CoFHE SDK
* 3. The encrypted value is then sent to the smart contract
*
* This ensures the actual value is never exposed on the blockchain,
Expand Down
Loading