Fuzz Testing khi kiểm thử smart contract, hướng dẫn

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.


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ặc int 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.
  • 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”.
  • 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:

bash

curl -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:

solidity

contract 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:

solidity

BankTest 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ỗiVí dụ phát hiện qua fuzz
Overflow/UnderflowCộ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 outInput 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()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.

Rate this post

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

[mwai_chatbot id="default"]