Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Mock Contracts

The plugin deploys a suite of mock contracts that simulate the full CoFHE coprocessor stack on the Hardhat network. This lets you develop and test FHE contracts without running the off-chain FHE engine.

What the mocks simulate

ContractRole
MockTaskManagerManages FHE operations; stores plaintext values on-chain for testing
MockACLAccess control for encrypted handles
MockZkVerifierSimulates ZK proof verification for encrypted inputs
MockThresholdNetworkHandles decryption requests
SimpleTestOptional helper contract for tests — exposes trivial value setters plus getValueHash()

The SDK automatically detects when it's running against the mock environment (by checking bytecode at the MockZkVerifier fixed address) and adapts its behavior accordingly — ZK proof generation is skipped and verification is handled by the mock contracts.

Auto-deployment

The core mock contracts are deployed automatically before every npx hardhat test and npx hardhat node run. SimpleTest is not auto-deployed.

To skip auto-deployment:

COFHE_SKIP_MOCKS_DEPLOY=1 npx hardhat test

You can also deploy mock contracts manually via the Hardhat task:

npx hardhat task:cofhe-mocks:deploy
npx hardhat task:cofhe-mocks:deploy --silent true          # suppress output

Or programmatically from a test or script:

import hre from 'hardhat';
 
await hre.cofhe.mocks.deployMocks();

Accessing mock contracts

hre.cofhe.mocks exposes typed accessors for the core mock contracts. Each method returns a fully typed Typechain contract instance:

import hre from 'hardhat';
 
const taskManager = await hre.cofhe.mocks.getMockTaskManager();
const acl = await hre.cofhe.mocks.getMockACL();
const thresholdNetwork = await hre.cofhe.mocks.getMockThresholdNetwork();
const zkVerifier = await hre.cofhe.mocks.getMockZkVerifier();
 
const simpleTestFactory = await hre.ethers.getContractFactory('SimpleTest');
const simpleTest = await simpleTestFactory.deploy();
await simpleTest.waitForDeployment();

Reading plaintext values

Because MockTaskManager stores plaintext values on-chain, you can read the underlying plaintext of any encrypted handle directly in tests — no acp needed.

getPlaintext(ctHash)

Returns the plaintext bigint for a given handle (ctHash in code):

import hre from 'hardhat';
import { expect } from 'chai';
 
const simpleTestFactory = await hre.ethers.getContractFactory('SimpleTest');
const simpleTest = await simpleTestFactory.deploy();
await simpleTest.waitForDeployment();
await simpleTest.setValueTrivial(7);
const ctHash = await simpleTest.getValueHash();
 
const plaintext = await hre.cofhe.mocks.getPlaintext(ctHash); 
 
expect(plaintext).to.equal(7n);

expectPlaintext(ctHash, expectedValue)

Assertion shorthand — wraps getPlaintext with a Chai expect:

import hre from 'hardhat';
 
const simpleTestFactory = await hre.ethers.getContractFactory('SimpleTest');
const simpleTest = await simpleTestFactory.deploy();
await simpleTest.waitForDeployment();
await simpleTest.setValueTrivial(7);
const ctHash = await simpleTest.getValueHash();
 
await hre.cofhe.mocks.expectPlaintext(ctHash, 7n); 

Gas reporting

Mock FHE operations consume more gas than they would on a real CoFHE network, because the off-chain FHE work is replicated on-chain. MockTaskManager measures this overhead and emits a MockGasConsumed(uint256) event for every block of mock-only work (op replication, decrypt-task storage, mock logging), so the plugin can report corrected numbers.

hre.cofhe.getAdjustedGasUsed(receipt)

Returns the transaction's gas usage with the mock overhead subtracted — an estimate of real-network cost:

import hre from 'hardhat';
 
const simpleTestFactory = await hre.ethers.getContractFactory('SimpleTest');
const simpleTest = await simpleTestFactory.deploy();
await simpleTest.waitForDeployment();
 
const tx = await simpleTest.setValueTrivial(7);
const receipt = await tx.wait();
 
const adjusted = hre.cofhe.getAdjustedGasUsed(receipt!); 

hre.cofhe.getAdjustedGasBreakdown(receipt)

Returns the full breakdown:

const { gasUsed, mockGas, adjustedGasUsed, mockGasEvents } = hre.cofhe.getAdjustedGasBreakdown(receipt);
// gasUsed         — raw gas (includes mock overhead)
// mockGas         — gas consumed by mock-only work
// adjustedGasUsed — gasUsed - mockGas (≈ real-network cost)
// mockGasEvents   — number of mock-only blocks executed

Both helpers are pure functions of the receipt — no RPC calls. On a real network the receipt carries no mock events, so adjustedGasUsed equals gasUsed; the same code works everywhere.

End-of-run summary table

Set cofhe: { gasSummary: true } in your Hardhat config to print a per-method table after every test run:

[COFHE-MOCKS] Gas summary — adjusted ≈ cost excluding mock-only overhead
┌──────────────────┬──────────────────────────┬───────┬─────────────────┬────────────────────┬───────────────┐
│ Contract         │ Method                   │ Calls │ Avg gas (mocks) │ Avg gas (adjusted) │ Mock overhead │
├──────────────────┼──────────────────────────┼───────┼─────────────────┼────────────────────┼───────────────┤
│ SimpleTest       │ setValueTrivial(uint256) │ 11    │ 179,897         │ 141,482            │ 21%           │
└──────────────────┴──────────────────────────┴───────┴─────────────────┴────────────────────┴───────────────┘