Solidity言語でスマートコントラクトを作るときにの個人的なメモ帳です。
逐次更新中
関数,変数
- msg.sender
- コントラクトを呼び出した一番最初のアドレスを返す
- msg.value
- 送金した金額
- tx.origin
- コントラクトを呼び出したアドレスを返す。
- コントラクト1 -> コントラクト2を呼び出したときは、コントラクト1のアドレスが返る。
- address.transfer(送金額)
- addressのアカウントに、コントラクトがweiで送金する。失敗したらフェイルバックする。
- address.send(送金額)
- addressのアカウントに、コントラクトがweiで送金する。
- address(this)
- コントラクトのアドレス
- address.balance
- weiで残高を返す
- now
- 現在の日時を返す
- now (uint): current block timestamp (alias for block.timestamp)
型
- uint
- boot
- address
- mapping
- bytes
- string
- struct
サンプルコード
- スマートコントラクト実行者に送金する。
function withdraw() returns(bool success) {
if( msg.sender ) {
// use the safe send pattern
if(msg.sender.send(amount) {
return true;
}
}
}
- コントラクトに送金されたら実行
function () payable{
uint amount = msg.value;
//いろいろ処理をする。
}
- スマートコントラクトを削除する
- 以前はsuicideという関数でしたが、自殺という名称が良くないので変わるらしいです。
// スマートコントラクトを削除する
function kill() { if (msg.sender == owner) selfdestruct(owner); }
- 配列の一部削除
配列の添え字を-1してあげる必要があるので注意
//タグを全部検索する
for ( uint i = 0; i < getTagsIndex(index); i++ ) {
//一致するタグを検索
if ( sha3(item[index].tags[i]) == sha3(vTag) ) {
//最後のindexでないことを確認する。
if (i == getTagsIndex(index)) {
return false;
}
//タグ番号を1個前にずらす。
for ( uint j = i; j < getTagsIndex(index) - 1; j++ ) {
item[index].tags[j] = item[index].tags[j+1];
}
//最後の配列は空にする。
item[index].tags[getTagsIndex(index)] = "";
//配列削除するときはかならず-1すること。
item[index].tags.length = item[index].tags.length - 1;
//成功を返す
return true;
}
}
- 文字列比較
solidityは文字列の比較ができないので、文字列をsha3に変換して比較するとよいです。
function searchTags(string v_tag) constant returns (string){
if (sha3(item.tag) == sha3(v_tag) ){
return true;
}
}
- 配列の末尾に追加
pushを使うと、配列末尾に追加できる
function putComments(uint index, string vComment) public returns(bool) {
//コメント欄の最後に追記する
item[index].comment.push(vComment);
return true;
}
構造体
struct test{
string address;
uint amount;
}
- 最近のバージョンでは構造体も外部から参照可能
struct test{ string address; uint amount; } test public Test;
実行ユーザーを限定する方法
modifier onlyByProvider() {
require(msg.sender == provider);
_;
}
function functionName(bytes32 _name) public onlyByProvider {
}
ガス消費を抑えるコツ
- トランザクションに載せない変数
変数定義にmemoryを付ける
string[4] memory adaArr = ["This", "is", "an", "array"];
- 読み込みのみの関数にはconstantを付ける
function getItemName(uint i) constant returns (bytes ){
return item[i].name;
}
- String型からByte型に変換する
function stringToBytes(string memory s) public pure returns (bytes) {
bytes memory b = bytes(s);
return b;
}
- Byte32型からString型に変換する
function bytes32ToString(bytes32 x) public pure returns (string) {
bytes memory bytesString = new bytes(32);
uint charCount = 0;
for (uint j = 0; j < 32; j++) {
byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
if (char != 0) {
bytesString[charCount] = char;
charCount++;
}
}
bytes memory bytesStringTrimmed = new bytes(charCount);
for (j = 0; j < charCount; j++) {
bytesStringTrimmed[j] = bytesString[j];
}
return string(bytesStringTrimmed);
}
エラー対策
Stack Too Deep
- 関数の引数や戻り値が多すぎると、このエラーが発生する。
対処としては、- ローカル変数を減らす
- 引数を減らす
- 返り値を減らす
- functionを分ける
- stringをbyte32にする
- structをネストする
struct Parts1{
string hoge1;
string hoge2;
string hoge3;
string hoge4;
string hoge5;
}
struct Parts2{
string fuga1
string fuga2;
string fuga3;
string fuga4;
string fuga5;
}
struct Matome{
Parts1 parts1;
Parts2 parts2;
}