---
# System prepended metadata

title: Hardhat 全攻略 (撰寫中...)
tags: [DAPP開發筆記]

---

# 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
```