ブロックチェーンゲーム制作チェーン -Minimal Arcade Medal-

ブロックチェーン技術、ゲーム作成のためのコード、ドット絵やアニメーションの作り方を解説するブログです。最終的に記事の内容を組み合わせることで誰でもブロックチェーンゲームが作れるようにしたいです。Micro Arcade MedalというdApps開発中です。

Solidityチートシート :CryptZombies

CryptZombiesを完了しました!


さぁ、スマコンを書こう!と意気込んだものの、
開発中にあれってどう書くんだっけ?となるのが目に見えます。


なので忘れないうちにCryptZombiesに出てきたキーワードまとめます!

contract

pragma solidity ^0.4.19; //solidityのコンパイラのバージョン指定

contract HelloWorld { //contract name {}で作れる

}

struct

struct Person { //struct name {datatype name; datatype name...}
  uint age;
  string name;
}

array

Person[] public people;
//peopleはpublicな変数であり、Person型の配列を確保している
//publicをつけるとgetterが自動で作成される
//people.push(Person(16,"Gyo"))でデータを追加できる

function

function eatHamburgers(string _name, uint _amount) {
//function name(datatype name, datatype name ) returns (datatype) {処理}
//関数から値返すときはreturnsに続けて型を書く
}

event

event IntegersAdded(uint x, uint y, uint result); 
//イベントを定義
//フロントエンドに渡したい値をevent宣言内に記述

function add(uint _x, uint _y) public { 
  uint result = _x + _y;
 
  IntegersAdded(_x, _y, result);
//addが呼ばれたときにイベント発火
// 定義した引数を入れる
  return result;
}

//--------------------

// フロントエンドのjavascript
YourContract.IntegersAdded(function(error, result) { 
//発生したeventはフロントサイドからContract名.Event名でアクセスできる。
//渡された値を使ってコールバック関数で処理を行う。
}

mapping

mapping(address => uint) public accountBalance;
//addressは口座番号のようなもの
//contractにアクセスしているaddressはmsg.senderで参照できる

//accountBalance内には
//{address key: uint value, address key: uint value,,,,}
//keyとvalueのペアが保存される

require & assert

function hoge(string huga) public returns (string) {
 
require(huga == "hugahuga")
//真ならばここから先の関数が処理される
//偽ならばエラーを投げて実行を止める
//ガスの残りは返却される

  return "YES hugahuga";
}

//------------
assert(huga == "hugahuga")

//assertも同じ役割を果たすが、関数呼び出しが失敗した場合、ユーザーにガスの残りを返却しない
//重大な間違いが起こった場合に使用される(uintのオーバーフローなど)

is (継承)

contract Doge {
  function catchphrase() public returns (string) {
    return "So Wow CryptoDoge";
  }
}

contract BabyDoge is Doge {
//ロジック毎にコードを整理するのに便利
//親の変数や関数にアクセス可
// is hoge, hugaで多重継承可

  function anotherCatchphrase() public returns (string) {
    return "Such Moon BabyDoge";
  }
}

import

import "./someothercontract.sol";
//他のファイルからcontractを読み込む
//./は同じディレクトリという意味

contract newContract is SomeOtherContract {

}

storage & memory

Sandwich storage mySandwich = sandwiches[_index];

Sandwich memory anotherSandwich = sandwiches[_index + 1];

//型がstructsやarraysの変数を使用する時に明示する必要あり

//storageはブロックチェーン上に永久格納
//状態変数(関数外で宣言された変数)の場合デフォルでstorage

//memoryは一時的な変数
//関数内で宣言された変数はデフォルトでmemory

view & pure

関数の修飾子
function huga() public view returns(string){}のように書く。
view関数ではデータの編集はできず、読み取り専用となる。
pure関数はアプリのデータにアクセスできない、つまり扱えるデータは引数のみとなる。

private, internal, external & public

関数につけてスコープを設定できる

function huga(string hoge) public {}
のように書く

  • private コントラクト内の別関数からのみ参照可
  • public コントラクト外部・内部どちらからでも参照可
  • internal 上記に加え継承したコントラクトからも参照可
  • external コントラクト外からのみ参照可

interface

contract NumberInterface {
  function getNum(address _myAddress) public view returns (uint);
//interfaceを書くときは関数の中身は書かない
}

contract MyContract {
  address NumberInterfaceAddress = 0xab38...; 
  // イーサリアム上の別のコントラクトのアドレスが入る
  NumberInterface numberContract = NumberInterface(NumberInterfaceAddress);
  // 冒頭で書いたinterfaceを型として変数宣言
//interface(使いたい関数)

  function someFunction() public {
 
    uint num = numberContract.getNum(msg.sender);
    //別contractの関数getNumが使える
  }
}

modifier

//関数修飾子 function hoge(string hoga) public modifier(hoge) {}のように書く
//requireと組み合わせて関数を実行する前に特定の条件を満たしているか確認するとき使える
//引数を修飾する関数から引っ張ってこれる
modifier onlyOwner(string huga) {
    require(msg.sender == owner);
    _; //これを終わりにつけるのを忘れないように!
  }

payable

contract OnlineStore {
  function buySomething() external payable {
    // 0.001 etherが送られたことを確認
    require(msg.value == 0.001 ether);
    //0.001 etherが送られていたら、関数呼び出し元にトークンを譲渡する
    transferThing(msg.sender);
  }
}

//------------------
//web3.js(javascriptフロントエンド)からの関数呼び出し
OnlineStore.buySomething({from: web3.eth.defaultAccount, value: web3.utils.toWei(0.001)})
//valueで0.001etherを指定している

//------------------
contract GetPaid is Ownable { //コントラクトのイーサリアムアカウントからetherを引き出す方法
  function withdraw() external onlyOwner {
    owner.transfer(this.balance);
  }
}

ERC721

ERC721
ユニークで分割できないトークンを作れる。
erc721.solをimportし、以下の関数を実装する必要がある。

function balanceOf(address _owner) public view returns (uint256 _balance);
//addressを受け取り、addressのトークン保有量を返す

 function ownerOf(uint256 _tokenId) public view returns (address _owner);
//トークンIDを受け取り、所有者のaddressを返す

function transfer(address _to, uint256 _tokenId) public;
//送り先addressと送りたいトークンIDを受け取り、トークンを移転する
//送り手が呼び出す

function approve(address _to, uint256 _tokenId) public;
//addressとトークンIDを受けとり、mappingで保存

function takeOwnership(uint256 _tokenId) public;
//msg.senderがトークンを受け取ることを承認((approve))されているか確認し、承認済みの場合はトークンが譲渡される
//受け手が呼びだす

library

//contractを宣言するときのようにlibraryを宣言する
//libraryで記述された全メソッドを特定のデータ型に追加できる

//contract内でlibraryを使う場合、contract内に以下のように書く
using library for uint256


//assertと組み合わせることでオーバーフローやアンダーフロー対策ができる
//異なるデータ型ごとにlibraryを定義する必要がある

natspec

solidityのコミュニティで用いられるコメントのフォーマット。
他の開発者や自分に向けてコントラクトや関数を説明するのに使われる。

//@title
//@author
//@notice
//@param
//@dev