CofheTest is the abstract test base shipped by @cofhe/foundry-plugin. It already inherits forge-std/Test, so inherit CofheTest directly — inheriting both is a redeclaration error.
deployMocks()
Call once in setUp(). Deploys the full CoFHE mock stack and wires the contracts together:
| Mock | Role | Address |
|---|---|---|
MockTaskManager | Manages FHE operations; stores plaintext values on-chain | TASK_MANAGER_ADDRESS (fixed) |
MockACL | Access control list for encrypted handles | (deployed) |
MockZkVerifier | Verifies encrypted-input ZK proofs | 0x…5001 (fixed) |
MockZkVerifierSigner | Signs encrypted inputs (for the mock verifier) | (funded with 10 ether) |
MockThresholdNetwork | Handles decryption requests | 0x…5002 (fixed) |
MockThresholdNetworkSigner | Signs decrypt-result outputs | (deployed) |
deployMocks() runs, the following public state vars are available on CofheTest:
expectPlaintext doesn’t cover (e.g. permission-denied assertions — see Testing).
createCofheClient()
Returns a fresh CofheClient. You typically follow it with connect(pkey):
Reading plaintext values
BecauseMockTaskManager stores plaintext values on-chain, you can read the underlying plaintext of any encrypted handle directly — no permit needed.
getPlaintext(handle)
Returns the on-chain plaintext from MockTaskManager.mockStorage. Typed overloads exist for every encrypted Solidity type:
expectPlaintext(handle, value) and (handle, value, "msg")
Assertion variant — typed overloads for the same type set. Faster than decryptForView (no SDK round-trip, no permit needed). Use it whenever you only care about the value, not the SDK code path.
Logging
The mocks log every FHE operation to the console when log mode is on. Toggle it locally with:| Function | Effect |
|---|---|
enableLogs() | Calls mockTaskManager.setLogOps(true) |
disableLogs() | Calls mockTaskManager.setLogOps(false) |
Common pitfalls
IDE Solidity LSP errors but `forge test` is green
IDE Solidity LSP errors but `forge test` is green
Solidity LSPs (Wake, Cursor, etc.) often resolve imports from the monorepo root rather than the package’s
node_modules. The plugin’s remappings are package-local, so the LSP may flag valid imports. forge is authoritative — if forge build and forge test succeed, the test is correct.`@cofhe/mock-contracts/foundry/CoFheTest.sol` import
`@cofhe/mock-contracts/foundry/CoFheTest.sol` import
That import path is the old API from See the migration mapping for the full rename table.
@cofhe/mock-contracts@0.4.x. Migrate to:Don't run `forge test` cross-monorepo
Don't run `forge test` cross-monorepo
The remappings are relative to the foundry package’s root. Running
forge test from a parent monorepo directory won’t resolve them — forge resolves from the working directory.Next steps
- CofheClient — per-user encrypt / decrypt / permit shim.
- Testing — canonical test-writing patterns and migration mapping.