2. Write contract
2.1 Create Counter.sol
cd contractsnano Counter.solcopy this to counter.sol
// SPDX-License-Identifier: BSD-3-Clause-Clear
pragma solidity ^0.8.24;
/// @title A simple counter contract
contract Counter {
uint32 private _count;
/// @notice Returns the current count
function getCount() external view returns (uint32) {
return _count;
}
/// @notice Increments the counter by a specific value
function increment(uint32 value) external {
_count += value;
}
/// @notice Decrements the counter by a specific value
function decrement(uint32 value) external {
require(_count >= value, "Counter: cannot decrement below zero");
_count -= value;
}
}2.2 Translation
cd ..
npx hardhat compile=⇒ output :
Compiled 1 Solidity file successfully2.3 Creat Counter.ts
cd test
nano Counter.tscoppy this to counter.ts
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
import { ethers } from "hardhat";
describe("Counter", function () {
it("empty test", async function () {
console.log("Cool! The test basic skeleton is running!");
});
});2.4. Run the first test
cd ..
npx hardhat testoutput :
Counter
Cool! The test basic skeleton is running!
✔ empty test
1 passing2.5 Add signers
cd ~/fhevm-counter-demo/test
nano Counter.tscoppy this to counter.ts
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
import { ethers } from "hardhat";
type Signers = {
owner: HardhatEthersSigner;
alice: HardhatEthersSigner;
bob: HardhatEthersSigner;
};
describe("Counter", function () {
let signers: Signers;
before(async function () {
const ethSigners: HardhatEthersSigner[] = await ethers.getSigners();
signers = { owner: ethSigners[0], alice: ethSigners[1], bob: ethSigners[2] };
});
it("should work", async function () {
console.log(`owner: ${signers.owner.address}`);
console.log(`alice: ${signers.alice.address}`);
console.log(`bob: ${signers.bob.address}`);
});
});run again
npx hardhat testoutput :
owner: 0x...
alice: 0x...
bob: 0x...
✔ should work2.6 add deploy fixture
cd ~/fhevm-counter-demo/test
nano Counter.tscoppy this to Counter.ts import { Counter, Counter__factory } from "../types";
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
import { expect } from "chai";
import { ethers } from "hardhat";
type Signers = {
deployer: HardhatEthersSigner;
alice: HardhatEthersSigner;
bob: HardhatEthersSigner;
};
async function deployFixture() {
const factory = (await ethers.getContractFactory("Counter")) as Counter__factory;
const counterContract = (await factory.deploy()) as Counter;
const counterContractAddress = await counterContract.getAddress();
return { counterContract, counterContractAddress };
}
describe("Counter", function () {
let signers: Signers;
let counterContract: Counter;
let counterContractAddress: string;
before(async function () {
const ethSigners: HardhatEthersSigner[] = await ethers.getSigners();
signers = { deployer: ethSigners[0], alice: ethSigners[1], bob: ethSigners[2] };
});
beforeEach(async () => {
({ counterContract, counterContractAddress } = await deployFixture());
});
it("should be deployed", async function () {
console.log(`Deployed at: ${counterContractAddress}`);
expect(ethers.isAddress(counterContractAddress)).to.eq(true);
});
});run test again
npx hardhat testoutput:
Deployed at: 0x...
✔ should be deployedDeployed at: 0x...
✔ should be deployed2.7 test getCount, increment, decrement
cd ~/fhevm-counter-demo/test
nano Counter.tscoppy this :
import { Counter, Counter__factory } from "../types";
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
import { expect } from "chai";
import { ethers } from "hardhat";
type Signers = {
deployer: HardhatEthersSigner;
alice: HardhatEthersSigner;
bob: HardhatEthersSigner;
};
async function deployFixture() {
const factory = (await ethers.getContractFactory("Counter")) as Counter__factory;
const counter = (await factory.deploy()) as Counter;
const address = await counter.getAddress();
return { counter, address };
}
describe("Counter", function () {
let signers: Signers;
let counter: Counter;
let address: string;
// Khởi tạo 3 tài khoản: deployer, alice, bob
before(async () => {
const s = await ethers.getSigners();
signers = { deployer: s[0], alice: s[1], bob: s[2] };
});
// Deploy hợp đồng mới trước mỗi test
beforeEach(async () => {
({ counter, address } = await deployFixture());
});
// Test 1: Kiểm tra deploy thành công
it("should be deployed", async () => {
console.log("Deployed at:", address);
expect(ethers.isAddress(address)).to.be.true;
});
// Test 2: Giá trị ban đầu = 0
it("count should be zero", async () => {
const count = await counter.getCount();
expect(count).to.eq(0);
});
// Test 3: Tăng 1 đơn vị
it("increment by 1", async () => {
await counter.connect(signers.alice).increment(1);
const count = await counter.getCount();
expect(count).to.eq(1);
});
// Test 4: Tăng 5 → Giảm 3 → Kết quả = 2
it("decrement by 1", async () => {
await counter.connect(signers.alice).increment(5);
await counter.connect(signers.alice).decrement(3);
const count = await counter.getCount();
expect(count).to.eq(2);
});
});cd ..
npx hardhat testoutput :
Counter
Deployed at: 0x5FbDB2315678afecb367f032d93F642f64180aa3
should be deployed
count should be zero
increment by 1
decrement by 1
4 passing (1s)Last updated