Thirdwebで作成したスマートコントラクトをデプロイするスクリプト作成方法

# はじめに
Tihirdwebを使うとパパッとスマートコントラクトを作成、デプロイできて非常に便利ですね。
しかしスマートコントラクトのConstructorにパラメータがある場合、毎度GUIで設定するのは結構めんどくさくなってきます。特に複雑なパラメータを持ったコントラクトだったり、デプロイタイミングで初期設定用のトランザクションを流したい場合などはもはや苦行としか言えない状態になります。
そこで、デプロイスクリプトからデプロイする方法を紹介します。

# 環境
Node.js、npmが必要になります。作業は以下バージョンで行いました。
```
# node -v            
v18.18.0
# npm -v
9.8.1
```


# Thirdwebでコントラクト作成
まずはThirdwebで適当なスマートコントラクトを作成します。
今回はERC20で作成しました。
```
# npx third web create
```

実行すると作成するコントラクトの種類や名前の入力をせがまれるので以下で入力しました。
```
# npx thirdweb create

    $$\     $$\       $$\                 $$\                         $$\       
    $$ |    $$ |      \__|                $$ |                        $$ |      
  $$$$$$\   $$$$$$$\  $$\  $$$$$$\   $$$$$$$ |$$\  $$\  $$\  $$$$$$\  $$$$$$$\  
  \_$$  _|  $$  __$$\ $$ |$$  __$$\ $$  __$$ |$$ | $$ | $$ |$$  __$$\ $$  __$$\ 
    $$ |    $$ |  $$ |$$ |$$ |  \__|$$ /  $$ |$$ | $$ | $$ |$$$$$$$$ |$$ |  $$ |
    $$ |$$\ $$ |  $$ |$$ |$$ |      $$ |  $$ |$$ | $$ | $$ |$$   ____|$$ |  $$ |
    \$$$$  |$$ |  $$ |$$ |$$ |      \$$$$$$$ |\$$$$$\$$$$  |\$$$$$$$\ $$$$$$$  |
     \____/ \__|  \__|\__|\__|       \_______| \_____\____/  \_______|\_______/ 

 💎 thirdweb v0.12.9 💎

✔ What type of project do you want to create? › Contract
✔ What is your project named? … erc20
✔ What framework do you want to use? › Hardhat
✔ What will be the name of your new smart contract? … MyContract
✔ What type of contract do you want to start from? › ERC20
✔ What extensions do you want to add to your contract? › None
```

# ThirdwebのCLIからデプロイできることを確認
```
#npx thirdweb deploy
```
誘導されるがままに操作を進めます。途中、ウォレットの署名が必要になりますので、承認してください。
今回はAvalancheのテストネットワークであるFujiにデプロイしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962731/4f5dd8af-e1a0-8b07-2b21-d6d672e3a272.png)

デプロイパラメータを入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962731/a08cb25a-a513-d82f-730a-ff5514e26986.png)

無事にデプロイできました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962731/65637ae4-68a0-d31f-6fe0-6375451b3473.png)

# スクリプトからのデプロイ
本題のデプロイスクリプトを作成していきます。
今回はNode.jsでThirdweb SDKとethers.jsを使用してデプロイします。


## 準備
デプロイにはThirdwebのEndpointが必要です。ThirewebにログインしてSettingsからCreateAPIKeyでEndpointを作成して、ClientIDとSecretを控えてください。

:::note warn
SecretはEndpointを作成したタイミングでしか取得できないので注意
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962731/3d49847e-edad-ebd3-d255-6b55413c25b5.png)

Endpointを作成したらClientID、Secretを.envファイルに記載します。
ついでにウォレットの秘密鍵も必要になるので、こちらも記載します。

:::note alert
これらの情報は絶対にGit Hub等に公開しないように注意してください。特に秘密鍵は流出するとトークンが盗まれる可能性があります。
:::

```.env
THIRDWEB_CLIENT_ID={cliendId}
THIRDWEB_SECRET_KEY={secret}
PRIVATE_KEY={privatekey}   
```

必要なライブラリをインストールします。
```
#npm i @thirdweb-dev/sdk --save-dev
#npm i dotenv
```

## スマートコントラクトのコンパイル
デプロイにはスマートコントラクトをコンパイルしてバイトコードとAbiが必要になるのでコンパイルします。
depolyしろと言われますが、ここでは無視します。
```
# npx thirdweb build

    $$\     $$\       $$\                 $$\                         $$\       
    $$ |    $$ |      \__|                $$ |                        $$ |      
  $$$$$$\   $$$$$$$\  $$\  $$$$$$\   $$$$$$$ |$$\  $$\  $$\  $$$$$$\  $$$$$$$\  
  \_$$  _|  $$  __$$\ $$ |$$  __$$\ $$  __$$ |$$ | $$ | $$ |$$  __$$\ $$  __$$\ 
    $$ |    $$ |  $$ |$$ |$$ |  \__|$$ /  $$ |$$ | $$ | $$ |$$$$$$$$ |$$ |  $$ |
    $$ |$$\ $$ |  $$ |$$ |$$ |      $$ |  $$ |$$ | $$ | $$ |$$   ____|$$ |  $$ |
    \$$$$  |$$ |  $$ |$$ |$$ |      \$$$$$$$ |\$$$$$\$$$$  |\$$$$$$$\ $$$$$$$  |
     \____/ \__|  \__|\__|\__|       \_______| \_____\____/  \_______|\_______/ 

 💎 thirdweb v0.12.9 💎

✔ Detected project type: hardhat
✔ Compilation successful


🔎 Detected extension on MyContract
✔️ ERC20
✔️ ERC20Burnable
✔️ ERC20Mintable
✔️ ERC20BatchMintable
✔️ ERC20Permit
✔️ ContractMetadata
✔️ Ownable

ℹ Suggested extensions
- ERC20ClaimConditionsV1 - https://portal.thirdweb.com/interfaces/erc20claimconditionsv1
- ERC20ClaimConditionsV2 - https://portal.thirdweb.com/interfaces/erc20claimconditionsv2
- ERC20ClaimPhasesV1 - https://portal.thirdweb.com/interfaces/erc20claimphasesv1
- ERC20ClaimPhasesV2 - https://portal.thirdweb.com/interfaces/erc20claimphasesv2
- ERC20SignatureMintable - https://portal.thirdweb.com/interfaces/erc20signaturemintable
- Permissions - https://portal.thirdweb.com/interfaces/permissions

ℹ Once you're done writing your contracts, you can run the following command to deploy them:

     npm run deploy
```

コンパイルしたスマートコントラクトはartifacts-zk/MyContract.jsonに含まれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962731/b183587a-3d9a-ee68-ce3c-a763ade13414.png)

## デプロイスクリプトの作成
デプロイスクリプトではThirdweb　SDK、ethersを使用します。
thirdwebに含まれるethersがver5のため、注意が必要です。（最新版はethers@6)
ethers.js@5のドキュメントはこちらを参照してください。
https://docs.ethers.org/v5/

手順としては以下です。詳しくはコードを参照ください。
1 ThirdwebのEndpoint経由でデプロイするため、ThirdwebSDKからProviderを取得する
2 秘密鍵を使用してProviderとウォレットを接続する
3 コンパイルしたスマートコントラクトのファクトリーを生成する
4 デプロイする

```javascript
require("dotenv").config();
const { ethers, ContractFactory } = require("ethers");
const fs = require('fs');
const { ThirdwebSDK } = require("@thirdweb-dev/sdk");
const { AvalancheFuji } = require("@thirdweb-dev/chains");

async function main() {
    // 1
    const sdk = ThirdwebSDK.fromPrivateKey(process.env.PRIVATE_KEY, AvalancheFuji, {
        clientId: `${process.env.THIRDWEB_CLIENT_ID}`, // Use client id if using on the client side, get it from dashboard settings
        secretKey: `${process.env.THIRDWEB_SECRET_KEY}`, // Use secret key if using on the server, get it from dashboard settings
    });

    // 2
    const wallet = new ethers.Wallet(
        process.env.PRIVATE_KEY,
        sdk.provider
    );
    // 3
    const MyContract = JSON.parse(fs.readFileSync('./artifacts-zk/contracts/MyContract.sol/MyContract.json', 'utf8'));
    const Factory = new ContractFactory(MyContract.abi, MyContract.bytecode, wallet);

    // 4
    const contract = await Factory.deploy(wallet.address, 'MyContract', 'MC');
    await contract.deployed()
    console.log('contract deploy success, address=', contract.address);
}

main().catch((error) => {
    console.error(error);
    process.exitCode = 1;
});
```

これを実行するとデプロイされたコントラクトのアドレスが表示されます。
```
# node scripts/deploy.js 
0x6e3D7bEA9A5eEb1b7e9f6A0E9a95e4636654e289
contract deploy success, address= 0x4E3BFeeDd04Ce4954F5782e70A35556E547e9C6c
```

ライブラリが割と頻繁にアップデートされるので本記事作成時点でのpackage.jsonを一応残しておきます
```json
{
  "name": "hardhat-javascript-starter",
  "scripts": {
    "build": "npx thirdweb@latest detect",
    "deploy": "npx thirdweb@latest deploy",
    "release": "npx thirdweb@latest release"
  },
  "devDependencies": {
    "@matterlabs/hardhat-zksync-solc": "^0.3.17",
    "@thirdweb-dev/sdk": "^3.10.66",
    "hardhat": "^2.13.0"
  },
  "dependencies": {
    "@thirdweb-dev/contracts": "^3.8.0",
    "dotenv": "^16.3.1",
    "zksync-web3": "^0.14.3"
  }
}

```

## デプロイされたことを確認する
Abaranche Testnetのエクスプローラーからコントラクトアドレスで検索するとデプロイされていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962731/f98dd7e7-3a0d-acae-620a-159bd6837271.png)

コントラクトデプロイ時に初期パラメータなんかを流し込みたい場合はこのスクリプトの中でトランザクションを流してあげることも可能です。（気が向いたら記事にします）

# 終わりに
Thirdweb、簡単にコントラクトを作れて便利なのですが開発中なんかはしょっちゅうデプロイするので、いちいちGUIでパラメータ入れるのが大変めんどくさくなリマス。是非スクリプト化して効率的な開発をして頂ければと思います！もっといい方法ご存知の方は教えて頂けたら嬉しいです！ではまた！