Ethereum Token 발행 번역 (CREATE YOUR OWN CRYPTO-CURRENCY WITH ETHEREUM) #1

in #ethereum7 years ago (edited)

이 글은 Ethereum의 token 발행의 번역글입니다. 원만한 내용의 진행을 위해 의역이 들어갔습니다. 번역의 실수로 오역이 있을 수 있습니다. 오역에 관해서는 댓글로 알려주시면 수정 하도록 하겠습니다.
원본 : https://ethereum.org/token

이더리움을 가지고 토큰 발행하기 (CREATE YOUR OWN CRYPTO-CURRENCY WITH ETHEREUM)

The coin

디지털 코인을 만들어 보겠습니다. 이더리움 생태계에서 토큰은 거래가 가능한 어떤것으로도 변할 수 있는 물건 을 의미 합니다. 토큰은 코인, 로얄티 점수, 우수 회원권, IOU그리고 게임 아이템등이 될 수 있습니다. 모든 토큰들은 몇몇 기본 특성들을 기본구현 방향대로 구현함으로서 당신이 만든 토큰은 이더리움 지갑이나 클라이언트, contract와 같은 기준을 통해서 바로 호환 됩니다.

THE CODE
만약 당신이 코드를 그냥 복사해서 붙여넣고 싶으면 다음을 이용 하십시요.

pragma solidity ^0.4.8;
contract tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData); }

contract MyToken {
    /* Public variables of the token */
    string public standard = 'Token 0.1';
    string public name;
    string public symbol;
    uint8 public decimals;
    uint256 public totalSupply;

    /* This creates an array with all balances */
    mapping (address => uint256) public balanceOf;
    mapping (address => mapping (address => uint256)) public allowance;

    /* This generates a public event on the blockchain that will notify clients */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /* This notifies clients about the amount burnt */
    event Burn(address indexed from, uint256 value);

    /* Initializes contract with initial supply tokens to the creator of the contract */
    function MyToken(
        uint256 initialSupply,
        string tokenName,
        uint8 decimalUnits,
        string tokenSymbol
        ) {
        balanceOf[msg.sender] = initialSupply;              // Give the creator all initial tokens
        totalSupply = initialSupply;                        // Update total supply
        name = tokenName;                                   // Set the name for display purposes
        symbol = tokenSymbol;                               // Set the symbol for display purposes
        decimals = decimalUnits;                            // Amount of decimals for display purposes
    }

    /* Send coins */
    function transfer(address _to, uint256 _value) {
        if (_to == 0x0) throw;                               // Prevent transfer to 0x0 address. Use burn() instead
        if (balanceOf[msg.sender] < _value) throw;           // Check if the sender has enough
        if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows
        balanceOf[msg.sender] -= _value;                     // Subtract from the sender
        balanceOf[_to] += _value;                            // Add the same to the recipient
        Transfer(msg.sender, _to, _value);                   // Notify anyone listening that this transfer took place
    }

    /* Allow another contract to spend some tokens in your behalf */
    function approve(address _spender, uint256 _value)
        returns (bool success) {
        allowance[msg.sender][_spender] = _value;
        return true;
    }

    /* Approve and then communicate the approved contract in a single tx */
    function approveAndCall(address _spender, uint256 _value, bytes _extraData)
        returns (bool success) {
        tokenRecipient spender = tokenRecipient(_spender);
        if (approve(_spender, _value)) {
            spender.receiveApproval(msg.sender, _value, this, _extraData);
            return true;
        }
    }        

    /* A contract attempts to get the coins */
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
        if (_to == 0x0) throw;                                // Prevent transfer to 0x0 address. Use burn() instead
        if (balanceOf[_from] < _value) throw;                 // Check if the sender has enough
        if (balanceOf[_to] + _value < balanceOf[_to]) throw;  // Check for overflows
        if (_value > allowance[_from][msg.sender]) throw;     // Check allowance
        balanceOf[_from] -= _value;                           // Subtract from the sender
        balanceOf[_to] += _value;                             // Add the same to the recipient
        allowance[_from][msg.sender] -= _value;
        Transfer(_from, _to, _value);
        return true;
    }

    function burn(uint256 _value) returns (bool success) {
        if (balanceOf[msg.sender] < _value) throw;            // Check if the sender has enough
        balanceOf[msg.sender] -= _value;                      // Subtract from the sender
        totalSupply -= _value;                                // Updates totalSupply
        Burn(msg.sender, _value);
        return true;
    }

    function burnFrom(address _from, uint256 _value) returns (bool success) {
        if (balanceOf[_from] < _value) throw;                // Check if the sender has enough
        if (_value > allowance[_from][msg.sender]) throw;    // Check allowance
        balanceOf[_from] -= _value;                          // Subtract from the sender
        totalSupply -= _value;                               // Updates totalSupply
        Burn(_from, _value);
        return true;
    }
}

최소 기능 토큰(MINIMUM VIABLE TOKEN)

토큰 계약은 꾀나 복잡합니다. 그러나 핵심만 요약하면 아래와 같습니다.

contract MyToken {
    /* This creates an array with all balances */
    mapping (address => uint256) public balanceOf;

    /* Initializes contract with initial supply tokens to the creator of the contract */
    function MyToken(
        uint256 initialSupply
        ) {
        balanceOf[msg.sender] = initialSupply;              // Give the creator all initial tokens
    }

    /* Send coins */
    function transfer(address _to, uint256 _value) {
        if (balanceOf[msg.sender] < _value) throw;           // Check if the sender has enough
        if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows
        balanceOf[msg.sender] -= _value;                     // Subtract from the sender
        balanceOf[_to] += _value;                            // Add the same to the recipient
    }
}

코드 이해하기(Understanding the code)

자 기본 부터 시작해 봅시다. Wallet app을 열고, contract tab으로 가서 Deploy new contract를 하세요. Solidity Contract Source code 텍스트 필드에 가서 아래의 코드를 적으세요.

contract MyToken {
    /* This creates an array with all balances */
    mapping (address => uint256) public balanceOf;
}

매핑은 잔액을 관리할 주소들을 담을 array를 연결하는 것을 의미합니다. 주소들을 기본적은 16진법의 이더리움 포맷이고, 잔액은 0 부터 115 * 10 ^ 75(quattuorvigintillion)의 숫자 입니다.(역자 : 엄청 크네요 @@) quattuorvigintillion에 대해서 잘 모른다면
이건 수 vigintillions_(역자: 10^63)로서 당신이 이용할 토큰의 숫자보다 훨씬 큰 수 입니다. public으로 되어 있는 부분은 블록체인의 어떤 사용자도 접근 할 수 있는 변수를 의미 합니다. 결국 모든 잔고는 외부에서 접근가능 하다는 뜻입니다.(이건 원한다면 하는 겁니다. 클라이언트에서 이래야 보여 줄 수 있죠)

당신의 계약(contract)를 배포 했다면 작동은 하겠지만 유용하지는 않을 겁니다. 당신이 발행한 계약은 모든 지갑의 잔액을 조회 할 수 있습니다. 하지만 코인을 전혀 발행하지 않았기 때문에 모든 지갑의 잔액은 0 이겠죠. 자, 그러니 이제부터 코인을 발행 해보겠습니다. 아래의 코드를 mapping line아래에 넣어 주세요.

function MyToken() {
    balanceOf[msg.sender] = 21000000;
}

주의 할점은 이번에 넣은 코드의 MyToken 함수가 위에서 계약에서 정의한 MyToken 함수와 같다는 점입니다. 이번에 넣은 함수의 이름을 다르게 하고 싶으면, 계약에서 정의한 MyToken 함수와 contract의 이름을 같이 바꿔주세요. 이 함수는 특별한 함수로서 계약이 네트워크에 업로드 될때 딱 한번만 수행되는 함수 입니다. 이번에 정의 한 함수는 msg.sender의 잔고를 21백만으로 하게 됩니다. msg.sender는 계약을 배포한 사람입니다.

21백만으로 정한건 임의로 정한겁니다. 당신이 원하는대로 숫자를 마음대로 바꿔도 됩니다. 하지만 더 좋은 방법이 있죠. 값을 정해 놓기 보단 MyToken의 함수의 인자로 초기 값을 받게 만드는 겁니다.

function MyToken(uint256 initialSupply) {
    balanceOf[msg.sender] = initialSupply;
}

아래의 그림을 참고해서 봐주세요. 오른쪽에 보면 SELECT CONTRACT TO DEPLOY를 보면 Pick a contract 버튼이 있고 누르면 drop down이 나타날겁니다. 여기서 "MyToken" 계약을 고르게 되면, 아래에 CONSTRUCTOR PARAMETERS가 보일 겁니다. 이것은 변할 수 있는 값을 넣는 곳으로, 단지 이값을 바꿈으로서 이코드를 재사용 할 수 있습니다.

이제 토큰 잔고를 만들 수 있는 기능을 수행 할 수 있는 계약을 만들었습니다. 하지만 전송 할 수 있는 코드는 없습니다. 이번엔 전송하는 코드를 구현 해보도록 하죠. 아래의 코드를 맨 마지막 부분에 넣어 주세요.

/* Send coins */
function transfer(address _to, uint256 _value) {
    /* Add and subtract new balances */
    balanceOf[msg.sender] -= _value;
    balanceOf[_to] += _value;
}

이건 매우 직관적인 함수 입니다. 보낼 곳과 보낼 금액을 적으면 됩니다. 이 함수를 부르게 되면 사용한 사람의 잔고에서 보낼만큼의 금액_value을 차감하고 받는 사람_to에게 잔고를 추가 해줍니다. 여기에 문제가 있습니다. 단순히 잔고에서 빼기만 하다보니, 같고 있는거 보다 더 많이 보내면 어쩌죠? 우리가 빚을 구현하진 않을 거니, 보낼려는 금액이 갖고 있는거 보다 많으면 간단히 해당 기능을 정지 시키면 됩니다. 아 물론 받는 사람의 overflow도 체크해야 됩니다. 안그러면 값이 0이 될테니까요.

계약의 실행을 중간에 멈추기 위해서는 return을 하거나 throw를 하면 됩니다. return이 더 적은 gas를 소모 하겠지만 return이전에 실행 된것이 그대로 남아 있기에 골치가 아프게 됩니다. 하지만 throw를 하게 되면 이전의 모든 이력들을 취소 시키게됩니다. 다만 수행을 시키기 위해 사용한 gas 전부를 잃게 됩니다. 지갑은 이러한 throw가 발생되면 알람을 보냄으로서 이더가 더이상 낭비 되지 않게 막아줍니다._(역자 : alert이 나도 계속 수행하면 잃는건 동일할까요?)

function transfer(address _to, uint256 _value) {
    /* Check if sender has balance and for overflows */
    if (balanceOf[msg.sender] < _value || balanceOf[_to] + _value < balanceOf[_to])
        throw;

    /* Add and subtract new balances */
    balanceOf[msg.sender] -= _value;
    balanceOf[_to] += _value;
}

이제 추가적으로 부족한 부분은 계약에 대한 기본적인 정보 입니다. 이러한 정보들은 근래에는 token registry에 의해 관리 되겠지만 일단은 계약에다가 다 등록하도록 합니다.

string public name;
string public symbol;
uint8 public decimals;

자 이제 constructor 함수를 업데이트 해서 모든 변수들이 시작 할 때 값을 같도록 합시다.

/* Initializes contract with initial supply tokens to the creator of the contract */
function MyToken(uint256 initialSupply, string tokenName, uint8 decimalUnits, string tokenSymbol) {
    balanceOf[msg.sender] = initialSupply;              // Give the creator all initial tokens
    name = tokenName;                                   // Set the name for display purposes
    symbol = tokenSymbol;                               // Set the symbol for display purposes
    decimals = decimalUnits;                            // Amount of decimals for display purposes
}

마지막으로 Events가 필요합니다. 이것은 특수한 비어있는 함수로서 이더리움 지갑이 계약의 활동을 추적하게 하는데 사용 됩니다. Events는 대문자로 시작 해야 됩니다. 아래의 line을 계약의 초반부에 event로 선언해줍니다.

event Transfer(address indexed from, address indexed to, uint256 value);

그리고 아래의 2라인을 transfer 함수에 추가 해줍니다.

   /* Notify anyone listening that this transfer took place */
    Transfer(msg.sender, _to, _value);

자 그럼 당신의 토큰은 준비가 됬습니다!

이후의 번역은 #2에서 이어서 하겠습니다.

Sort:  

Hi. I am a volunteer bot for @resteembot that upvoted you.
Your post was chosen at random, as part of the advertisment campaign for @resteembot.
@resteembot is meant to help minnows get noticed by re-steeming their posts


To use the bot, one must follow it for at least 3 hours, and then make a transaction where the memo is the url of the post.
If you want to learn more - read the introduction post of @resteembot.
If you want help spread the word - read the advertisment program post.


Steem ON!

Coin Marketplace

STEEM 0.28
TRX 0.12
JST 0.032
BTC 66167.71
ETH 3014.78
USDT 1.00
SBD 3.73