先日イーサリアムnaviでおこなった「コントラクトコードの輪読会」という勉強会のレポートを、記事としてまとめていきます。
今回の勉強会は、Lootというボトムアップ型NFTのコントラクトを読んで、SolidityならびにLootについての理解を深めることを目的としたものでした。
![](https://ethereumnavi.com/wp-content/uploads/2021/11/HIDE記事アイキャッチ-300x199.jpg)
勉強会当日は、1時間半ほどzoomを使いながら進めていきましたが、非常に満足度の高い勉強会となり、これからSolidityの勉強をしたい人にも役に立つ内容だったため、備忘録としてレポートにしておこうと考えました。
本記事では
- 「Loot」のコードを見てみよう
- 「uint256」とは?
- 「Keccak256」とは?
- 「abi.encodePacked」とは?
- 「nonReentrant」とは?
- SVGについて
- Solidityにランダム関数はないの?
- まとめ
という構成で、第一回コントラクト輪読会レポートとしてまとめていきたいと思います。
本記事が、皆さんの「Loot」「Solidity」への理解の一助となりましたら幸いです。
※本記事は一般的な情報提供を目的としたものであり、法的または投資上のアドバイスとして解釈されることを意図したものではなく、また解釈されるべきではありません。ゆえに、特定のFT/NFTの購入を推奨するものではございませんので、あくまで勉強の一環としてご活用ください。
イーサリアムnaviの活動をサポートしたい方は、「定期購読プラン」をご利用ください。
「Loot」のコードを見てみよう
![](https://ethereumnavi.com/wp-content/uploads/2021/11/tbl-12GFg-1024x545.png)
まず、Etherscanからコントラクトのコードを見てみましょう。
![](https://ethereumnavi.com/wp-content/uploads/2021/11/uoN4OMgjM-1024x548.png)
トランザクションを確認する際は「Transactions」の欄を見ますが、コードを読む際は「Contracrt」の欄を使います。
![](https://ethereumnavi.com/wp-content/uploads/2021/11/wsJv_e4cY-1024x542.png)
![](https://ethereumnavi.com/wp-content/uploads/2022/02/でりおツイッター用_サングラスあり-150x150.png)
この勉強会前まで素人であった筆者は、Command + Fでキーワード(Loot, mint…etc)を検索して、読みたいコードを探していました。
しかし、Etherscanでコードを読む際にはもっと良い方法があると教えていただいたので、最初にそれについて話します。
上写真のピンク枠左側の「Outline」から、各functionの内容を確認できます。
![](https://ethereumnavi.com/wp-content/uploads/2021/11/8Sb2lLR9K-1024x544.png)
![](https://ethereumnavi.com/wp-content/uploads/2021/11/8Sb2lLR9K-1024x544.png)
この検索機能により、調べたいfunction・気になるfunctionを見つけやすくなりますね。
さらに、ピンク枠右側の「More Options」から「Sol2Uml」をクリックすると、「Solidity UML Diagram」というものが見れます。
![](https://ethereumnavi.com/wp-content/uploads/2021/11/G-mjGDaAR-1024x546.png)
![](https://ethereumnavi.com/wp-content/uploads/2021/11/G-mjGDaAR-1024x546.png)
この機能により、.solファイルの構成や結びつきを俯瞰的に見ることができるようになるので、コントラクトの全体像を視覚的に理解しやすくなります。
「uint256」とは?
![](https://ethereumnavi.com/wp-content/uploads/2021/11/3Ymnkd2mk-1024x454.png)
![](https://ethereumnavi.com/wp-content/uploads/2021/11/3Ymnkd2mk-1024x454.png)
Solidityではよく出てきますが、符号なし整数のことです。
一般的には整数表記でint
を用いますが、Ethereumでは金額(ETH)を扱うことが多くあまりマイナス表記を使わないという理由で、uint
が用いられると聞いたことがあります。
uint
は、uint8
からuint256
まで8の倍数の型が存在し、この8の倍数の数字はbit数(パソコンが一度の処理に扱えるデータの大きさ)を表しています。
読み方の通称は「ユーイント にごろ」だそうです。
「Keccak256」とは?
![](https://ethereumnavi.com/wp-content/uploads/2021/11/9LU1mwbPl-1024x655.png)
![](https://ethereumnavi.com/wp-content/uploads/2021/11/9LU1mwbPl-1024x655.png)
Ethereumで使われるハッシュ関数で、読み方の通称は「ケチャック にごろ」です。
ハッシュ化と聞くとややこしい印象をもつ方もいるでしょうが、Ethereumのアドレスも、公開鍵をkeccak256
でハッシュ化したものの一部が使われています。
この後の『abi.encodePacked
とは?』でも述べますが、Solidityでは文字(string)の扱い方がやや難しいため、keccak256
が使われる場面が多いです。
「abi.encodePacked」とは?
![](https://ethereumnavi.com/wp-content/uploads/2021/11/U3pKlA4UH-1024x654.png)
![](https://ethereumnavi.com/wp-content/uploads/2021/11/U3pKlA4UH-1024x654.png)
Solidityに組み込みで用意されている関数で、文字(string
)を結合する時に使います。
先ほども少し触れましたが、Solidityではstring
を扱うことが難しい仕様になっています。
例えば、
- 「筆者は」
- 「でりおてんちょーです」
Solidityを使ってこの2つの文字列を結合したい場合、『「筆者は」+「でりおてんちょーです」』ではダメなのです。
ではどうするかというと、「筆者は」と「でりおてんちょーです」をabi.encodePacked
を使って連結させる必要があります。
str1 = “筆者は”;
str2 = “でりおてんちょーです”;
abi.encodePacked(str1, str2);
また、上の場合は「連結」のパターンでしたが、Solidityで文字列を「比較」する際には、一度Keccak256関数を使って文字列をbytes32
型にハッシュ化して、その値同士で比較しなければなりません。
keccak256(abi.encodePacked(str1)) == keccak256(abi.encodePacked(str2))
![](https://ethereumnavi.com/wp-content/uploads/2022/02/でりおツイッター用_サングラスあり-150x150.png)
![](https://ethereumnavi.com/wp-content/uploads/2022/02/でりおツイッター用_サングラスあり-150x150.png)
![](https://ethereumnavi.com/wp-content/uploads/2022/02/でりおツイッター用_サングラスあり-150x150.png)
このあたりの話は、以下doublejump.tokyo満足さんの資料が大変参考になるので、興味のある方はご覧ください。
![](https://ethereumnavi.com/wp-content/uploads/2021/11/DNuN3sCHr-1024x478.png)
![](https://ethereumnavi.com/wp-content/uploads/2021/11/DNuN3sCHr-1024x478.png)
Lootでは上写真のように、文字だけが載った画像として出力されています。
![](https://ethereumnavi.com/wp-content/uploads/2021/11/6YUiCpfIR-1024x359.png)
![](https://ethereumnavi.com/wp-content/uploads/2021/11/6YUiCpfIR-1024x359.png)
これは、先に述べた「文字列の結合」の話で、abi.encodePacked(parts[0], parts[1], parts[2], ... , parts[16]))
によって、文字列をどうにかひと固まりにしてoutput
に値を格納していることが分かりますね。
「nonReentrant」とは?
![](https://ethereumnavi.com/wp-content/uploads/2021/11/I9bnW5fmk-1024x663.png)
![](https://ethereumnavi.com/wp-content/uploads/2021/11/I9bnW5fmk-1024x663.png)
nonReentrantは、Reentrancy攻撃対策のためのコントラクトモジュールです。
![](https://ethereumnavi.com/wp-content/uploads/2022/02/にわとり-150x150.png)
![](https://ethereumnavi.com/wp-content/uploads/2022/02/にわとり-150x150.png)
![](https://ethereumnavi.com/wp-content/uploads/2022/02/にわとり-150x150.png)
Reentrancy攻撃って何ですか?
という話は長くなるので割愛しますが、その昔あった「The DAO事件」でも用いられた攻撃方法です。
OpenZeppelinには、ReentrancyGuardと呼ばれる使用可能な独自のmutex実装があり、このlibraryはmutexで関数をガードする「nonReentrant」と呼ばれる、すべての関数に適用できる修飾子を提供してくれています。
要は、LootでもReentrancy攻撃から守るために「nonReentrant」がつけられている訳なのですが、なぜ外部アドレスにETHを送るわけではないclaim関数とownerClaim関数にnonReentrantが必要なのかは不明です。
![](https://ethereumnavi.com/wp-content/uploads/2022/02/でりおツイッター用_サングラスあり-150x150.png)
![](https://ethereumnavi.com/wp-content/uploads/2022/02/でりおツイッター用_サングラスあり-150x150.png)
![](https://ethereumnavi.com/wp-content/uploads/2022/02/でりおツイッター用_サングラスあり-150x150.png)
ご存知の方がいたら、ぜひ教えてください。
ERC721のclaimでも内部でOpenZeppelinの_safeMintを呼び出すとすると、受け取り側がコントラクトの場合にERC721を受け取れるかをチェックします。
そのコントラクトのIERC721Receiver.onERC721Receivedを呼び出すので制御が受け取り側のコントラクトにいってしまうため、リエントランシー攻撃の対策が必要そうです。
SVGについて
![](https://ethereumnavi.com/wp-content/uploads/2021/11/h8eaJ9YOv-1024x315.png)
![](https://ethereumnavi.com/wp-content/uploads/2021/11/h8eaJ9YOv-1024x315.png)
「フルオンチェーン=100%SVGファイル」という訳ではありませんが、一般的にフルオンチェーンとよばれるNFTは、tokenURIにSVG形式で書かれているケースが多く、Lootもそれに当たります。
コントラクト上でメタデータを生成し、かつコントラクトを叩くとURLではないメタデータを返す点で、LootはフルオンチェーンNFTであると言えますね。
![](https://ethereumnavi.com/wp-content/uploads/2021/11/XmSZy8VJe.png)
![](https://ethereumnavi.com/wp-content/uploads/2021/11/XmSZy8VJe.png)
ちなみに余談ですが、「Autoglyphs」というフルオンチェーンNFTのtokenURIは、こんな(↓)感じです。
![](https://ethereumnavi.com/wp-content/uploads/2021/11/wdiTNE0Vw-1024x452.png)
![](https://ethereumnavi.com/wp-content/uploads/2021/11/wdiTNE0Vw-1024x452.png)
「コントラクト上でメタデータを生成し、かつコントラクトを叩くとURLではないメタデータを返す」を満たしていますね!
フルオンチェーンNFTの場合、メタデータもEthereumブロックチェーン上に載せられていることから、Ethereumブロックチェーンが消滅しない限り、画像データもなくならないことを保証してくれています。
しかし、Lootのような文字だけなら問題ないですが、容量が大きくなってしまうとEthereumチェーンにのせるためのコスト(gas代)が膨大になってしまう問題が発生します。
![](https://ethereumnavi.com/wp-content/uploads/2022/10/made-724kb-jpg-image-fully-on-chain-nft-300x158.jpg)
![](https://ethereumnavi.com/wp-content/uploads/2022/10/made-724kb-jpg-image-fully-on-chain-nft-300x158.jpg)
Solidityにランダム関数はないの?
結論から言うと、Random.range
のような組み込みで用意されたランダム関数は存在しません。
Solidityの設計思想に「スマートコントラクトはインプットが同じであれば、必ず同じ結果が返される」とあるため、Solidityには乱数生成の処理はないみたいです。
また、そもそもの話、ブロックチェーン上でランダム関数を作るのは難しい問題があるそうです。
例えば、ブロック番号を使ってハッシュ値の計算を行い、それを10や100で割った余りで0〜9、0〜99の乱数を生成する方法が考えられますよね?
しかし、ブロック番号を使うということはマイナーが操作することも理論的には可能なので、厳密には乱数ではないことになってしまいます。
以上の理由から、Solidityには組み込みで用意されたランダム関数が存在しないみたいですが、最近だとChainlinkがVRFというものを用意しているそうです。
まとめ
本記事では、先日イーサリアムnaviでおこなった「コントラクトコードの輪読会」という勉強会のレポートを、記事としてまとめました。
![](https://ethereumnavi.com/wp-content/uploads/2022/02/でりおツイッター用_サングラスあり-150x150.png)
![](https://ethereumnavi.com/wp-content/uploads/2022/02/でりおツイッター用_サングラスあり-150x150.png)
![](https://ethereumnavi.com/wp-content/uploads/2022/02/でりおツイッター用_サングラスあり-150x150.png)
筆者は今までSolidityの勉強を独学でおこなってきましたが、初めてイベントのような形式でSolidityについて学び、理解を深めることができた点で、非常に新鮮で有意義な勉強会だったように感じました。
昨今はコロナ禍ということもあり、なかなかオフラインでのイベントも開催しづらいので、こういった形式の勉強会は今後も企画していきたいと考えています!
![](https://ethereumnavi.com/wp-content/uploads/2021/12/still-lp-1-1024x436.png)
![](https://ethereumnavi.com/wp-content/uploads/2021/12/still-lp-1-1024x436.png)
イーサリアムnaviを運営するSTILL合同会社では、web3/crypto関連のリサーチ代行、アドバイザー業務、その他(ご依頼・ご提案・ご相談など)に関するお問い合わせを受け付けております。
まずはお気軽に、こちらからご連絡ください。
- 法人プランLP:https://ethereumnavi.com/lp/corporate/
- Twitter:@STILL_Corp
- メールアドレス:info@still-llc.com