누구나 만들 수 있는 이더리움 ERC20 코인/토큰 실전 개발 (2편)

in #kr-dev7 years ago (edited)

"누구나 만들 수 있는 이더리움 ERC20 코인/토큰 실전 개발" (2편)

steemit 이 정말 좋은데... 개발 소스를 설명하기엔 화면 좌우 폭이 너무 짧은 것 같습니다. 아무리 노력해도 가독성이 그닥 좋지 못한 문서가 나온 것 같습니다. 😭😭😭

약간이라도 가독성을 높여 보기 위해 원래는 하나의 글로 올렸던 기나긴 글을 두개로 쪼개봤습니다. 그런 이유로 이 글은 1편에서 바로 이어집니다.


BasicToken 소스 설명 (1)

pragma solidity ^0.4.18;

import "./ERC20Basic.sol";
import "../../math/SafeMath.sol";

  • 컴파일러 버전은 0.4.18 버전을 사용하겠다.
  • ERC20BasicSafeMath 파일을 불러서 참조하여라.

BasicToken 소스 설명 (2)

/**
 * @title Basic token
 * @dev Basic version of StandardToken, with no allowances.
 */

  • BasicToken 콘트랙트에 대해 설명한 주석 부분
  • 이더리움은 표준 주석 포맷에 대해 정의를 해두었습니다. 표준을 따라 주석을 작성하려면 이 링크 를 참고하세요.

BasicToken 소스 설명 (3)

  using SafeMath for uint256;
  mapping(address => uint256) balances;
  uint256 totalSupply_;

  • uint256 타입에 SafeMath 라이브러리 함수를 적용하겠다.
  • balances 변수는 누가 얼마를 가지고 있는지 저장하는 변수입니다.
  • totalSupply_ 변수는 발행된 토큰의 전체 개수를 저장하는 변수입니다. 참고로 uint256 타입이 가질 수 있는 가장 큰 값은 1.1579209e+77 정도 되기 때문에 어마어마하게 큰 수입니다.

BasicToken 소스 설명 (4)

  /**
  * @dev total number of tokens in existence
  */
  function totalSupply() public view returns (uint256) {
    return totalSupply_;
  }

  • 함수의 경우 다음과 같이 구성됩니다.
    • function [함수명] ([파라메터]) [수식어] returns ([파라메터])
    • 첫번째 파라메터 는 함수에 입력하는 값입니다. 콤마로 구분하여 여러개를 입력 받을 수 있습니다.
    • 수식어(function modifier) 는 public 이나 view 등처럼 함수를 꾸미는 키워드입니다. 사용자가 직접 정의한 수식어를 사용할 수도 있는데, 차후 설명드리겠습니다. 혹시 궁금하신 분은 이 링크 를 참고하시기 바랍니다.
    • 두번째 파라메터 는 함수의 출력 결과(return) 값입니다. 콤마로 구분하여 여러개를 입력 받을 수 있습니다.

  • totalSupply : 발행된 전체 토큰의 개수를 알려주는(return totalSupply_;) 함수. view 함수라서 가스가 소모되지 않음.

BasicToken 소스 설명 (5)

  /**
  * @dev transfer token for a specified address
  * @param _to The address to transfer to.
  * @param _value The amount to be transferred.
  */
  function transfer(address _to, uint256 _value) public returns (bool) {
    require(_to != address(0));
    require(_value <= balances[msg.sender]);

    // SafeMath.sub will throw if there is not enough balance.
    balances[msg.sender] = balances[msg.sender].sub(_value);
    balances[_to] = balances[_to].add(_value);
    Transfer(msg.sender, _to, _value);
    return true;
  }

  • transfer : 내 계좌에 있는 토큰을 _to 에게 _value 만큼 보내는 함수. 결과값으로 성공 여부를 return 한다.
    • _to 계정이 유효한 계정인지(0이 아닌지) 체크하고 _value 값이 잔고 이내인지 체크한다.
    • balances[msg.sender] = balances[msg.sender].sub(_value); 내 잔고에서 _value 만큼 뺀다.
    • balances[_to] = balances[_to].add(_value); _to 계정의 잔고에 _value 만큼 더한다.
      • 토큰이 전송되는 건 딱 위 두 줄로 끝납니다. 큰 돈이 오고 갈 수도 있는데, 어떻게 보면 허무하죠...?
    • 토큰이 이동했으므로 ERC20 규약에 따라 Transfer 이벤트를 호출한다.
      • 이렇게 한 줄 호출하는 것만으로 이더리움 블록체인에 검색될 수 있는 기록으로 남습니다.
    • true 값을 리턴한다. (중간에 require 에 걸리지 않는 이상 무조건 참이 리턴됨)

  • msg.sender 에 대한 개념은 굉장히 중요한데, 기본적으로는 '가스 비용을 내고 이 콘트랙트 함수를 호출한 유저 계정(EOA)' 이라고 생각하시면 됩니다. 즉, 토큰을 보낼 사람이 가스 비용을 내고 transfer 함수를 호출해야 합니다. 그런데 msg.sender 가 EOA 가 아니라 콘트랙트 계정(Contract Account) 이 될 수도 있습니다. 이 개념은 조금 복잡하니 차후 ICO 과정을 설명할 때 말씀드리도록 하겠습니다.

BasicToken 소스 설명 (6)

  /**
  * @dev Gets the balance of the specified address.
  * @param _owner The address to query the the balance of.
  * @return An uint256 representing the amount owned by the passed address.
  */
  function balanceOf(address _owner) public view returns (uint256 balance) {
    return balances[_owner];
  }
}

  • balanceOf : _owner 가 보유한 토큰이 몇개인지 알려주는(return balances[_owner];) 함수. view 함수라서 가스가 소모되지 않음.

첫 토큰 만들러 가즈아~! - "MyBasicToken.sol"

pragma solidity ^0.4.18;

import "BasicToken.sol";

contract MyBasicToken is BasicToken {
  uint8 public constant decimals = 18; // solium-disable-line uppercase
  uint256 public constant INITIAL_SUPPLY = 10000 * (10 ** uint256(decimals));

  /**
   * @dev Constructor that gives msg.sender all of existing tokens.
   */
  function MyBasicToken() public {
    totalSupply_ = INITIAL_SUPPLY;
    balances[msg.sender] = INITIAL_SUPPLY;
    Transfer(0x0, msg.sender, INITIAL_SUPPLY);
  }
}

이 파일은 zeppelin 의 SimpleToken 예제에서 몇 줄을 삭제하고 만든 소스입니다.

  • 10000 * (10의 18승) 의 값을 가진 INITIAL_SUPPLY 상수를 선언합니다. 보통 18승으로 하는 이유는, 이더리움에서 1 ether = 10**18 wei 이기 때문입니다. 이더리움 돈의 단위가 궁금하신 분은 여기 를 보세요.
  • MyBasicToken() 함수는 콘트랙트가 만들어질 때 자동으로 실행되는 '생성자' 입니다. 콘트랙트 이름과 같은 이름의 함수가 생성자가 됩니다.
    • totalSupply_ = INITIAL_SUPPLY; 전체 발행량에 INITIAL_SUPPLY 값을 저장합니다.
    • balances[msg.sender] = INITIAL_SUPPLY; 관리자(msg.sender, 가스를 소모하여 이 콘트랙트를 만든 사람)의 계좌에 INITIAL_SUPPLY 값을 저장합니다.
    • Transfer(0x0, msg.sender, INITIAL_SUPPLY); 토큰이 생성되었으므로 ERC20 규약에 따라 Transfer 이벤트를 호출합니다.

짠~! 드디어 우리의 첫 토큰을 만들었습니다. 관리자에게 토큰이 10000 * (10의 18승) 만큼 배분되었고, 관리자는 원하는 계좌로 토큰을 전송하고 나눠줄 수 있습니다. 또 받은 사람들은 다시 토큰을 나눠줄 수 있기 때문에 토큰 생태계가 완성된 것입니다.

Solidity 의 기초적인 문법과 개념을 소개하다보니 글이 엄청나게 길어졌는데요, BasicToken.sol 은 zeppelin 이 이미 만들어 준 소스이기 때문에 실제로는 MyBasicToken.sol 부분의 몇 줄만으로도 토큰을 만든 것입니다.

그런데 BasicToken 이 ERC20 의 일부만을 구현한 거라 얘기한 내용 기억하시나요? 다음 연재에는 ERC20 규약을 완성시킨 코인을 만들어 보도록 하겠습니다.

글을 완성시키고 보니 새벽 6시네요. 저의 정성을 갸륵히 여겨 지금 바로 Vote 를... 읍읍....

3편이 업뎃되어 링크를 남깁니다.


TaeKim(@nida-io) 의 프로젝트를 구경하세요.

  • 니다닷컴 : 쉽게 읽히는 "한글 멘트 그대로의 링크" 를 만들어드립니다. 마케팅 콘텐츠, 홈페이지, 쇼핑몰, 블로그, 청첩장, 포트폴리오 등의 링크에 사용하여 가독성과 클릭율을 높여보세요.
  • 케이스타코인 : 830만 팔로어 전세계 1위 한류 미디어 KStarLive 와 함께 만든 한류 플랫폼에 사용되는 코인입니다. 스팀잇처럼 커뮤니티 활동을 하면서 코인을 얻을 수 있으며, 한류 콘텐츠 구매, 공연 예매, 한국 관광 관련, 기부 및 팬클럽 활동 등에 사용될 계획입니다.
Sort:  

잘 읽었습니다.
읽다가 질문이 하나 생겼는데

Transfer(0x0, msg.sender, INITIAL_SUPPLY);

이부분에서 0x0을 0xff나 다른걸로 바꿔도 되나요?

ERC20 규약상 코인이 생성될 때는 0x0 으로 지정해줘야 합니다. 원문은 다음과 같습니다. :-)

A token contract which creates new tokens SHOULD trigger a Transfer event with the _from address set to 0x0 when tokens are created.

가입인사 안 쓰셨네요.
쓰시면 팔로워도 늘고 지식을 좀 얻으실 수 있을거에요
태그는@myfan님의 2.25일 태그 정리 목록여기 참조하시면 좋습니다. 뉴비를 위한 책 :이지 스팀잇이 글이 많이 도움이 될 겁니다.
그리고 마지막으로 코딩을 다룰 줄 아시면 Utopian.io에 대해서 알아보시면 좋을거 같네요.

우와~ 대박! utopian.io 이렇게 좋은 프로젝트가 있었네요. 스팀 계정을 외부로 연동시킬 수 있다는 부분도 정말 재밌습니다. 많이 배웠습니다! 곧 가입인사도 쓰겠습니다. ^.^