Solidity 入門
SolidityはEthereum(イーサリアム)上で実行可能なプログラム言語です。
本記事ではSolidityの基本事項をまとめました👍
初めてSolidityを触る方、Solidityを復習したい方の参考となれば幸いです🤗
(随時更新予定です)
コントラクト
Solidityのコードはコントラクト内にカプセル化されている。
コントラクトはイーサリアムアプリケーションの基本ブロックのこと。
⬇︎コントラクトの例
pragma solidity ^0.4.19;
contract BookShop {
// イベントを設定してフロントエンドに通知できるようにする
event NewBook(string name);
struct Book {
string name;
uint dna;
}
function _getBook(string _name) private {
NewBook(_name);
}
}
Solidityでは、関数はデフォルトでpublicです。
別のコントラクトからでも実行できます。
マッピング
キーバリューストア。
//ユーザーIdとユーザー名をセットで格納
mapping (uint => string) userIdToName;
アドレス型
銀行の口座番号のようなもの。アカウントに固有な値。
(グローバル変数である、msg.sender
を使用することで、関数を呼び出したユーザー(またはスマートコントラクト)の addressを参照できる。)
mapping (address => uint) favoriteBook;
function setMyBook(uint _myBook) public {
// ユーザーのアドレスにデータを格納
favoriteBook[msg.sender] = _myBook;
}
関数
view修飾子とpure修飾子
view修飾子は読み取り専用であることを示します。
string greeting = "hello solidity!!";
function sayHello() public view returns (string) {
return greeting;
}
pure修飾子はアプリ内のデータにすらアクセスできない関数であることを示します。
function _add(uint a, uint b) private pure returns (uint) {
return a + b;
}
ガス
・ガス
Solidityでは、ユーザーが関数を使用するたびにガスと呼ばれる通貨を支払うことになっている。ユーザーはEtherでガスを買い、関数を実行する。
関数を実行するために必要なガスの量は、その操作を実行するためにどれくらいの計算資源が必要になるのかで決まっている。
➡️ コードの最適化が重要
例えば、structの中において、できる限り小さい単位の uintを使うことで、Solidityが複数の変数をまとめて、ストレージを小さくすることが可能である。
⬇︎ MiniMeを使用した方がガスコストが低い
struct NormalStruct {
uint a;
uint b;
uint c;
}
struct MiniMe {
uint32 a;
uint32 b;
uint c;
}
また、ブロックチェーン上でなにも変更しない=ブロックチェーン上にトランザクションを生成する必要がない、という理由からview関数を外部から呼び出す場合、ガスは一切かからない。
ストレージとメモリ
Storageキーワード
ブロックチェーン上に永久に格納される変数。
コントラクトのストレージ上でアドレス(ポインタ)として扱われる。
Solidityでstorageへの操作は高コストである。(ガスコストが高い)
← データを書き込んだり、変更するたびに、それがすべてブロックチェーンに永久に書き込まれるため。永久に、世界中の何千個というノードがすべてそのデータをハードドライブに書き込む必要があり、そのデータ容量はブロックチェーンが成長すればするほど大きくなる。故にどうしてもコストは高くなる。
そこで、コストを抑えるためには絶対に必要な場合を除いてデータをstorageに書き込まないようにする。
Memoryキーワード
一時的な変数。メモリ上に新たな領域が確保される。
例
contract CookieFactory {
struct Cookie {
string name;
string status;
}
Cookie[] Cookies;
function eatCookie(uint _index) public {
// `storage`で宣言
Cookie storage myCookie = cookie[_index];
//...`mySandwich`がstorage内で`cookies[_index]`に
// ポインタをさす場合...
myCookie.status = "Eaten!";
// ...この場合`cookies[_index]`をブロックチェーン上で永久に変更することになる
// コピーしたいだけなら、`memory`の方が便利
Cookie memory anotherCookie = cookies[_index + 1];
// ...この場合`anotherSandwich`は memory内のデータを
// コピーすることになる...
anotherCookie.status = "Eaten!";
// ...一時的な変数を変更するだけで、`sandwiches[_index + 1]`には
// なんの影響もない
}
}