Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
15
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

Organization

Solidityによるコントラクトの作成(1) - 基礎

今回はSolidityを用いたコントラクトの作り方について説明致します。

開発環境
OS : OSX 10.11.4

Ethereumインストール

Ethereumをインストールしていない方は、インストールしてください。
Consoleで以下のコマンドを叩けばインストールされます。

bash <(curl https://install-geth.ethereum.org -L)

その他のインストール方法についてはこちらを参考にしてください。

Ethereum立ち上げ

続いてEthereumをを立ち上げましょう。今回はテスト用に使うため、Private_netを立ち上げます。

geth --networkid "11"  --datadir "path_to_directory" --genesis "path_to_genesisjson" console

--networkid:networkIDを指定します。1,2,3以外の数字を使いましょう。
--genesis :genesis blockを指定します。
--datadir :databaseのあるディレクトリを指定します。
console  :consoleを開くために必要です。

geth command line options

コントラクト作成

早速コントラクトを記述してみましょう。言語はSolidityを使います。
(事前にsolidityコンパイラ(solc)がインストールされているか確認してください。されてない場合はこちらの記事に沿ってインストールしてください。)

エディタで次のようなコントラクトを記述しましょう。これはEthereum上に独自のコインを作るためのコントラクトです。

token.sol
contract token { 
    mapping (address => uint) public coinBalanceOf;
    event CoinTransfer(address sender, address receiver, uint amount);

  /* Contract初期化のための関数。contract名と同じにする */
  function token(uint supply) {
        coinBalanceOf[msg.sender] = supply;
    }

  /* コインを送るための関数 */
    function sendCoin(address receiver, uint amount) returns(bool sufficient) {
        if (coinBalanceOf[msg.sender] < amount) return false;
        coinBalanceOf[msg.sender] -= amount;
        coinBalanceOf[receiver] += amount;
        CoinTransfer(msg.sender, receiver, amount);
        return true;
    }
}

このコントラクトから改行を削除します。テキストから改行を削除する方法についてはこちらの記事を参考にしてください。

token_one_line.sol
contract token {    mapping (address => uint) public coinBalanceOf;    event CoinTransfer(address sender, address receiver, uint amount);  /* Contract初期化のための関数。contract名と同じにする */  function token(uint supply) {        coinBalanceOf[msg.sender] = supply;    }  /* コインを送るための関数 */    function sendCoin(address receiver, uint amount) returns(bool sufficient) {        if (coinBalanceOf[msg.sender] < amount) return false;        coinBalanceOf[msg.sender] -= amount;        coinBalanceOf[receiver] += amount;        CoinTransfer(msg.sender, receiver, amount);        return true;    }}

コンパイル

続いて、solcを用いてコントラクトをコンパイルします。

> var source = "contract token {    mapping (address => uint) public coinBalanceOf;    event CoinTransfer(address sender, address receiver, uint amount);  /* Contract初期化のための関数。contract名と同じにする */  function token(uint supply) {        coinBalanceOf[msg.sender] = supply;    }  /* コインを送るための関数 */    function sendCoin(address receiver, uint amount) returns(bool sufficient) {        if (coinBalanceOf[msg.sender] < amount) return false;        coinBalanceOf[msg.sender] -= amount;        coinBalanceOf[receiver] += amount;        CoinTransfer(msg.sender, receiver, amount);        return true;    }}"
> var compiledSource = eth.compile.solidity(source)

これでコンパイルは完了しました。続いてコンパイルしたコードをEthereumのネットワークに送信します。

> var abiDefinition = compiledSource.token.info.abiDefinition
> var compiledContract = eth.contract(abiDefinition)
> var supply = 10000
> var contract = compiledContract.new(supply, {from:eth.accounts[0], data: compiledSource.token.code, gas:1000000})

これでネットワークへの送信は完了しました。しかしまだマイニングは行われていないので、このコントラクトは承認されていません。そのためaddressもまだ未定です。

> contract
{
  address: undefined,
  transactionHash: "0x09b7b27e8d948b601ef1dd0548c7d33604c2fc7b8ee31d7d8e637f66da302a69"
}

マイニングが完了すると以下のようにaddressが付与されます。

> contract
{
  address: "0xb4ffc81cb032941a6cfd29f1f1817dc76413fae6",
  transactionHash: "0x09b7b27e8d948b601ef1dd0548c7d33604c2fc7b8ee31d7d8e637f66da302a69",
  CoinTransfer: function(),
  allEvents: function(),
  coinBalanceOf: function(),
  sendCoin: function()
}

コントラクトのメソッドを用いる

コントラクトで定義されているメソッドを呼び出してみましょう。
以下のsendCoinメソッドは引数を2つとります。1つ目は受取主、2つ目は送金額です。

> contract.sendCoin.sendTransaction(eth.accounts[1], 1000, {from: eth.accounts[0]})
I0511 22:09:00.939817    8397 xeth.go:1028] Tx(0xcd1003befe323aa1cdaee4e81e032b07cfe70fffc33400f46d033dc86cf4c4a1) to: 0xb4ffc81cb032941a6cfd29f1f1817dc76413fae6
"0xcd1003befe323aa1cdaee4e81e032b07cfe70fffc33400f46d033dc86cf4c4a1"

メソッドがネットワークに送信されました。しかしまだマイニングされていないので、eth.accounts[0]の残高は10,000、eth.accounts[1]の残高は0のままです。

> contract.coinBalanceOf(eth.accounts[0])
10000
> contract.coinBalanceOf(eth.accounts[1])
0

マイニングを行います。すると残高が以下のように変化します。

> contract.coinBalanceOf(eth.accounts[0])
9000
> contract.coinBalanceOf(eth.accounts[1])
1000

以上がコントラクト内のメソッドの呼び出し方です。

外部からコントラクトにアクセスする

第三者がコントラクトにアクセスするにはAbiDefinitionaddressが必要です。今回の場合は以下になります。

> abiDefinition 
[{
    constant: false,
    inputs: [{
        name: "receiver",
        type: "address"
    }, {
        name: "amount",
        type: "uint256"
    }],
    name: "sendCoin",
    outputs: [{
        name: "sufficient",
        type: "bool"
    }],
    type: "function"
}, {
    constant: true,
    inputs: [{
        name: "",
        type: "address"
    }],
    name: "coinBalanceOf",
    outputs: [{
        name: "",
        type: "uint256"
    }],
    type: "function"
}, {
    inputs: [{
        name: "supply",
        type: "uint256"
    }],
    type: "constructor"
}, {
    anonymous: false,
    inputs: [{
        indexed: false,
        name: "sender",
        type: "address"
    }, {
        indexed: false,
        name: "receiver",
        type: "address"
    }, {
        indexed: false,
        name: "amount",
        type: "uint256"
    }],
    name: "CoinTransfer",
    type: "event"
}]
> contract.address
"0xb4ffc81cb032941a6cfd29f1f1817dc76413fae6"

上記のデータを用いて、コントラクトにアクセスする変数を作成します。

> var theContract = eth.contract(abiDefinition).at(contract.address)
> theContract
{
  address: "0xb4ffc81cb032941a6cfd29f1f1817dc76413fae6",
  CoinTransfer: function(),
  allEvents: function(),
  coinBalanceOf: function(),
  sendCoin: function()
}

これで第三者がコントラクトにアクセス出来るようになりました。

まとめ

以上Solidityを使ったコントラクトの作成方法でした。次回はSolidityを用いたデリバティブの実装方法についてご説明致します。

参考記事

https://ethereum.gitbooks.io/frontier-guide/content/ether_transfer.html
http://book.ethereum-jp.net/first_use/contract.html
https://solidity.readthedocs.io/en/latest/index.html
http://linux.just4fun.biz/%E9%80%86%E5%BC%95%E3%81%8DUNIX%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89/%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%81%8B%E3%82%89%E6%94%B9%E8%A1%8C%E3%82%92%E5%89%8A%E9%99%A4%E3%81%99%E3%82%8B.html

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
15
Help us understand the problem. What are the problem?