28 May, 2025 by

Smartcontract: Bộ đếm on-chain với Hardhat

Bạn có thể tăng tốc quá trình phát triển Web App với Javascript/NextJS, Web Server với Rust/Rocket.rs, Mobile App với Dash/Flutter, và cùng nguyên tắc đó ta có phát triển smartcontract với Solidity/Hardhat.

Khởi tạo dự án

Tạo folder dự án cs01 và cài đặt hardhat:

Khởi tạo hardhat. Lưu ý, chúng ta phải chọn Create a TypeScript project (with Viem)y cho tất cả các cài đặt còn lại.

Sau khi hoàn tất, ta được cấu trúc thư mục như bên dưới:

Trong đó hardhat.config.ts là cài đặt Hardhat, thư mục contracts chứa code solidity, thư mục ignition chứa scripts triển khai contracts, và thư mục test để kiểm thử contracts.

Chạy thử lệnh npx hardhat compile,

Quan hệ giữa Smartcontract, Solidity, và ABI

Bạn sẽ phát triển smartcontract bằng Solidity và biên dịch ra mã máy bằng Solidity Compiler. Blockchain sẽ lưu trữ và thực thi mã máy này. Tuy nhiên để tương tác với smartcontract thông qua các ngôn ngữ lập trình như Javascript, Python,... chúng ta cần định nghĩa lại interface của contract một cách thủ công. Điều này được chuẩn hoá bởi Solidity Compiler bằng cách tạo ra một sản phẩm phụ mang tên ABI (Application Binary Interface) trong quá trình biên dịch. Với ABI, các ngôn ngữ lập trình có thể nhanh chóng hiểu và tương tác với smartcontract.

Sản phẩm của Solidity Compiler. Nguồn ảnh: https://medium.com/coinmonks/smart-contract-and-its-compilation-process-34868abccb69Sản phẩm của Solidity Compiler. Nguồn ảnh: https://medium.com/coinmonks/smart-contract-and-its-compilation-process-34868abccb69

Bộ đếm on-chain

Có thể xoá contracts mẫu của hardhat, contracts/Lock.sol.

Chúng ta sẽ viết một smartcontract đơn giản với biến counter được khởi tạo bằng 0 và một hàm increase để tăng +1 cho mỗi lần gọi. Đối với hàm increase, ta chỉ cho phép owner truy cập và emit một sự kiện Increase cho mỗi lần gọi thành công.

Đối với logic contract đã được chuẩn hoá cao như Ownership, token ERC20, thư viện toán MathSafe,... thay vì phải viết lại cho mỗi lần phát triển dự án, sẽ an toàn hơn khi ta sử dụng @openzeppelin/contracts.

@openzeppelin/contracts là một tập hợp các contracts mẫu mực đã được kiểm thử và nâng cấp nhiều lần từ cộng đồng cũng như các công ty đầu ngành. Hiện nay, các contracts phổ biến trong @openzeppelin/contracts có độ tin cậy và an toàn cao.

Với contract Counter.sol bên trên, ta kế thừa lại login của Ownable.sol. Điều này cho phép ta có thể quản lý chủ của (owner) contract và thiết lập quyền cho các hàm mong muốn (ví dụ như increase).

ABI

Nếu chạy thử pnpm build ta sẽ nhận ra một thư mục artifacts chứa các sản phẩm bytecodeabi. Vì ABI sẽ được tái sử dụng nhiều và cho cả SDK, chúng ta nên cần một thư mục riêng để chứa các ABI này.

Thêm cài đặt cho hardhat.config.ts,

Thiết lập các câu lệnh làm việc

Trong scrips của package.json, thay (hoặc thêm mới) 2 lệnh buildtest.

Chạy thử lệnh build,

Đồng thời, ta sẽ được folder abi chứa tất cả các ABI cần thiết. Lưu ý, vì abi là sản phẩm của quá trình build nên hãy thêm nó vào .gitignore.

Phụ lục

Tại sao chúng ta phải tạo các file ts cho ABI?

Để viem có thể suy diễn được interface của contract, viem cần const assertion. Đó là lý do tại sao ta có as const ở cuối các file ts cho ABI. Các bạn có thể bắt gặp công dụng của nó ở bài Triển khai SDK.

VSC Plugins

🪖 Solidity by Nomic Foundation

🎨 Prettier - Code formatter by Prettier

Autoformat trong VSC

❓ How do you format code on save in VS Code - Stackoverflow

You have questions?

Please create issues on my GitHub for any questions.