커버 이미지의 출처는 다음과 같습니다 : https://cryptozombies.io/ko/

크립토좀비 사이트 내용을 정리하였으며, 컨텐츠 관련 모든 권리는 Loom Network에 있습니다.

5) 토큰, ERC721 표준, 그리고 크립토 수집품 자산(Crypto-collectible assets)

1. 이더리움 상의 토큰

토큰 표준의 필요성

예시 : 거래소에서 새로운 ERC20 토큰 상장

다른 토큰 표준

ERC721 토큰의 속성

2. ERC721 표준, 다중 상속

ERC721 표준

contract ERC721 {
  event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
  event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);

  function balanceOf(address _owner) public view returns (uint256 _balance);
  function ownerOf(uint256 _tokenId) public view returns (address _owner);
  function transfer(address _to, uint256 _tokenId) public;
  function approve(address _to, uint256 _tokenId) public;
  function takeOwnership(uint256 _tokenId) public;
}

토큰 컨트랙트 구현하기

contract SatoshiNakamoto is NickSzabo, HalFinney {
  // 오 이런, 이 세계의 비밀이 밝혀졌군!
}

3. balanceOf 와 ownerOf

balanceOf

  function balanceOf(address _owner) public view returns (uint256 _balance);

ownerOf

  function ownerOf(uint256 _tokenId) public view returns (address _owner);

4. ERC721: 전송 로직

  1. 토큰의 소유자가 전송 상대의 address, 전송하고자 하는 _tokenId와 함께 transfer 함수를 호출
  2. 토큰의 소유자가 위의 정보를 가지고 approve를 호출
    • 이후 컨트랙트에 누가 해당 토큰을 가질 수 있도록 허가받았는지 저장
    • 일반적으로는 mapping(uint256 => address)으로 구현
    • 이후, 누군가 takeOwnership을 호출하면
    • 해당 컨트랙트는 이 msg.owner가 허가를 받았는지 확인
    • 허가받았다면 해당 토큰을 전송함
function transfer(address _to, uint256 _tokenId) public;
function approve(address _to, uint256 _tokenId) public;
function takeOwnership(uint256 _tokenId) public;

5. ERC721: Approve

  1. 소유자가 새로운 소유자의 address와 보내고 싶은 _tokenId를 사용해 approve를 호출
  2. 새 소유자가 _tokenId를 사용해 takeOwnership 함수를 호출하면, 컨트랙트는 승인된 자인지 확인하고 토큰 전송

6. ERC721: takeOwnership

7. 오버플로우 막기

컨트랙트 보안 강화: 오버플로우와 언더플로우

SafeMath 사용하기

using SafeMath for uint256;

uint256 a = 5;
uint256 b = a.add(3); // 5 + 3 = 8
uint256 c = a.mul(2); // 5 * 2 = 10

SafeMath 내부 구현 코드

library SafeMath {

  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    if (a == 0) {
      return 0;
    }
    uint256 c = a * b;
    assert(c / a == b);
    return c;
  }

  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    // assert(b > 0); // Solidity automatically throws when dividing by 0
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    return c;
  }

  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    assert(b <= a);
    return a - b;
  }

  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    assert(c >= a);
    return c;
  }
}

SafeMath 내부 구현 코드 설명

using SafeMath for uint;
// 우리는 이제 이 메소드들을 아무 uint에서나 쓸 수 있네.
uint test = 2;
test = test.mul(3); // test는 이제 6이 되네
test = test.add(5); // test는 이제 11이 되네

SafeMath 내부 구현 코드 설명 2

function add(uint256 a, uint256 b) internal pure returns (uint256) {
  uint256 c = a + b;
  assert(c >= a);
  return c;
}

우리의 코드에 SafeMath 사용하기

// 다음 코드를
myUint++;

// 다음으로 변경
myUint = myUint.add(1);

8. 주석(Comment)

한 줄 주석

// 이게 한 줄 주석이네. 자신 또는 다른 사람에 대한 메모와도 같은 것이지.

여러 줄 주석

contract CryptoZombies {
  /* This is a multi-lined comment. I'd like to thank all of you
    who have taken your time to try this programming course.
    I know it's free to all of you, and it will stay free
    forever, but we still put our heart and soul into making
    this as good as it can be.

    Know that this is still the beginning of Blockchain development.
    We've come very far but there are so many ways to make this
    community better. If we made a mistake somewhere, you can
    help us out and open a pull request here:
    https://github.com/loomnetwork/cryptozombie-lessons

    Or if you have some ideas, comments, or just want to say
    hi - drop by our Telegram community at https://t.me/loomnetworkkr
  */
}

Solidity 표준 주석

/// @title 기본적인 산수를 위한 컨트랙트
/// @author H4XF13LD MORRIS 💯💯😎💯💯
/// @notice 지금은 곱하기 함수만 추가한다.
contract Math {
  /// @notice 2개의 숫자를 곱한다.
  /// @param x 첫 번쨰 uint.
  /// @param y 두 번째 uint.
  /// @return z (x * y) 곱의 값
  /// @dev 이 함수는 현재 오버플로우를 확인하지 않는다.
  function multiply(uint x, uint y) returns (uint z) {
    // 이것은 일반적인 주석으로, natspec에 포함되지 않는다.
    z = x * y;
  }
}
at4am의 프로필 이미지

at4am

2019년 06월 13일

글쓴이의 더 많은 글 읽어보기