# 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,其他預設就好。

記得安裝 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
```