# Hardhat 全攻略 (撰寫中...) ###### tags: `DAPP開發筆記` 參考: https://medium.com/my-blockchain-development-daily-journey/完整的hardhat實踐教程-a9b005aa4c12 ::: success 以下教學使用 Typescript ::: 會使用多個 plugin,若要看載哪些 plugin和使用方法,請直接搜尋 "PlugIn" --- ### 安裝 <br> 使用 npm,如果要用 yarn 也行。因為 hardhat 只有在本地才會使用,所以加上 -D。 ```shell= mkdir hardhat cd hardhat npm init -y npm install -D hardhat ``` 接下來執行指令,初始化 hardhat 開發環境 ```shell= npx hardhat ``` 選擇 TypeScript,其他預設就好。 ![](https://hackmd.io/_uploads/rJtxoNn8h.png =80%x) 記得安裝 dependency `npm install --save-dev "hardhat@^2.14.1" "@nomicfoundation/hardhat-toolbox@^2.0.0"` --- ### 底下不會深入講解程式碼如何撰寫,細節請參考 Documentation ### 1. Compile ``` npx hardhat compile //編譯solidity程式碼 ``` ### 2. Testing ``` typescript= import { expect } from "chai"; import hre from "hardhat"; import { time } from "@nomicfoundation/hardhat-network-helpers"; describe("Lock", function () { it("Should set the right unlockTime", async function () { const lockedAmount = 1_000_000_000; const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60; const unlockTime = (await time.latest()) + ONE_YEAR_IN_SECS; // deploy a lock contract where funds can be withdrawn // one year in the future const Lock = await hre.ethers.getContractFactory("Lock"); const lock = await Lock.deploy(unlockTime, { value: lockedAmount }); // assert that the value is correct expect(await lock.unlockTime()).to.equal(unlockTime); }); }); ``` 上面範例中,在一開始可以加上 ```beforeEach()```,將重複的code像部屬合約、變數設定...等放在裡面。但缺點是如果部署許多合約則測試會變慢,因為每個測試(it)都必須發送多個交易作為設定的一部分、且在 beforeEach 和測試(it)之間共享變數很醜陋且容易出錯。 >PlugIn: hardhat-network-helpers([連結](https://hardhat.org/hardhat-network-helpers/docs/overview)) > 上面 plugin 的 `loadFixture` 可以解決這樣的問題,因為當執行第二個測試他會直接 reset state。[更多細節請參考這裡](https://hardhat.org/hardhat-runner/docs/guides/test-contracts)。 hardhat 的 `deployments.fixture` 同樣可以做到上面的事。 ```shell= npx hardhat coverage //可以看自己測試的覆蓋率 ``` 底下這個 plugin 可以看有 gas 消耗多少相關的資訊 > PlugIn: hardhat-etwork-helpers ([連結](https://github.com/cgewecke/hardhat-gas-reporter)) > ### 3. Deploy ```shell= npx hardhat run --network localhost scripts/deploy.ts ``` `--network` 表示要部屬到哪個 network上,可以在 `hardhat.config.ts` 設定,細節設定後續會說明。 >PlugIn: hardhat-deploy-ethers ([連結](https://www.npmjs.com/package/hardhat-deploy-ethers)) 因為 `hardhat-deploy-ethers` 是 `@nomiclabs/hardhat-ethers` 的一個分支,並且其他插件可能對 `@nomiclabs/hardhat-ethers` 具有硬編碼依賴性,因此安裝確保兼容性的最佳方法如下: ```shell= npm install --save-dev @nomiclabs/hardhat-ethers@npm:hardhat-deploy-ethers ethers ``` 引用: ```typescript= import "@nomiclabs/hardhat-ethers"; ``` 基本上這個 plugin 是在原有的 `@nomiclabs/hardhat-ethers` 新增額外功能。有很多 helper function可以使用很方便。 > PlugIn: hardhat-deploy ([連結](https://www.npmjs.com/package/hardhat-deploy)) > 將合約部署到任何網絡,追蹤它們並複制相同的環境進行測試。 > 如果多個測試使用相同的合約,部署將執行一次並且每個測試將以完全相同的狀態開始。 ### 3.1 Deploy to testnet and verify (sepolia) [參考連結](https://hardhat.org/hardhat-runner/docs/guides/verifying) ```typescript= //hardhat.config.ts const ALCHEMY_API_KEY = "KEY"; const SEPOLIA_PRIVATE_KEY = "YOUR SEPOLIA PRIVATE KEY"; module.exports = { networks: { sepolia: { url: `https://eth-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY}`, accounts: [SEPOLIA_PRIVATE_KEY], }, }, }; ``` 部屬: ```shell= npx hardhat run scripts/deploy.ts --network sepolia ``` verify: ```shell= npx hardhat verify --network sepolia <address> <unlock time> //後面是參數 ``` 也可以直接寫程式碼更具彈性,如以下所示: ```typescript= await hre.run("verify:verify", { address: contractAddress, constructorArguments: [ 50, "a string argument", { x: 10, y: 5, }, "0xabcdef", ], }); ``` ### 4. Task [參考連結](https://hardhat.org/hardhat-runner/docs/guides/tasks-and-scripts) 寫一些 task 可以直接 command line 執行想要得到的資訊。 例如: ```typescript= task("accounts", "Prints the list of accounts", async (taskArgs, hre) => { const accounts = await hre.ethers.getSigners(); for (const account of accounts) { console.log(account.address); } }); ``` ```shell= npx hardhat accounts ```