Fuzz testing là một kỹ thuật kiểm thử quan trọng nhưng thường bị bỏ qua trong quy trình QA smart contract. Trong khi unit test giúp đảm bảo từng hàm hoạt động đúng với các input dự đoán trước, thì fuzz testing lại giúp tìm ra những lỗi bất ngờ khi người dùng nhập vào các giá trị “kỳ quặc” – như số cực lớn, địa chỉ bất thường hoặc hành vi không nằm trong dự đoán của dev.
Bài viết này sẽ giúp bạn hiểu rõ fuzz testing là gì, cách thực hiện fuzz testing trong Solidity, những lỗi dễ phát hiện, và khi nào nên áp dụng.
Table of Contents
Fuzz Testing Là Gì?
Fuzz testing (kiểm thử ngẫu nhiên) là quá trình tự động sinh các giá trị đầu vào ngẫu nhiên để kiểm tra xem smart contract có phản hồi bất thường không. Kỹ thuật này thường dùng để phát hiện:
- Arithmetic overflow/underflow.
- Giải thích: Lỗi xảy ra khi một phép toán số học (cộng/trừ/nhân) làm giá trị vượt quá giới hạn mà biến kiểu
uint
hoặcint
có thể lưu trữ — dẫn đến kết quả sai lệch hoặc quay vòng về 0.
Ví dụ:uint8 a = 255; a + 1
→ quay về 0.
- Giải thích: Lỗi xảy ra khi một phép toán số học (cộng/trừ/nhân) làm giá trị vượt quá giới hạn mà biến kiểu
- Revert không mong muốn.
- Giải thích: Hợp đồng bị dừng (revert) trong lúc thực hiện một hành động hợp lệ vì không xử lý đúng logic điều kiện hoặc input, khiến giao dịch hợp lệ cũng bị từ chối.
- Assertion lỗi.
- Xảy ra khi một dòng kiểm tra kiểu
assert()
không đạt điều kiện mong đợi, thường là dấu hiệu của lỗi nghiêm trọng trong logic vìassert()
dùng để đảm bảo điều “luôn đúng”.
- Xảy ra khi một dòng kiểm tra kiểu
- Crash không rõ nguyên nhân khi input bất thường.
Fuzz test không cần biết cụ thể input là gì – chính sự ngẫu nhiên là cách để khám phá những lỗi mà test case bình thường không bao giờ nghĩ tới.
Công Cụ Fuzz Testing Phổ Biến Cho Smart Contract
🔹 Foundry (Được khuyên dùng nhất)
- Foundry hỗ trợ fuzz testing tự động chỉ với vài dòng lệnh.
- Dễ tích hợp với các dự án viết bằng Solidity.
- Tốc độ test cực nhanh, có thể chạy hàng nghìn case chỉ trong vài giây.
Cài đặt Foundry:
bashcurl -L https://foundry.paradigm.xyz | bash
foundryup
Cách Viết Fuzz Test Với Foundry
Ví dụ: kiểm tra hàm deposit(uint amount)
không cho phép gửi giá trị âm hoặc quá lớn.
Smart Contract mẫu:
soliditycontract Bank {
mapping(address => uint256) public balances;
function deposit(uint256 amount) public {
require(amount > 0 && amount < 1e30, "Invalid amount");
balances[msg.sender] += amount;
}
}
Viết fuzz test:
solidityBankTest is Test {
Bank public bank;
function setUp() public {
bank = new Bank();
}
function testFuzz_Deposit(uint256 amount) public {
vm.assume(amount > 0 && amount < 1e30);
uint256 prev = bank.balances(address(this));
bank.deposit(amount);
assertEq(bank.balances(address(this)), prev + amount);
}
}
Dùng fuzz testing để kiểm tra rằng với bất kỳ số tiền nạp nào (trong khoảng hợp lệ), hàm
deposit()
luôn cộng đúng số dư cho người dùng.
Ở đây:
vm.assume()
loại bỏ những giá trị không hợp lệ.- Foundry sẽ tự tạo hàng trăm giá trị
amount
ngẫu nhiên mỗi lần chạy.
Fuzz Testing Có Thể Phát Hiện Lỗi Gì?
Lỗi | Ví dụ phát hiện qua fuzz |
---|---|
Overflow/Underflow | Cộng tràn uint256 khi user gửi số quá lớn |
Lỗi logic edge-case | Điều kiện require bị bypass nếu input ngẫu nhiên đúng |
Lỗi revert bất ngờ | Input bất thường dẫn tới contract revert không mong muốn |
Infinite loop / gas out | Input gây loop quá lớn → hết gas |
Khi Nào Nên Dùng Fuzz Testing?
Fuzz test nên được áp dụng trong các tình huống:
- Hàm nhận input từ người dùng (token amount, index, address,…).
- Hàm có logic phức tạp với nhiều rẽ nhánh
if-else
. - Dự án có sử dụng phép toán số học, reward calculation, hay staking.
- Sau khi fix bug bảo mật để chắc chắn không phát sinh lỗi mới.
Lưu Ý Khi Làm Fuzz Testing
- Fuzz không thay thế unit test – nên dùng kết hợp.
- Cần dùng
assume()
để loại bỏ input không hợp lệ. - Theo dõi kỹ các
assert()
vàrequire()
để xem lúc nào test fail. - Có thể bổ sung invariant test để nâng cao độ tin cậy (Foundry hỗ trợ).
Mở Rộng: Kết Hợp Fuzz + Coverage + Invariant
- Dùng
forge coverage
để xem fuzz test đã cover đủ các dòng code chưa. - Thêm invariant test để khẳng định tính chất luôn đúng (ví dụ:
balance >= 0
). - Fuzz chạy càng lâu càng tốt: test nhanh thì không nên giới hạn.
Kết Luận
Fuzz testing giúp phát hiện những bug khó lường nhất trong smart contract Solidity – những bug có thể bị bỏ sót dù đã viết unit test kỹ càng. Nếu bạn đang QA cho một dự án DeFi, NFT hoặc staking protocol, hãy bổ sung fuzz testing vào quy trình kiểm thử của mình. Đây là một lớp bảo vệ quan trọng trước khi đưa sản phẩm ra testnet hoặc audit.
Quay lại bài viết Tìm hiểu đầy đủ quy trình các bước kiểm thử smart contract.
Digital Marketing Specialist