Edited at

Solidity言語メモ


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;
}