$30 off During Our Annual Pro Sale. View Details »

Ethereum Exercise I

Ethereum Exercise I

2023年8月30日(水)、ブロックチェーンハブ主催のブロックチェーンアカデミーにて使用したスライドです。

Kenji Saito
PRO

August 30, 2023
Tweet

More Decks by Kenji Saito

Other Decks in Technology

Transcript

  1. 2 Ethereum I
    CSO /
    [email protected]
    — 2 Ethereum I — 2023-08-30 – p.1/37

    View Slide

  2. https://speakerdeck.com/ks91
    — 2 Ethereum I — 2023-08-30 – p.2/37

    View Slide

  3. ( )
    SFC ( )
    CSO (Chief Science Officer)
    1993 ( )
    2006 ( )
    SFC
    22 P2P (Peer-to-Peer)
    2011 ( )
    2018 2019
    VR 2021.9 & VR 2022.3
    2023 AI VR&RPG 2023.5 “Don’t Be So Serious”
    VOXEL 2023.7 DAZE 2023
    → ( )
    — 2 Ethereum I — 2023-08-30 – p.3/37

    View Slide

  4. ERC-20
    2
    ERC-20
    — 2 Ethereum I — 2023-08-30 – p.4/37

    View Slide

  5. 1. : ERC-20
    2. :
    3. :
    — 2 Ethereum I — 2023-08-30 – p.5/37

    View Slide

  6. 1. : ERC-20
    $ brownie bake token
    — 2 Ethereum I — 2023-08-30 – p.6/37

    View Slide

  7. Solidity
    JavaScript
    ( , )
    (constructor)
    ( )
    ( )
    Ether
    Ethereum
    — 2 Ethereum I — 2023-08-30 – p.7/37

    View Slide

  8. pragma solidity ˆ0.6.0; /* 0.8.x */
    contract Token {
    ( )
    :
    (EVM )
    :
    constructor (...) public { /* */
    :
    }
    function balanceOf(...) { /* ( ) */
    :
    }
    :
    }
    constructor
    C (/* */ // )
    — 2 Ethereum I — 2023-08-30 – p.8/37

    View Slide

  9. ERC-20
    ERC (Ethereum Request for Comments) EIP (Ethereum Improvement Proposals) 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
    ERC-777
    — 2 Ethereum I — 2023-08-30 – p.9/37

    View Slide

  10. ERC-20
    ERC-20
    ( )
    ⇒ ERC-20
    ( ERC-20 )
    ERC-20

    — 2 Ethereum I — 2023-08-30 – p.10/37

    View Slide

  11. (fungible)
    ERC-20 → ERC-223 (draft) or ERC-777 ( )( )
    (non-fungible)
    ERC-721
    ( )
    ERC-1155 ( )
    ERC-3525 (SLOT )
    — 2 Ethereum I — 2023-08-30 – p.11/37

    View Slide

  12. Token ( )
    string public symbol;
    string public name;
    uint256 public decimals;
    uint256 public totalSupply;
    mapping(address => uint256) balances;
    .
    .
    .
    name, symbol
    decimals
    : 2 100 1.00
    mapping balances
    — 2 Ethereum I — 2023-08-30 – p.12/37

    View Slide

  13. Token ( )
    event Transfer(address from, address to, uint256 value);
    Token function emit Transfer() ( )
    — 2 Ethereum I — 2023-08-30 – p.13/37

    View Slide

  14. Token ( )
    constructor(
    string memory _symbol,
    string memory _name,
    uint256 _decimals,
    uint256 _totalSupply
    )
    public
    {
    symbol = _symbol;
    name = _name;
    decimals = _decimals;
    totalSupply = _totalSupply;
    balances[msg.sender] = _totalSupply;
    }
    msg.sender
    _totalSupply
    — 2 Ethereum I — 2023-08-30 – p.14/37

    View Slide

  15. Token balanceOf()
    function balanceOf(address _owner) public view returns (uint256) {
    return balances[_owner];
    }
    — 2 Ethereum I — 2023-08-30 – p.15/37

    View Slide

  16. Token transfer()
    function transfer(address _to, uint256 _value) public returns (bool) {
    require(balances[msg.sender] >= _value, "Insufficient balance");
    balances[msg.sender] = balances[msg.sender].sub(_value);
    balances[_to] = balances[_to].add(_value);
    emit Transfer(msg.sender, _to, _value);
    return true;
    }
    require (function )
    ( ↑ )
    OpenZeppelin
    https://openzeppelin.org
    — 2 Ethereum I — 2023-08-30 – p.16/37

    View Slide

  17. 2.
    — 2 Ethereum I — 2023-08-30 – p.17/37

    View Slide

  18. GitHub git clone
    $ git clone https://github.com/ks91/sample-smart-contracts.git
    sample-smart-contracts contracts, scripts
    tests token
    Token
    Solidity 0.5 0.6/0.7
    (Token )
    Token Solidity 0.5 0.6
    Solidity
    — 2 Ethereum I — 2023-08-30 – p.18/37

    View Slide

  19. (m2 )
    1 1
    — 2 Ethereum I — 2023-08-30 – p.19/37

    View Slide

  20. IndivisibleAsset
    string public _name_;
    string public _symbol_;
    uint256 public _quantity_;
    address public _owner_;
    _name_ ( )
    _symbol_ _quantity_ (m2 )
    _owner_
    ‘_’ Solidity . . .
    — 2 Ethereum I — 2023-08-30 – p.20/37

    View Slide

  21. IndivisibleAsset
    event Transfer(address indexed from, address indexed to);
    from to
    indexed
    — 2 Ethereum I — 2023-08-30 – p.21/37

    View Slide

  22. IndivisibleAsset
    constructor (string name, string symbol, uint256 quantity) public {
    _name_ = name;
    _symbol_ = symbol;
    _quantity_ = quantity;
    _owner_ = msg.sender;
    }
    — 2 Ethereum I — 2023-08-30 – p.22/37

    View Slide

  23. IndivisibleAsset getOwner()
    function getOwner() public view returns (address) {
    return (_owner_);
    }
    — 2 Ethereum I — 2023-08-30 – p.23/37

    View Slide

  24. IndivisibleAsset transfer()
    function transfer(address to) public returns (bool) {
    require(_owner_ == msg.sender);
    _owner_ = to;
    emit Transfer(msg.sender, to);
    return true;
    }
    require (function )
    ( )
    $ brownie compile
    — 2 Ethereum I — 2023-08-30 – p.24/37

    View Slide

  25. scripts/indivisible asset.py
    from brownie import *
    def main():
    accounts[0].deploy(IndivisibleAsset, "5322 Endo, Fujisawa", "mˆ2", 300)
    SFC (300m2 )
    ( )
    — 2 Ethereum I — 2023-08-30 – p.25/37

    View Slide

  26. from brownie import *
    import pytest
    def test_owner_and_transfer(IndivisibleAsset):
    asset = accounts[0].deploy(IndivisibleAsset, "5322 Endo", "mˆ2", 300)
    assert asset.getOwner() == accounts[0]
    asset.transfer(accounts[1], {’from’: accounts[0]})
    assert asset.getOwner() == accounts[1]
    try:
    asset.transfer(accounts[0], {’from’: accounts[0]})
    done = 1
    except:
    done = 0
    assert done == 0
    accounts[0] accounts[1]
    — 2 Ethereum I — 2023-08-30 – p.26/37

    View Slide

  27. $ pytest tests/test_indivisible_asset.py
    — 2 Ethereum I — 2023-08-30 – p.27/37

    View Slide

  28. 3.
    — 2 Ethereum I — 2023-08-30 – p.28/37

    View Slide

  29. transfer
    settle, retrieve asset, retrieve token 3
    — 2 Ethereum I — 2023-08-30 – p.29/37

    View Slide

  30. 1. ( )
    2. ( )
    3. ( )
    — 2 Ethereum I — 2023-08-30 – p.30/37

    View Slide

  31. OneTimeEscrow settle()
    function settle() public returns (bool) {
    require(_token_.balanceOf(address(this)) >= _price_); /* this */
    require(_asset_.getOwner() == address(this));
    _token_.transfer(_seller_ , _price_);
    _asset_.transfer(_buyer_);
    emit Settled(); /* */
    return true;
    }
    settle()
    transfer
    ( / )
    $ brownie compile
    — 2 Ethereum I — 2023-08-30 – p.31/37

    View Slide

  32. (1)
    from brownie import *
    import pytest
    def test_deploy_and_settle(Token, IndivisibleAsset, OneTimeEscrow):
    asset = accounts[0].deploy(IndivisibleAsset, "5322 Endo", "mˆ2", 300)
    token = accounts[0].deploy(Token, "Test Token", "TEST", 18, "1000 ether")
    — 2 Ethereum I — 2023-08-30 – p.32/37

    View Slide

  33. (2)
    token.transfer(accounts[1], 300, {’from’: accounts[0]})
    escrow = accounts[0].deploy(OneTimeEscrow, token, accounts[1], asset, accounts[0], 300)
    accounts[0] accounts[1] 300
    300 TX
    accounts[1] accounts[0] 300
    bake Token
    300 ETH wei
    — 2 Ethereum I — 2023-08-30 – p.33/37

    View Slide

  34. (3)
    token.transfer(escrow, 300, {’from’: accounts[1]})
    asset.transfer(escrow, {’from’: accounts[0]})
    assert token.balanceOf(accounts[0]) == 999999999999999999700
    assert token.balanceOf(accounts[1]) == 0
    assert token.balanceOf(escrow) == 300
    assert asset.getOwner() == escrow
    accounts[1] ( ) 300
    accounts[0] ( )
    — 2 Ethereum I — 2023-08-30 – p.34/37

    View Slide

  35. (4)
    escrow.settle({’from’: accounts[0]})
    assert token.balanceOf(accounts[0]) == 1000000000000000000000
    assert token.balanceOf(accounts[1]) == 0
    assert token.balanceOf(escrow) == 0
    assert asset.getOwner() == accounts[1]
    settle()
    accounts[0] OK
    — 2 Ethereum I — 2023-08-30 – p.35/37

    View Slide

  36. $ pytest tests/test_one_time_escrow.py
    :
    settle()
    — 2 Ethereum I — 2023-08-30 – p.36/37

    View Slide

  37. 3 Ethereum II
    :
    — 2 Ethereum I — 2023-08-30 – p.37/37

    View Slide