Solidity
ガス
ユーザが関数を実行するたびにガスと呼ばれる通貨を支払うことになる
ユーザは実際にお金を使って関数を動かすことになるから、イーサリアムは他のプログラミング言語よりもずっとコードの最適化が重要になる ユーザにストレージと計算時間について支払うことで、無限ループを起こしてネットワークをつまらせたりネットワークの計算資源を無駄にしないことを意図している
uint8などの型により容量を節約できる
view関数の実行にはコストはかからない
ブロックチェーン上にトランザクションを発生させる必要がなく、ローカルのイーサリアムノードに問い合わせるだけで良いため storageへの書き込みはコストが高い
すべてのブロックチェーンに永久に書き込むため
絶対に必要な場合を除いてデータをstorageに書き込まないようにする
一見非効率的なロジックを作ることもある
単純に配列を変数に保存するかわりに、関数を呼び出す毎にmemory上の配列を再構築する
ループで計算量が増えたとしてもview関数にするほうがコストが低い
時間
Solidityでは時間を扱う機能がある
now - 1 daysのような計算ができる
関数の可視性を制御する関数修飾子
private
internal
コントラクト内の別の関数、または継承したコントラクトからのみ呼び出される external
public
デフォルトではpublicになる
関数の状態を制御する状態修飾子
view
関数が動作してもなんのデータも保存・変更されないことを示す
pure
関数が動作してもなんのデータも保存・変更されない、かつブロックチェーンからデータを読み込むこともないことを示す
上記の2つはコントラクト外から呼び出されてもガスを必要としない
カスタムのmodifier
開発者が定義するもの
1つの関数に複数個のmodifierをつけることもできる
payable
payable修飾子がない関数にEtherを送ろうとすると関数がトランザクションを拒否する 関数内でmsg.valueを見るとどのぐらいEtherが送られたかわかる
例
code:onlinestore.sol
contract OnlineStore {
function buySomething() external payable {
require(msg.value == 0.001 ether);
transferThing(msg.sender);
}
}
code:web3.js
OnlineStore.buySomething({from: web3.eth.defaultAccount, value: web3.utils.toWei(0.001)})
コントラクトに送られたEthはコントラクトのEthereumアカウントに貯められ、引き出すまではそのまま
this.balanceで確認できる
transfer
Etherをあるアドレスに送ることができる
owner.transfer(this.balance)
ownerが引き出す
msg.sender.transfer(msg.value - itemFee)
余分に送られたEtherを送り返す
seller.transfer(msg.value)
販売者のaddressをstorageに保存しておいて、誰かが販売者のアイテムを購入する際に、購入者が支払った料金を販売者に送金する
継承
code:solidity
contract Z is A,B {
}
library
contractと似た構文で定義する
code:solidity
library A {
function add(uint256 _a, uint256 _b) internal pure returns(uint256) {
return _a + _b;
}
}
別のデータ型にメソッドを追加できる
code:solidity
using A for uint;
uint a = 100.add(1); // a == 1001
変数
publicの変数を宣言すると自動的にgetterが作成される
Event
イベントは安価なストレージ、ログとして利用できる
Web3.jsのフロントエンドで参照することはできるがコントラクト内から読み取ることはできない