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

```