누구나 만들 수 있는 이더리움 ERC20 코인/토큰 실전 개발 (2편)
kr-dev·@nida-io·
0.000 HBD누구나 만들 수 있는 이더리움 ERC20 코인/토큰 실전 개발 (2편)
# "누구나 만들 수 있는 이더리움 ERC20 코인/토큰 실전 개발" (2편) <p></p> steemit 이 정말 좋은데... 개발 소스를 설명하기엔 화면 좌우 폭이 너무 짧은 것 같습니다. 아무리 노력해도 가독성이 그닥 좋지 못한 문서가 나온 것 같습니다. 😭😭😭 약간이라도 가독성을 높여 보기 위해 원래는 하나의 글로 올렸던 기나긴 글을 두개로 쪼개봤습니다. 그런 이유로 이 글은 1편에서 바로 이어집니다. - ["누구나 만들 수 있는 이더리움 ERC20 코인/토큰 실전 개발" (1편) 보러가기](https://steemit.com/kr-dev/@nida-io/2oduk2-erc20-1) --- <p></p> ## BasicToken 소스 설명 (1) <p></p> ``` pragma solidity ^0.4.18; import "./ERC20Basic.sol"; import "../../math/SafeMath.sol"; ``` <p></p> - 컴파일러 버전은 0.4.18 버전을 사용하겠다. - `ERC20Basic` 과 `SafeMath` 파일을 불러서 참조하여라. ## BasicToken 소스 설명 (2) <p></p> ``` /** * @title Basic token * @dev Basic version of StandardToken, with no allowances. */ ``` <p></p> - BasicToken 콘트랙트에 대해 설명한 주석 부분 - 이더리움은 표준 주석 포맷에 대해 정의를 해두었습니다. 표준을 따라 주석을 작성하려면 [이 링크](https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format) 를 참고하세요. ## BasicToken 소스 설명 (3) <p></p> ``` using SafeMath for uint256; mapping(address => uint256) balances; uint256 totalSupply_; ``` <p></p> - `uint256` 타입에 `SafeMath` 라이브러리 함수를 적용하겠다. - `balances` 변수는 누가 얼마를 가지고 있는지 저장하는 변수입니다. - `totalSupply_` 변수는 발행된 토큰의 전체 개수를 저장하는 변수입니다. 참고로 `uint256` 타입이 가질 수 있는 가장 큰 값은 `1.1579209e+77` 정도 되기 때문에 어마어마하게 큰 수입니다. ## BasicToken 소스 설명 (4) <p></p> ``` /** * @dev total number of tokens in existence */ function totalSupply() public view returns (uint256) { return totalSupply_; } ``` <p></p> - 함수의 경우 다음과 같이 구성됩니다. - `function [함수명] ([파라메터]) [수식어] returns ([파라메터])` - `첫번째 파라메터` 는 함수에 입력하는 값입니다. 콤마로 구분하여 여러개를 입력 받을 수 있습니다. - `수식어`(*function modifier*) 는 `public` 이나 `view` 등처럼 함수를 꾸미는 키워드입니다. 사용자가 직접 정의한 수식어를 사용할 수도 있는데, 차후 설명드리겠습니다. 혹시 궁금하신 분은 [이 링크](http://solidity.readthedocs.io/en/latest/contracts.html#modifiers) 를 참고하시기 바랍니다. - `두번째 파라메터` 는 함수의 출력 결과(return) 값입니다. 콤마로 구분하여 여러개를 입력 받을 수 있습니다. <p></p> - `totalSupply` : 발행된 전체 토큰의 개수를 알려주는(`return totalSupply_;`) 함수. `view` 함수라서 가스가 소모되지 않음. ## BasicToken 소스 설명 (5) <p></p> ``` /** * @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; } ``` <p></p> - `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` 에 걸리지 않는 이상 무조건 참이 리턴됨) <p></p> - `msg.sender` 에 대한 개념은 굉장히 중요한데, 기본적으로는 *'가스 비용을 내고 이 콘트랙트 함수를 호출한 유저 계정(EOA)'* 이라고 생각하시면 됩니다. 즉, 토큰을 보낼 사람이 가스 비용을 내고 `transfer` 함수를 호출해야 합니다. 그런데 `msg.sender` 가 EOA 가 아니라 콘트랙트 계정(Contract Account) 이 될 수도 있습니다. 이 개념은 조금 복잡하니 차후 ICO 과정을 설명할 때 말씀드리도록 하겠습니다. ## BasicToken 소스 설명 (6) <p></p> ``` /** * @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]; } } ``` <p></p> - `balanceOf` : `_owner` 가 보유한 토큰이 몇개인지 알려주는(`return balances[_owner];`) 함수. `view` 함수라서 가스가 소모되지 않음. # 첫 토큰 만들러 가즈아~! - "MyBasicToken.sol" <p></p> ``` 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); } } ``` <p></p> 이 파일은 zeppelin 의 SimpleToken 예제에서 몇 줄을 삭제하고 만든 소스입니다. - 10000 * (10의 18승) 의 값을 가진 `INITIAL_SUPPLY` 상수를 선언합니다. 보통 18승으로 하는 이유는, 이더리움에서 `1 ether = 10**18 wei` 이기 때문입니다. 이더리움 돈의 단위가 궁금하신 분은 [여기](http://www.ethdocs.org/en/latest/ether.html#what-is-ether) 를 보세요. - `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편이 업뎃되어 링크를 남깁니다. - ["누구나 만들 수 있는 이더리움 ERC20 코인/토큰 실전 개발" (3편) 보러가기](https://steemit.com/kr-dev/@nida-io/erc20-3) ---------------- TaeKim(@nida-io) 의 프로젝트를 구경하세요. - [니다닷컴](http://니다.com) : 쉽게 읽히는 "한글 멘트 그대로의 링크" 를 만들어드립니다. 마케팅 콘텐츠, 홈페이지, 쇼핑몰, 블로그, 청첩장, 포트폴리오 등의 링크에 사용하여 가독성과 클릭율을 높여보세요. - [케이스타코인](http://kstarcoin.com) : 830만 팔로어 전세계 1위 한류 미디어 KStarLive 와 함께 만든 한류 플랫폼에 사용되는 코인입니다. 스팀잇처럼 커뮤니티 활동을 하면서 코인을 얻을 수 있으며, 한류 콘텐츠 구매, 공연 예매, 한국 관광 관련, 기부 및 팬클럽 활동 등에 사용될 계획입니다.