はじめに
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にデプロイしました。
スクリプトからのデプロイ
本題のデプロイスクリプトを作成していきます。
今回はNode.jsでThirdweb SDKとethers.jsを使用してデプロイします。
準備
デプロイにはThirdwebのEndpointが必要です。ThirewebにログインしてSettingsからCreateAPIKeyでEndpointを作成して、ClientIDとSecretを控えてください。
SecretはEndpointを作成したタイミングでしか取得できないので注意
Endpointを作成したらClientID、Secretを.envファイルに記載します。
ついでにウォレットの秘密鍵も必要になるので、こちらも記載します。
これらの情報は絶対にGit Hub等に公開しないように注意してください。特に秘密鍵は流出するとトークンが盗まれる可能性があります。
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に含まれます。
デプロイスクリプトの作成
デプロイスクリプトでは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 デプロイする
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を一応残しておきます
{
"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のエクスプローラーからコントラクトアドレスで検索するとデプロイされていることが確認できます。
コントラクトデプロイ時に初期パラメータなんかを流し込みたい場合はこのスクリプトの中でトランザクションを流してあげることも可能です。(気が向いたら記事にします)
終わりに
Thirdweb、簡単にコントラクトを作れて便利なのですが開発中なんかはしょっちゅうデプロイするので、いちいちGUIでパラメータ入れるのが大変めんどくさくなリマス。是非スクリプト化して効率的な開発をして頂ければと思います!もっといい方法ご存知の方は教えて頂けたら嬉しいです!ではまた!