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

Ethereum 実習 / Practicing Ethereum

Ethereum 実習 / Practicing Ethereum

2018年10月31日(水)、ブロックチェーンハブ主催で開催されたブロックチェーンアカデミー「【ハンズオン】スマートコントラクトプログラミング(2) イーサリアム実習」にて使用したスライドです。

Kenji Saito

October 31, 2018
Tweet

More Decks by Kenji Saito

Other Decks in Technology

Transcript

  1. 1. : ERC20 2. : 3. : — (2) —

    2018-10-31 – p.3/37
  2. Solidity JavaScript ( , ) (constructor) ( ) ( )

    Ether — (2) — 2018-10-31 – p.6/37
  3. pragma solidity ˆ0.4.24; contract MyToken { ( ) : (EVM

    ) : constructor (...) public { /* */ : } function MyToken(...) { /* ( ) */ : } : } constructor C (/* */ // ) — (2) — 2018-10-31 – p.7/37
  4. ERC20 ERC (Ethereum Request for Comment) 20 https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md contract ERC20

    { function totalSupply() constant returns (uint totalSupply); function balanceOf(address _owner) constant returns (uint balance); function transfer(address _to, uint _value) returns (bool success); function transferFrom(address _from, address _to, uint _value) returns (bool success); function approve(address _spender, uint _value) returns (bool success); function allowance(address _owner, address _spender) constant returns (uint remaining); event Transfer(address indexed _from, address indexed _to, uint _value); event Approval(address indexed _owner, address indexed _spender, uint _value); } name/ , symbol/ , decimals/ approve allowance ERC223 ( ), ERC721 (Non-Fungible) — (2) — 2018-10-31 – p.8/37
  5. MyToken string public _name; string public _symbol; uint8 public _decimals;

    mapping (address => uint256) public _balanceOf; uint256 _totalSupply; _name, _symbol _decimals : 2 100 1.00 mapping _balanceOf ‘_’ Solidity . . . — (2) — 2018-10-31 – p.9/37
  6. MyToken event Transfer(address indexed from, address indexed to, uint256 value);

    indexed (3 ) MyToken function Transfer() — (2) — 2018-10-31 – p.10/37
  7. MyToken constructor (uint256 supply, string name, string symbol, uint8 decimals)

    public { if (supply == 0) { supply = 1000000; /* supply 1,000,000 */ } _totalSupply = supply; _balanceOf[msg.sender] = supply; _name = name; _symbol = symbol; _decimals = decimals; } msg.sender supply — (2) — 2018-10-31 – p.11/37
  8. MyToken balanceOf() function balanceOf(address tokenOwner) external view returns (uint256) {

    return _balanceOf[tokenOwner]; } — (2) — 2018-10-31 – p.12/37
  9. MyToken transfer() function transfer(address to, uint256 value) external returns (bool)

    { require(value <= _balanceOf[msg.sender]); /* */ require(_balanceOf[to] + value >= _balanceOf[to]); /* */ _balanceOf[msg.sender] -= value; _balanceOf[to] += value; Transfer(msg.sender, to, value); return true; } require (function ) OpenZeppelin https://openzeppelin.org — (2) — 2018-10-31 – p.13/37
  10. (1) import pytest @pytest.fixture() def token_contract(chain): TokenFactory = chain.provider.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 — (2) — 2018-10-31 – p.14/37
  11. (2) def test_my_token(token_contract, chain): account0 = chain.web3.eth.accounts[0] account1 = chain.web3.eth.accounts[1]

    assert token_contract.call().balanceOf(account0) == 1000000 assert token_contract.call().balanceOf(account1) == 0 txid = token_contract.transact().transfer(account1, 10) chain.wait.for_receipt(txid) assert token_contract.call().balanceOf(account0) == 999990 assert token_contract.call().balanceOf(account1) == 10 account0 coinbase account1 account0 account1 10BcH — (2) — 2018-10-31 – p.15/37
  12. IndivisibleAsset string public _name; string public _symbol; uint256 public _quantity;

    address public _owner; _name ( ) _symbol _quantity (m2 ) _owner — (2) — 2018-10-31 – p.19/37
  13. IndivisibleAsset constructor (string name, string symbol, uint256 quantity) public {

    _name = name; _symbol = symbol; _quantity = quantity; _owner = msg.sender; } — (2) — 2018-10-31 – p.21/37
  14. IndivisibleAsset transfer() function transfer(address to) external returns (bool) { require(_owner

    == msg.sender); _owner = to; Transfer(msg.sender, to); return true; } ( / ) $ populus compile — (2) — 2018-10-31 – p.23/37
  15. (1) import pytest @pytest.fixture() def asset_contract(chain): AssetFactory = chain.provider.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 ) — (2) — 2018-10-31 – p.24/37
  16. (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 — (2) — 2018-10-31 – p.25/37
  17. 1. ( ) 2. ( ) 3. ( ) —

    (2) — 2018-10-31 – p.29/37
  18. OneTimeEscrow settle() function settle() public returns (bool) { require(_token.balanceOf(this) >=

    _price); /* this */ require(_asset.getOwner() == address(this)); _token.transfer(_seller , _price); _asset.transfer(_buyer); Settled(); /* */ return true; } settle() transfer ( / ) $ populus compile solidity 0.4.21 — (2) — 2018-10-31 – p.30/37
  19. (1) import pytest @pytest.fixture() def token_contract(chain): . . . @pytest.fixture()

    def asset_contract(chain): . . . — (2) — 2018-10-31 – p.31/37
  20. (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 — (2) — 2018-10-31 – p.32/37
  21. (3) EscrowFactory = chain.provider.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 — (2) — 2018-10-31 – p.33/37
  22. (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().balanceOf(account0) == 999700 assert token_contract.call().balanceOf(account1) == 0 assert token_contract.call().balanceOf(contract_address) == 300 assert asset_contract.call().getOwner() == contract_address account1 300BcH account0 — (2) — 2018-10-31 – p.34/37
  23. (5) txid = EscrowFactory.transact().settle(); chain.wait.for_receipt(txid) assert token_contract.call().balanceOf(account0) == 1000000 assert

    token_contract.call().balanceOf(account1) == 0 assert token_contract.call().balanceOf(contract_address) == 0 assert asset_contract.call().getOwner() == account1 settle() — (2) — 2018-10-31 – p.35/37
  24. BBc-1 1. BBc-1 2. BBc-1 3. 4. Ethereum ( )

    — (2) — 2018-10-31 – p.37/37