web3-testing – skill Lập trình cho agent AI
Nắm vững các chiến lược kiểm thử toàn diện cho smart contract với Hardhat, Foundry và các mẫu kiểm thử nâng cao.
Cài skill web3-testing bằng một lệnh
Chọn công cụ bạn đang dùng, copy lệnh và dán vào terminal. Skill sẽ nằm trong thư mục skills của công cụ đó và sẵn sàng dùng ở phiên làm việc tiếp theo.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/web3-testing-7b87a.tgz | tar xz -C ~/.claude/skills
Gọi trong Claude Code: /web3-testing – rồi mô tả công việc bạn muốn làm.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/web3-testing-7b87a.tgz | tar xz -C ~/.codex/skills
Gọi trong Codex: $web3-testing – rồi mô tả công việc bạn muốn làm.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/web3-testing-7b87a.tgz | tar xz -C ~/.hermes/skills
Gọi trong Hermes Agent: /web3-testing – rồi mô tả công việc bạn muốn làm.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/web3-testing-7b87a.tgz | tar xz -C ~/.deepcode/skills
Gọi trong DeepSeek: /web3-testing – rồi mô tả công việc bạn muốn làm.
Nội dung SKILL.md
Nội dung SKILL.md gốc bằng tiếng Anh.
Supporting material availability
This catalog copy contains the inline guidance below, but does not include the following supporting paths. They are external prerequisites, not bundled files:
<support-root>/references/hardhat-setup.md<support-root>/references/foundry-setup.md<support-root>/references/test-patterns.md<support-root>/references/mainnet-forking.md<support-root>/references/contract-verification.md<support-root>/assets/hardhat-config.js<support-root>/assets/test-suite.js<support-root>/assets/foundry.toml<support-root>/scripts/test-contract.sh
Ask for the original supporting material or an existing installation before using a step that depends on these paths; this catalog does not identify a verified download source for them. Resolve each path relative to that installation, inspect its contents, and verify any applicable license and execution prerequisites. Do not run a command or claim a referenced procedure was followed until its required file exists. Do not fabricate the missing scripts or treat an unrelated file with the same name as equivalent. Independent steps fully documented here can proceed within the user’s authorized scope; report any dependent step as unavailable.
Web3 Smart Contract Testing
Master comprehensive testing strategies for smart contracts using Hardhat, Foundry, and advanced testing patterns.
Do not use this skill when
- The task is unrelated to web3 smart contract testing
- You need a different domain or tool outside this scope
Instructions
- Clarify goals, constraints, and required inputs.
- Apply relevant best practices and validate outcomes.
- Provide actionable steps and verification.
Use this skill when
- Writing unit tests for smart contracts
- Setting up integration test suites
- Performing gas optimization testing
- Fuzzing for edge cases
- Forking mainnet for realistic testing
- Automating test coverage reporting
- Verifying contracts on Etherscan
Hardhat Testing Setup
The CommonJS snippets illustrate a legacy Hardhat 2 / ethers 5 toolchain. Pin compatible reviewed versions from the project lockfile; do not combine them with Hardhat 3 / ethers 6 without migration. Contract fixtures and interfaces are project-specific prerequisites, not bundled deployable code. Use local development chains and disposable keys only. Forked state is local; never broadcast or deploy on a funded network as a testing shortcut. Remote source verification is a separate publication action.
// hardhat.config.js
require("@nomicfoundation/hardhat-toolbox");
require("@nomiclabs/hardhat-etherscan");
require("hardhat-gas-reporter");
require("solidity-coverage");
module.exports = {
solidity: {
version: "0.8.19",
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
networks: {
hardhat: {
forking: {
url: process.env.MAINNET_RPC_URL,
blockNumber: 15000000,
},
},
},
gasReporter: {
enabled: true,
currency: "USD",
coinmarketcap: process.env.COINMARKETCAP_API_KEY,
},
etherscan: {
apiKey: process.env.ETHERSCAN_API_KEY,
},
};Unit Testing Patterns
const { expect } = require("chai");
const { ethers, network } = require("hardhat");
const {
loadFixture,
time,
} = require("@nomicfoundation/hardhat-network-helpers");
describe("Token Contract", function () {
// Fixture for test setup
async function deployTokenFixture() {
const [owner, addr1, addr2] = await ethers.getSigners();
const Token = await ethers.getContractFactory("Token");
const token = await Token.deploy();
return { token, owner, addr1, addr2 };
}
describe("Deployment", function () {
it("Should set the right owner", async function () {
const { token, owner } = await loadFixture(deployTokenFixture);
expect(await token.owner()).to.equal(owner.address);
});
it("Should assign total supply to owner", async function () {
const { token, owner } = await loadFixture(deployTokenFixture);
const ownerBalance = await token.balanceOf(owner.address);
expect(await token.totalSupply()).to.equal(ownerBalance);
});
});
describe("Transactions", function () {
it("Should transfer tokens between accounts", async function () {
const { token, owner, addr1 } = await loadFixture(deployTokenFixture);
await expect(token.transfer(addr1.address, 50)).to.changeTokenBalances(
token,
[owner, addr1],
[-50, 50],
);
});
it("Should fail if sender doesn't have enough tokens", async function () {
const { token, owner, addr1 } = await loadFixture(deployTokenFixture);
const initialBalance = await token.balanceOf(addr1.address);
await expect(
token.connect(addr1).transfer(owner.address, 1),
).to.be.revertedWith("Insufficient balance");
});
it("Should emit Transfer event", async function () {
const { token, owner, addr1 } = await loadFixture(deployTokenFixture);
await expect(token.transfer(addr1.address, 50))
.to.emit(token, "Transfer")
.withArgs(owner.address, addr1.address, 50);
});
});
describe("Time-based tests", function () {
it("Should handle time-locked operations", async function () {
const { token } = await loadFixture(deployTokenFixture);
// Increase time by 1 day
await time.increase(86400);
// Test time-dependent functionality
});
});
describe("Gas optimization", function () {
it("Should use gas efficiently", async function () {
const { token, addr1 } = await loadFixture(deployTokenFixture);
const tx = await token.transfer(addr1.address, 100);
const receipt = await tx.wait();
expect(receipt.gasUsed).to.be.lessThan(50000);
});
});
});Foundry Testing (Forge)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "forge-std/Test.sol";
import "../src/Token.sol";
interface IERC20MetadataForTest {
function symbol() external view returns (string memory);
}
contract TokenTest is Test {
Token token;
address owner = address(1);
address user1 = address(2);
address user2 = address(3);
function setUp() public {
vm.prank(owner);
token = new Token();
}
function testInitialSupply() public {
assertEq(token.totalSupply(), 1000000 * 10**18);
}
function testTransfer() public {
vm.prank(owner);
token.transfer(user1, 100);
assertEq(token.balanceOf(user1), 100);
assertEq(token.balanceOf(owner), token.totalSupply() - 100);
}
function testTransferInsufficientBalance() public {
vm.expectRevert(); // Prefer the exact expected error from the tested contract.
vm.prank(user1);
token.transfer(user2, 100); // Should fail
}
function testCannotTransferToZeroAddress() public {
vm.prank(owner);
vm.expectRevert("Invalid recipient");
token.transfer(address(0), 100);
}
// Fuzzing test
function testFuzzTransfer(uint256 amount) public {
vm.assume(amount > 0 && amount <= token.totalSupply());
vm.prank(owner);
token.transfer(user1, amount);
assertEq(token.balanceOf(user1), amount);
}
// Test with cheatcodes
function testDealAndPrank() public {
// Give ETH to address
vm.deal(user1, 10 ether);
// Impersonate address
vm.prank(user1);
// Test functionality
assertEq(user1.balance, 10 ether);
}
// Mainnet fork test
function testForkMainnet() public {
vm.createSelectFork(vm.envString("MAINNET_RPC_URL"), 15000000);
// Interact with mainnet contracts
address dai = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
assertEq(IERC20MetadataForTest(dai).symbol(), "DAI");
}
}Advanced Testing Patterns
Snapshot and Revert
describe("Complex State Changes", function () {
let snapshotId;
beforeEach(async function () {
snapshotId = await network.provider.send("evm_snapshot");
});
afterEach(async function () {
await network.provider.send("evm_revert", [snapshotId]);
});
it("Test 1", async function () {
// Make state changes
});
it("Test 2", async function () {
// State reverted, clean slate
});
});Mainnet Forking
describe("Mainnet Fork Tests", function () {
let uniswapRouter, dai, usdc;
before(async function () {
await network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
jsonRpcUrl: process.env.MAINNET_RPC_URL,
blockNumber: 15000000,
},
},
],
});
// Connect to existing mainnet contracts
uniswapRouter = await ethers.getContractAt(
"IUniswapV2Router",
"0x7a250d5630B4cF539739dF2C5dAcb4c659… (nội dung đầy đủ có trong gói tải về)
Skill liên quan
- web3-transaction-relayer-pool – Sổ đăng ký pool node relayer giao dịch không phí gas: giới hạn tài trợ phí, đồng bộ…
- webapp-testing – Để kiểm thử ứng dụng web cục bộ, viết script Playwright Python gốc.
- webdriverio-skill – Tạo test tự động hóa WebdriverIO (WDIO) bằng JavaScript hoặc TypeScript. Hỗ trợ chạy cục…
- what-could-break – Tìm những gì một thay đổi có thể làm hỏng ngoài phạm vi diff của nó, rồi chứng minh một…
- whatsapp-cloud-api – Tích hợp WhatsApp Business Cloud API (Meta). Tin nhắn, template, webhook HMAC-SHA256, tự…
- wiki-qa – Trả lời câu hỏi về repository chỉ dựa trên bằng chứng từ mã nguồn. Dùng khi người dùng…
- wjttc-builder – LẬP KẾ HOẠCH và TẠO bộ test WJTTC (đẳng cấp vô địch) cho mọi dự án. Phân tích codebase…
- wjttc-tester – Bộ THỰC THI test lấy cảm hứng từ F1, kiêm báo cáo. Chạy kế hoạch test, tìm và tái hiện…