![見出し画像](https://assets.st-note.com/production/uploads/images/74178247/rectangle_large_type_2_86de52a54f2d3a5ce4acc295ccaeb5e1.png?width=800)
【保存版】更新可能なコントラクトを作ってみよう(なぜ可能かも理解しましょう)
こんにちは、CryptoGamesの高橋です。
クリスペの会社です。
また、CryptoMaidsのアンバサダーを務めさせていただいております。
始める前に
・秘密鍵を扱うことになります。慣れないうちは、テストアカウントで実施するようにお願いします。秘密鍵の扱いは厳重にお願いします。
0 はじめに
まず、基本的にコントラクトは変更することができませんね。
でも、バグが見つかったり、機能を追加したいなどでコントラクト(コード)を修正することができたら幅が広がりそうです。
実は、Openzeppelinのプラグインを使うことで、状態である
①state、②balance、③addressを保持したまま、コードを変えることができます!
1 Hardhatを使ってテストをしてみよう
では、実際にHardhatを使って、更新可能なコントラクトを作ってみましょう。
Hardhatの使い方が不明な場合は、こちらをご参照ください。
また、こちらのOpenZeppelinの公式ドキュメントを元に進めておりますので、コードのコピペなど、こちらをご利用ください。
では進めていきましょう。
2 「deployProxy」を使ってデプロイしよう
実はdeployProxyを使ってデプロイをすることで、後にアップグレードが可能となります。
なお、アップグレードができるのは、最初にデプロイを行ったアドレスだけです。
![](https://assets.st-note.com/img/1647147347087-9u5rhgvB2r.png?width=800)
また、内部処理としましては、「deployProxy」は次の3つをデプロイします。(大事です。)
① 実装コントラクト(Boxコントラクト)
② ProxyAdminコントラクト
③ proxy コントラクト
![](https://assets.st-note.com/img/1647160968179-jTfGrl4H4T.png?width=800)
3 Upgradable用のコントラクトを作る
OpeenZeppelinのコード貼り付けました。
こちらが基本となるコードとなります。
![](https://assets.st-note.com/img/1647148144278-3Xc9ZkipIL.png?width=800)
4 Hardhat-upgradesの環境設定
4ー1 インストール
下のように、インストールを行いましょう。
npm install --save-dev @openzeppelin/hardhat-upgrades
![](https://assets.st-note.com/img/1647148294536-nPPKeAKi6N.png?width=800)
4ー2 hardhat.config.jsの設定
インストールしたhardhat-upgradesを使用するために「hardhat.config.js」で下のように設定します。
![](https://assets.st-note.com/img/1647149125874-2E8J0yHJIY.png?width=800)
コードはこちらです。
require("@nomiclabs/hardhat-waffle");
require("@nomiclabs/hardhat-ethers");
require("@openzeppelin/hardhat-upgrades");
/** * @type import('hardhat/config').HardhatUserConfig */module.exports = { solidity: "0.8.0",};
なお、Ethers.jsとWaffleプラグインを利用するため、すでに下のコマンドも実施済みです。
npm install --save-dev @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai
5 デプロイ用のファイルを作る
アップグレードができるコントラクトを作るためにはデプロイ時のやり方がいつもと異なります。
下のように「deployProxy」を使います。
![](https://assets.st-note.com/img/1647149638446-QkUSc0Mo7x.png?width=800)
今回は初期化のために「store」を呼び出し、初期値として42を設定します。
hardhatとしてはこんな感じです。
![](https://assets.st-note.com/img/1647149650468-grqHtXu2Np.png?width=800)
6 Rinkebyでのデプロイの実施
では、Rinkebyでデプロイを行なってみましょう。
(ローカルネットワークで最終的にうまくいかなかったため。)
![](https://assets.st-note.com/img/1647156427091-jcSw1Cx5dA.png?width=800)
このようになれば成功です。
0x8033F3eb4b811F09C482eaB47b8C764b57701579
として作られたようです。
npx hardhat run scripts/deploy_upgradeable_box.js --network rinkeby
7 コントラクトに設定した値を確認する
hardhat consoleを用いて、コントラクトの中身を確認してみましょう。
npx hardhat console --network rinkeby
![](https://assets.st-note.com/img/1647156676476-5e1Ue9f4eJ.png?width=800)
上のように、今回作られたコントラクトアドレスを入れています。
(皆さん自身のコントラクトアドレスを入れてください。)
box.retrieve()を行うと、第5章で設定した「42」という値が返ってきました。
8 更新用コントラクトを作成する
では、更新用のコントラクトを作ってみましょう。
内容は格納されている値に1を加える機能の追加です。
![](https://assets.st-note.com/img/1647157145350-dJ6FrsAPdO.png?width=800)
先ほどの値は「42」でしたので、これを使うことができれば、値を「43」にすることができます。
![](https://assets.st-note.com/img/1647157388012-2NmSFFySB0.png?width=800)
コードはこちらです。
// Increments the stored value by 1
function increment() public {
_value = _value + 1;
emit ValueChanged(_value);
}
9 upgradeProxyを準備する
アップグレードを行うために、「upgradeProxy」を使います。
ちなみに、「upgradeProxy」が作るトランザクションは
① 実装コントラクト(BoxV2 コントラクト)
② proxyContractをアップデートするためにProxyAdminを呼び出す
![](https://assets.st-note.com/img/1647161637377-FvvEsR5Btf.png?width=800)
![](https://assets.st-note.com/img/1647161651616-KiNmTwZkeQ.png?width=800)
ちなみに、ProxyAdminは「deployProxy」で作られましたね。
![](https://assets.st-note.com/img/1647158281773-ZFIlllTlo2.png?width=800)
10 デプロイしてみよう
コンソール画面のままの場合はCtrl + Cで抜けましょう。
抜けましたら、デプロイを行ってみましょう。
npx hardhat run scripts/upgrade_box.js --network rinkeby
![](https://assets.st-note.com/img/1647158510960-8obN4Zzi0u.png?width=800)
11 コントラクトが更新されたことを確認しよう
hardhat consoleを使ってコントラクトが更新されたことを確認しましょう。
更新前は+1を行う機能がありませんでした。
そのため、+1の機能を実行でき、結果を確認することができれば、コントラクトが更新されたことを確認できます。
![](https://assets.st-note.com/img/1647159262233-mwgznBThig.png?width=800)
上のように、コントラクトが更新されたことが確認できました。
12 アップグレードの仕組みは?
ここがとても大事だと思います。
なぜ状態を保持したまま、コードの更新ができるのでしょうか?
![](https://assets.st-note.com/img/1647162393627-nfr65hOu6o.png?width=800)
それは、コードとステートのコントラクトが分離しているからです。
![](https://assets.st-note.com/img/1647162229949-WvKv0FVSPW.png?width=800)
ご興味のある方は、ぜひ、公式のドキュメントも読んでみてください。
以上です。
サポートをしていただけたらすごく嬉しいです😄 いただけたサポートを励みに、これからもコツコツ頑張っていきます😊