LoginSignup
5
5

More than 5 years have passed since last update.

Solidityによるコントラクトの作成(2) - オプション取引

Last updated at Posted at 2016-05-13

前回はSolidityの使い方についてご説明しました。今回はSolidityを用いてオプション取引を実装してみましょう。

コントラクト概要

今回はコール・オプションを実装します。コール・オプションとはある資産を買う権利のことです。(ちなみにある資産を売る権利をプット・オプションといいます)。

コール・オプションのカラムは以下のようにします。

key value
資産 ビットコイン
数量 1
権利行使価格 ¥50,000
プレミアム ¥5,000
期日 1463127335
売り手 0xfffe72483eb0bc804295af2416d2aeb4fa15a8bc
買い手 0x0e7b3774402f2f19a05e7a279238a4a1fe5e2bc0

14631273352016/05/13 8:15am(UTC)UNIX TimeStampです

以下が完成形のコードです

call_option.sol
contract CallOption{
    address public buyer;
    address public seller;
    uint public btc_amount;
    uint public btc_price;
    uint public premium;
    uint public exercise_date;
    mapping (address => uint) public balanceOfJPY;
    mapping (address => uint) public balanceOfBTC;
    function CallOption(
      address _seller,
      uint _seller_jpy,
      uint _seller_btc,
      uint _btc_price,
      uint _btc_amount,
      uint _premium,
      uint _exercise_date
      ){
      seller = _seller;
      balanceOfJPY[seller] = _seller_jpy;
      balanceOfBTC[seller] = _seller_btc;
      btc_price = _btc_price;
      btc_amount = _btc_amount;
      premium = _premium;
      exercise_date = _exercise_date;
    }
    function Respond (address _buyer, uint _buyer_jpy) {
      buyer = _buyer;
      balanceOfJPY[buyer] = _buyer_jpy;
      if (balanceOfJPY[buyer] < premium + btc_amount * btc_price) throw;
      balanceOfJPY[buyer] -= premium;
      balanceOfJPY[seller] += premium;
    }
    function Expire (uint _current_btc_price, uint _current_time){
      if (_current_time < exercise_date) throw;
      if (_current_btc_price < btc_price) throw;
      balanceOfJPY[buyer] -= btc_price * btc_amount;
      balanceOfJPY[seller] += btc_price * btc_amount;
      balanceOfBTC[buyer] += btc_amount;
      balanceOfBTC[seller] -= btc_amount;
    }
    function () {
      throw;
    }
}
  • CallOption:初期化(今回は、オプションの発行主体は常に売り手とします。)
  • Respond:買い手の登録
  • Expire:オプション実行

コントラクト登録

まずコードをコンパイルします。

> var source = "contract CallOption{    address public buyer;    address public seller;    uint public btc_amount;    uint public btc_price;    uint public premium;    uint public exercise_date;    mapping (address => uint) public balanceOfJPY;    mapping (address => uint) public balanceOfBTC;    function CallOption(      address _seller,      uint _seller_jpy,      uint _seller_btc,      uint _btc_price,      uint _btc_amount,      uint _premium,      uint _exercise_date      ){      seller = _seller;      balanceOfJPY[seller] = _seller_jpy;      balanceOfBTC[seller] = _seller_btc;      btc_price = _btc_price;      btc_amount = _btc_amount;      premium = _premium;      exercise_date = _exercise_date;    }    function Respond (address _buyer, uint _buyer_jpy) {      buyer = _buyer;      balanceOfJPY[buyer] = _buyer_jpy;      if (balanceOfJPY[buyer] < premium + btc_amount * btc_price) throw;      balanceOfJPY[buyer] -= premium;      balanceOfJPY[seller] += premium;    }    function Expire (uint _current_btc_price, uint _current_time){      if (_current_time < exercise_date) throw;      if (_current_btc_price < btc_price) throw;      balanceOfJPY[buyer] -= btc_price * btc_amount;      balanceOfJPY[seller] += btc_price * btc_amount;      balanceOfBTC[buyer] += btc_amount;      balanceOfBTC[seller] -= btc_amount;    }    function () {      throw;    }}"
> var compiledSource = eth.compile.solidity(source)

続いて、コントラクトをEthereumのネットワークに送信します。

> var abiDefinition = compiledSource.CallOption.info.abiDefinition
> var compiledContract = eth.contract(abiDefinition)
> var seller = "0xfffe72483eb0bc804295af2416d2aeb4fa15a8bc"
> var buyer = "0x0e7b3774402f2f19a05e7a279238a4a1fe5e2bc0"
> var contract = compiledContract.new(seller, 100000, 1,  50000, 1, 1463127335, {from: seller, data: compiledSource.CallOption.code, gas:1000000})

以下のようにコントラクトが送信されました。
しかしまだマイニングされていないので、アドレスは割り当てられていません。

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

マイニングが完了すると以下のようになります。アドレスが付与されるているのがわかります。

> contract
{
  address: "0x0bc2c62ecc340e0a4606d087f2d9d9afe0ef16d6",
  transactionHash: "0xf194ae6298b85b7fa6b0a9b75d115181ffb44ef546e4da9bcd970b943b01fa02",
  Expire: function(),
  Respond: function(),
  allEvents: function(),
  balanceOfBTC: function(),
  balanceOfJPY: function(),
  btc_amount: function(),
  btc_price: function(),
  buyer: function(),
  exercise_date: function(),
  premium: function(),
  seller: function()
}

Respondメソッド

初期化が完了しました。続いてRespondメソッドを実行しましょう。
以下がコードです。第一引数は買い手のアドレス、第二引数は買い手のJPY残高を表しています。

 function Respond (address _buyer, uint _buyer_jpy) {
      buyer = _buyer;
      balanceOfJPY[buyer] = _buyer_jpy;
      if (balanceOfJPY[buyer] < premium + btc_amount * btc_price) throw;
      balanceOfJPY[buyer] -= premium;
      balanceOfJPY[seller] += premium;
 }

以下の条件文は、もしも買い手のJPY残高が (ビットコインの購入費+プレミアム) より少ない場合は、このメソッドは無効にするものです。

if (balanceOfJPY[buyer] < premium + btc_amount * btc_price) throw;

メソッドを呼び出しましょう。

> contract.Respond.sendTransaction(buyer, 100000, {from: buyer, gas:1000000})

まだマイニングが完了していないので、売りてと買い手のJPY残高は変化していません。

> contract.balanceOfJPY(seller)
100000
> contract.balanceOfJPY(buyer)
0

マイニング完了後は以下のように残高が変化します。プレミアム分だけ売り手の残高が増えているのがわかります。

> contract.balanceOfJPY(seller)
105000
> contract.balanceOfJPY(buyer)
95000

Expireメソッド呼び出し

最後にExpireメソッドを実行しましょう。これは期日を過ぎたら、契約内容に沿って取引を実効するメソッドです。

  function Expire (uint _current_btc_price, uint _current_time){
      if (_current_time < exercise_date) throw; 
      if (_current_btc_price < btc_price) throw;
      balanceOfJPY[buyer] -= btc_price * btc_amount;
      balanceOfJPY[seller] += btc_price * btc_amount;
      balanceOfBTC[buyer] += btc_amount;
      balanceOfBTC[seller] -= btc_amount;
    }

期日に達してない場合は無効とする条件文です。

if (_current_time < exercise_date) throw;

現在のBTC価格が、権利行使価格より安い場合は無効とする条件文です。

if (_current_btc_price < btc_price) throw;

メソッドを呼び出します。

contract.Expire.sendTransaction(55000, 1463127340, {from:seller, gas:1000000}

BTC価格は¥55000(>¥50000)、現在時刻は1463127340(>1463127335)であるため、契約は実行されるはずです。

マイニング前

> contract.balanceOfBTC(seller)
1
> contract.balanceOfBTC(buyer)
0
> contract.balanceOfJPY(seller)
105000
> contract.balanceOfJPY(buyer)
95000

マイニング後

> contract.balanceOfBTC(seller)
0
> contract.balanceOfBTC(buyer)
1
> contract.balanceOfJPY(seller)
155000
> contract.balanceOfJPY(buyer)
45000

契約条件に沿って、売り手と買い手のJPY残高とBTC残高が変化しているのが確認出来ました。

まとめ

今回はSolidityを用いたオプション取引の実装方法をご説明しました。次回はスワップ取引の実装方法をご紹介致します。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5