FHE Counter
🟢 Beginner | 📦 Basics
A simple encrypted counter with increment and decrement operations
Overview
This example demonstrates the fundamental concepts of FHEVM by implementing a basic counter that stores its value as an encrypted euint32. Users can increment or decrement the counter using encrypted inputs, and only authorized users can decrypt the current count value.
Quick Start
# Create new project from this template
npx labz create counter my-project
# Navigate and install
cd my-project
npm install
# Run tests
npx hardhat testContract
// SPDX-License-Identifier: BSD-3-Clause-Clear
pragma solidity ^0.8.24;
import { FHE, euint32, externalEuint32 } from "@fhevm/solidity/lib/FHE.sol";
import { ZamaEthereumConfig } from "@fhevm/solidity/config/ZamaConfig.sol";
/// @title FHE Counter - A simple encrypted counter
/// @notice Demonstrates basic FHEVM operations: encrypted state, add, sub, and ACL
contract FHECounter is ZamaEthereumConfig {
/// @dev The encrypted counter value - stored as euint32
euint32 private _count;
/// @notice Returns the encrypted counter handle
/// @dev Returns bytes32(0) if counter is uninitialized
function getCount() external view returns (euint32) {
return _count;
}
/// @notice Increments the counter by an encrypted value
/// @param inputEuint32 The encrypted value to add (from client-side encryption)
/// @param inputProof Zero-knowledge proof validating the encrypted input
function increment(externalEuint32 inputEuint32, bytes calldata inputProof) external {
// Convert external encrypted input to usable euint32
euint32 evalue = FHE.fromExternal(inputEuint32, inputProof);
// Perform encrypted addition
_count = FHE.add(_count, evalue);
// Grant permissions for the new encrypted value
FHE.allowThis(_count); // Allow contract to use this value
FHE.allow(_count, msg.sender); // Allow caller to decrypt off-chain
}
/// @notice Decrements the counter by an encrypted value
/// @param inputEuint32 The encrypted value to subtract (from client-side encryption)
/// @param inputProof Zero-knowledge proof validating the encrypted input
/// @dev No underflow check - for production, implement proper range validation
function decrement(externalEuint32 inputEuint32, bytes calldata inputProof) external {
// Convert external encrypted input to usable euint32
euint32 evalue = FHE.fromExternal(inputEuint32, inputProof);
// Perform encrypted subtraction
_count = FHE.sub(_count, evalue);
// Grant permissions for the new encrypted value
FHE.allowThis(_count); // Allow contract to use this value
FHE.allow(_count, msg.sender); // Allow caller to decrypt off-chain
}
}
Code Explanation
Imports
Import the FHE library with encrypted types (euint32, externalEuint32) and the ZamaEthereumConfig for network configuration. These are essential for any FHEVM contract.
Lines 1-5
Contract Declaration
The contract inherits from ZamaEthereumConfig which provides the necessary FHEVM configuration. The _count variable is an encrypted euint32 - its value is never visible on-chain.
Lines 7-9
Get Count
Returns the encrypted counter handle. Note: This does NOT return the actual value - it returns a bytes32 handle that points to the encrypted value. Users need off-chain decryption to see the actual count.
Lines 11-14
Increment
Increments the counter by an encrypted value. The input comes as externalEuint32 with a proof (inputProof) that validates the encryption. FHE.fromExternal converts it to usable euint32, then FHE.add performs encrypted addition.
Lines 16-24
Decrement
Decrements the counter by an encrypted value. Similar to increment but uses FHE.sub for encrypted subtraction. Note: No underflow check is performed in this simple example.
Lines 26-34
Permissions
FHE.allowThis grants the contract permission to use the encrypted value in future operations. FHE.allow grants the caller (msg.sender) permission to decrypt the value off-chain. Both are critical for proper ACL management.
Lines 21-23
Tags
counter euint32 add sub state beginner FHE.add FHE.sub
Related Examples
Next Steps
After this example, check out:
Generated with Lab-Z
Last updated
