Hẳn đối với những bạn mới bắt đầu tìm hiểu Ethereum nói riêng cũng như các nền tảng EVM-based nói chung đều biết đến Truffle
(một framework hỗ trợ compile, deploy smart contract). Tuy nhiên, khi cần phát triển các smart contract lớn, phức tạp hơn thì nó sẽ bộc lộ 1 số hạn chế như tốn nhiều gas, thời gian deploy lâu, ... Với Hardhat
, framework đem lại cho chúng ta những tùy chọn, tính năng phần nào vượt trội hơn để làm với các hệ thống smart contract phức tạp hơn.
1. Giới thiệu tổng quan
Cũng như Truffle, Hardhat là một môi trường phát triển để biên dịch, triển khai, test và debug Dapp Ethereum.
Một số điểm tính năng nổi bật của Hardhat
- Tích hợp mạng local
hardhat
, dễ dàng chạy và debug code ngay trên local. - Debug dễ dàng hơn: Với Hardhat, chúng ta có thể debug code Solidity dễ dàng hơn khi có thể console.log ra các biến (Solidity vốn ko hỗ trợ console.log)
- Hệ thống plugin: Giúp developer có thể bổ sung chức năng, tùy vào từng dự án cụ thể
- Hỗ trợ TypeScript
2. Cài đặt
Chúng ta còn setup thử 1 project mẫu nho nhỏ với hardhat
. Chúng ta thực hiện các thao tác như dưới đây
mkdir hardhat-tutorial cd hardhat-tutorial npm init --yes npm install --save-dev hardhat
npx hardhat
Chúng ta sẽ chọn lựa chọn số 1 (tạo ra 1 project mẫu)
Tiếp tục lựa chọn các option cần thiết
Cuối cùng, cấu trúc thư mục project mẫu của Hardhat sẽ như thế này các bạn ạ
Còn đây lấy cấu trúc tương ứng của Truffle Box
Cơ bản cấu trúc project của 2 công cụ là tương đối giống nhau
- Thư mục
contracts
chứa mã nguồn của các smart contract - Thư mục
scripts
vàmigrations
chứa các script viết bằng Javascript để biên dịch, deploy smart contract. - Thư mục
test
chứa unit test viết cho contract - 2 File
hardhat.config.js
vàtruffle-config.js
chứa các config như networks, địa chỉ ví, trình biên dịch ...
3. Sử dụng
Greeter.sol
Chúng ta có file smart contract Greeter.sol
trong folder contracts
pragma solidity ^0.7.0; // Thư viện giúp sử dụng console.log trong solidity để debug
import "hardhat/console.sol"; contract Greeter { string greeting; constructor(string memory _greeting) { console.log("Deploying a Greeter with greeting:", _greeting); greeting = _greeting; } function greet() public view returns (string memory) { return greeting; } function setGreeting(string memory _greeting) public { console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); greeting = _greeting; }
}
hardhat.config.js
File hardhat.config.js
là nơi chúng ta định nghĩa các networks, trình biên dịch, thư mục file build, ...
require('@nomiclabs/hardhat-waffle'); task("accounts", "Prints the list of accounts", async () => { const accounts = await ethers.getSigners(); for (const account of accounts) { console.log(account.address); }
}); module.exports = { solidity: '0.7.3'
};
Một phiên bản hoàn thiện hơn
module.exports = { defaultNetwork: 'hardhat', networks: { hardhat: {}, development: { url: 'http://127.0.0.1:8545', }, quorum: { url: 'http://127.0.0.1:22000', }, }, solidity: { version: '0.6.2', settings: { optimizer: { enabled: true, runs: 200, }, }, }, paths: { sources: './contracts', tests: './test', cache: './cache', artifacts: './artifacts', }, mocha: { timeout: 20000, },
};
scripts/sample-script.js
Khác với Truffle, Hardhat không cần deploy "đệm" thêm contract Migration.sol
, nên tiết kiệm được 1 lượng gas
const hre = require("hardhat"); async function main() { // load contract Greeter const Greeter = await hre.ethers.getContractFactory("Greeter"); // Truyền tham số cho hàm constructor const greeter = await Greeter.deploy("Vui Tet Cung Viblo"); // deploy contract await greeter.deployed(); console.log("Greeter deployed to:", greeter.address);
} main() .then(() => process.exit(0)) .catch(error => { console.error(error); process.exit(1); });
Deploy
npx hardhat run scripts/sample-script.js
Nếu muốn deploy code contract ở các mạng khác thì chúng ta thêm lựa chọn --network
npx hardhat run scripts/sample-script.js --network development
Vậy đoạn console.log chúng ta đặt trong hàm constructor
đã được thực thi
4. Các tính năng nâng cao hơn
Biên dịch các contract ở nhiều phiên bản Solidity khác nhau
hardhat.config.js
module.exports = { solidity: { compilers: [ { version: "0.5.5" }, { version: "0.6.7", settings: { } } ] }
}
Hardhat trong trường hợp này sẽ dùng trình biên dịch 0.5.5
với các contract pragma solidity ^0.5.0
và 0.6.7
với các contract pragma solidity ^0.6.0
Trong TH contract định nghĩa trình biên dịch pragma solidity >=0.5.0
thì Hardhat sẽ lựa chọn trình biên dịch cao nhất 0.6.7
Hoặc chúng ta có thể config chi tiết cho contracs nào dùng trình biên dịch nào
module.exports = { solidity: { compilers: [...], overrides: { "contracts/Foo.sol": { version: "0.5.5", settings: { } } } }
}
Chạy riêng 1 mạng blockchain local như ganache
Trước đây, mình hay dùng ganache để deploy smart contract trên local với truffle để thử nghiệm, tất nhiên là mình có thể dùng truffle develop
nhưng ganache có nhiều lựa chọn và cách cấu hình các thông số hơn. Với Hardhat, mình có thể dùng luôn Hardhat, nó hỗ trợ cả việc mô phỏng các phiên bản hardforks của Ethereum trên local.
npx hardhat node
Mặc định mạng sẽ chạy ở port 8545
, chúng ta có thể thêm các tham số để điều chỉnh lại theo ý muốn
--fork
--fork-block-number
--hostname --port
Kết luận
Nhìn chung, Hardhat là 1 công cụ rất mạnh, đầy đủ tính năng cần thiết giúp các developer có thể triển khai smart contract trên Ethereum. Cách dùng Hardhat cũng khá giống với Truffle, ngoài ra cũng khắc phục được 1 số điểm chưa tốt từ đối thủ.