Upgrade to Pro — share decks privately, control downloads, hide ads and more …

スマートコントラクトを理解する 〜解説と実演〜 / Understanding Smart Contracts

スマートコントラクトを理解する 〜解説と実演〜 / Understanding Smart Contracts

2017年6月7日(水)、Interop Tokyo 2017 の同名のセッションにて私用したスライドです。

Kenji Saito

June 07, 2017
Tweet

More Decks by Kenji Saito

Other Decks in Technology

Transcript

  1. ( ) SFC ( ) CSO (Chief Science Officer) 1993

    M.Eng ( ) 2006 ( ) SFC 16 P2P 2011 → ( ) — — 2017-06-07 – p.2/70
  2. Vitalik Buterin, “Ethereum White Paper: A NEXT GENERATION SMART CONTRACT

    & DECENTRALIZED APPLICATION PLATFORM” 15 — — 2017-06-07 – p.5/70
  3. Solidity contract metaCoin { mapping (address => uint) balances; function

    metaCoin() { balances[msg.sender] = 10000; } function sendCoin(address receiver, uint amount) returns(bool sufficient) { if (balances[msg.sender] < amount) return false; balances[msg.sender] -= amount; balances[receiver] += amount; return true; } } by hshimo — — 2017-06-07 – p.13/70
  4. The DAO ( ) The DAO Split ( ) 360

    ETH (50∼60 ) (2016/6/17) ( ) ( ; ) (2016/7/20 ) — — 2017-06-07 – p.19/70
  5. JVM ( ) (Uniqueness Services) UTXO X.509 PKI ( )

    Corda — — 2017-06-07 – p.26/70
  6. 4. Mac OS X (Yosemite 10.10.5) + Homebrew Linux (Ubuntu

    16.04) Windows 10 + Bash on Ubuntu on Windows geth, solidity populus — — 2017-06-07 – p.27/70
  7. Solidity JavaScript ( , ) (constructor) ( ) ( )

    Ether — — 2017-06-07 – p.37/70
  8. pragma solidity ˆ0.4.8; contract MyToken { ( ) : (EVM

    ) : function MyToken(...) { /* */ : } : } function C (/* */ // ) — — 2017-06-07 – p.38/70
  9. MyToken string public name; string public symbol; uint8 public decimals;

    mapping (address => uint256) public balanceOf; name, symbol decimals : 2 100 1.00 mapping balanceOf — — 2017-06-07 – p.39/70
  10. MyToken event Transfer(address indexed from, address indexed to, uint256 value);

    indexed (3 ) MyToken function Transfer() Ethereum-Wallet — — 2017-06-07 – p.40/70
  11. MyToken function MyToken(uint256 _supply, string _name, string _symbol, uint8 _decimals)

    { if (_supply == 0) { _supply = 1000000; /* _supply 1,000,000 */ } balanceOf[msg.sender] = _supply; name = _name; symbol = _symbol; decimals = _decimals; } msg.sender _supply C++ _ — — 2017-06-07 – p.41/70
  12. MyToken transfer() function transfer(address _to, uint256 _value) { if (balanceOf[msg.sender]

    < _value) { /* */ throw; } if (balanceOf[_to] + _value < balanceOf[_to]) { /* */ throw; } balanceOf[msg.sender] -= _value; balanceOf[_to] += _value; Transfer(msg.sender, _to, _value); } throw (function ) catch — — 2017-06-07 – p.43/70
  13. (1) import pytest @pytest.fixture() def token_contract(chain): TokenFactory = chain.get_contract_factory(’MyToken’) deploy_txid

    = TokenFactory.deploy(args=[ 0, "BcH Coin", "BcH", 0, ]) contract_address = chain.wait.for_contract_address(deploy_txid) return TokenFactory(address=contract_address) populus — — 2017-06-07 – p.44/70
  14. (2) def test_my_token(token_contract, chain): account0 = chain.web3.eth.accounts[0] account1 = chain.web3.eth.accounts[1]

    assert token_contract.call().getBalanceOf(account0) == 1000000 assert token_contract.call().getBalanceOf(account1) == 0 txid = token_contract.transact().transfer(account1, 10) chain.wait.for_receipt(txid) assert token_contract.call().getBalanceOf(account0) == 999990 assert token_contract.call().getBalanceOf(account1) == 10 account0 coinbase account1 account0 account1 10BcH — — 2017-06-07 – p.45/70
  15. IndivisibleAsset string public _name; string public _symbol; uint256 public _quantity;

    address public _owner; _name ( ) _symbol _quantity (m2 ) _owner _ Solidity . . . — — 2017-06-07 – p.49/70
  16. IndivisibleAsset function IndivisibleAsset(string name, string symbol, uint256 quantity) { _name

    = name; _symbol = symbol; _quantity = quantity; _owner = msg.sender; } — — 2017-06-07 – p.51/70
  17. IndivisibleAsset transfer() function transfer(address to) { if (_owner != msg.sender)

    { throw; } _owner = to; Transfer(msg.sender, to); } — — 2017-06-07 – p.53/70
  18. (1) import pytest @pytest.fixture() def asset_contract(chain): AssetFactory = chain.get_contract_factory(’IndivisibleAsset’) deploy_txid

    = AssetFactory.deploy(args=[ "5322 Endo, Fujisawa", "mˆ2", 300, ]) contract_address = chain.wait.for_contract_address(deploy_txid) return AssetFactory(address=contract_address) SFC (300m2 ) — — 2017-06-07 – p.54/70
  19. (2) def test_indivisible_assset(asset_contract, chain): account0 = chain.web3.eth.accounts[0] account1 = chain.web3.eth.accounts[1]

    assert asset_contract.call().getOwner() == account0 txid = asset_contract.transact().transfer(account1) chain.wait.for_receipt(txid) assert asset_contract.call().getOwner() == account1 account0 account1 — — 2017-06-07 – p.55/70
  20. 1. ( ) 2. ( ) 3. ( ) —

    — 2017-06-07 – p.59/70
  21. OneTimeEscrow settle() function settle() { address addr = this; /*

    this */ if (_token.getBalanceOf(this) < _price || _asset.getOwner() != addr) { throw; } _token.transfer(_seller , _price); _asset.transfer(_buyer); Settled(); /* */ } settle() transfer — — 2017-06-07 – p.60/70
  22. (1) import pytest @pytest.fixture() def token_contract(chain): . . . @pytest.fixture()

    def asset_contract(chain): . . . — — 2017-06-07 – p.61/70
  23. (2) def test_one_time_escrow(token_contract, asset_contract, chain): account0 = chain.web3.eth.accounts[0] account1 =

    chain.web3.eth.accounts[1] txid = chain.web3.eth.sendTransaction({ ’from’: account0, ’to’: account1, ’value’: chain.web3.toWei(1, "ether") }) chain.wait.for_receipt(txid) txid = token_contract.transact().transfer(account1, 300) chain.wait.for_receipt(txid) account0 account1 1Ether 300BcH 300BcH TX — — 2017-06-07 – p.62/70
  24. (3) EscrowFactory = chain.get_contract_factory(’OneTimeEscrow’) txid = EscrowFactory.deploy(args=[ token_contract.address, account1, asset_contract.address,

    account0, 300, ]) contract_address = chain.wait.for_contract_address(txid) EscrowFactory.address = contract_address; account1 account0 300BcH — — 2017-06-07 – p.63/70
  25. (4) txid = token_contract.transact({ ’from’: account1 }).transfer(contract_address, 300) chain.wait.for_receipt(txid) txid

    = asset_contract.transact().transfer(contract_address) chain.wait.for_receipt(txid) assert token_contract.call().getBalanceOf(account0) == 999700 assert token_contract.call().getBalanceOf(account1) == 0 assert token_contract.call().getBalanceOf(contract_address) == 300 assert asset_contract.call().getOwner() == contract_address account1 300BcH account0 — — 2017-06-07 – p.64/70
  26. (5) txid = EscrowFactory.transact().settle(); chain.wait.for_receipt(txid) assert token_contract.call().getBalanceOf(account0) == 1000000 assert

    token_contract.call().getBalanceOf(account1) == 0 assert token_contract.call().getBalanceOf(contract_address) == 0 assert asset_contract.call().getOwner() == account1 settle() — — 2017-06-07 – p.65/70
  27. ( ) (by ) (since 1984) ( ) ( )

    . . . ( ) — — 2017-06-07 – p.68/70
  28. ( ) ( ) ( ) ( ) (by )

    — — 2017-06-07 – p.69/70