'2017/07/07'에 해당되는 글 2건

  1. 2017.07.07 이더리움 - Token 만들기(2)
  2. 2017.07.07 이더리움 - Token 만들기(1) 4
블록체인2017. 7. 7. 17:49


토큰 기능 개선


암호화토큰은 코드를 만지지도 않고 바로 만들어 배포할 수 있다. 하지만 진짜 마술은 커스터마이징하면서 발생한다. 이번 장에서는 토큰에 추가 할 수있는 함수에 대한 제안을 제공하여 사용자의 필요에 더 적합하게 만든다.


중앙화된 관리자


dapp이 기본적으로 분산되어 있지만 원한다면 중앙화된 관리자를 가질수 없다는것을 의미하지는 않는다. 중앙에서 어떤 제약조건을 강제하고 싶을 수 있다. 이런 기능을 추가할 수 있으며 시작시에 추가할 수 있다 이는 모든 토큰 소유자는 게임을 소유하기로 결정하기전에 게임의 규칙을 정확하게 알 수 있다.


그러려면 화폐에 대한 중안컨트롤러가 필요하다. 이는 단순한 계정이 될수 있지만 또 한 컨트랙트로 가능하며 토큰을 생성하는데 이 컨트랙트에 따라서 결정이 되게 된다. 투표권을 부여할 수 있는 민주적단체이거나 토큰 주인에게 제한적인 능력만을 부여 할 수 있다.



contract owned {

    address public owner;


    function owned() {

        owner = msg.sender;

    }


    modifier onlyOwner {

        if (msg.sender != owner) throw;

        _;

    }


    function transferOwnership(address newOwner) onlyOwner {

        owner = newOwner;

    }

}


이것은 소유할 수 있는 계약에 대한 아주 기본적인 코드이가. 다음 단계로 컨트렉트에 추가한다.


contract MyToken is owned {

    /* the rest of the contract as usual */


이는 MyToken의 내부 어디에서든 owner와 modifier onlyOwner에 접근이 가능하다는 것을 의미한다. transferOwnership이라는 함수를 가지고 있다. 이 정보가 아주 중요하기 때문에 컨트랙트 시작시 셋업할 수 있다.


function MyToken(

    uint256 initialSupply,

    string tokenName,

    uint8 decimalUnits,

    string tokenSymbol,

    address centralMinter

    ) {

    if(centralMinter != 0 ) owner = centralMinter;


CENTERAL MINT


회전되고 있는 동전의 양이 바뀌길 원한다고 가정하자. 이것은 실제로 금괴인증서나 정부통화같은 블록체인이 아닌 자산(off blockchain asset)를 나타내며 가상 재고가 실제 재고를 반영하도록 하려는 경우이다.이는 통화보유자가 토큰 가격을 통제하기를 원하고 회전되고 있는 통화를 더 발행하거나 제거하려는 경우도 해당된다.


먼저 해야할것은 totalSuplly를 추가하고 초기화하는것이다.


contract MyToken {

    uint256 public totalSupply;


    function MyToken(...) {

        totalSupply = initialSupply;

        ...

    }

    ...

}


이제 새함수를 추가하여 소유자가 새로운 토큰을 만들수 있게 한다.


function mintToken(address target, uint256 mintedAmount) onlyOwner {

    balanceOf[target] += mintedAmount;

    totalSupply += mintedAmount;

    Transfer(0, owner, mintedAmount);

    Transfer(owner, target, mintedAmount);

}


함수명 뒤에 onlyOwner를 주의깊게 봐야한다. 이는 앞서 정의한 mofifier onlyOwner에서 상속되어 컴파일되어 재작성될것이라는것을 의미한다. 이 함수의 코드는 mofifier함수의 밑줄 부분에 삽입될것이다. 이는 이 함수가 해당 계정에 의해서만 호출되고 owner로 셋팅될것을 의미한다. 이 코드만 추가하면 더 많은 코인을 생성할 수 있다.


자산의 동결


토큰의 사용유형에 따라 사용할 수 있는 사람과 할수 없는 사람에 대한 규칙적인 제한이 필요할 수 있다. 그러려면 자산을 동결하거나 해재하는 파라메터를 컨트랙트에 추가해야 한다.


아래 변수와 함수를 아무데나 컨트랙트내에 추가한다. 아무데나 가능하지만 다른 이벤트나 매핑과 함께 배치하는게 좋다.


mapping (address => bool) public frozenAccount;

event FrozenFunds(address target, bool frozen);


function freezeAccount(address target, bool freeze) onlyOwner {

    frozenAccount[target] = freeze;

    FrozenFunds(target, freeze);

}


이 코드로 기본적으로 미동결상태인 모든 계좌를 Freeze Account를 호출함으로써 동결할 수 있다. 불행히도 동결은 아무런 효과가 없다. 왜냐하면 transfer함수에 아무것도 추가하지 않았기 때문에, 그래서 다음과 같이 해야 한다.


function transfer(address _to, uint256 _value) {

    if (frozenAccount[msg.sender]) throw;


이제 동결된 계좌는 자금은 있지만 송금은 할  수 없다. 디폴트는 미동결계좌이나 원한다면 화이트리스트를 관리하면서 원할 때 계좌를 동결할 수 있다. frozenAccount를 approvedAccount로 변경하여 적용이 가능하다.


if (!approvedAccount[msg.sender]) throw;


자동 구매 및 판매


지금까지 토큰을 평가하기 위해 유틸리티와 신뢰에 의존했다. 하지만 원한다면 자동으로 시장의 가치를 기준으로 구입하는 펀드를 만들어 토큰의 가치를 이더(또는 다른 토큰)로 뒷받침 할 수 있다.


먼저 구매와 판매가격을 셋팅한다.


uint256 public sellPrice;

uint256 public buyPrice;


function setPrices(uint256 newSellPrice, uint256 newBuyPrice) onlyOwner {

    sellPrice = newSellPrice;

    buyPrice = newBuyPrice;

}


이것은 가격에 접근가능하게 하며 자주 변하지 않는다. 이를 변경하려면 트랜잭션을 싱행하면서 이더를 소비하게 되기 때문이다. 변동가격을 일정하게 유지하려면 표준데이터피드를 참고하라.


다음은 구매와 판매함수를 작성한다.


// 살때

// msg.sender => 구매자

function buy() payable returns (uint amount){

    amount = msg.value / buyPrice;                     // msg.value는 구매금액(eth), 구매금액을 토큰가격으로 나눠서 토큰개수 계산

    if (balanceOf[this] < amount) throw;               // 현재 토큰잔액 확인

    balanceOf[msg.sender] += amount;                   // 구매자 토큰개수 추가

    balanceOf[this] -= amount;                         // 판매자 토큰개수 차감

    Transfer(this, msg.sender, amount);                // 전송 수행

    return amount;                                     // 토큰개수 반환

}


// 팔때

// msg.sender => 판매자

function sell(uint amount) returns (uint revenue){

    if (balanceOf[msg.sender] < amount ) throw;   // 판매자 토큰 잔액 확인

    balanceOf[this] += amount;                              // 구매자 토큰잔액 추가

    balanceOf[msg.sender] -= amount;                   // 판매자 토큰 잔액 차감 subtracts the amount from seller's balance

    revenue = amount * sellPrice;                // 판매금액 계산(eth)

    if (!msg.sender.send(revenue)) {                   // 판매자에게 이더 전송, 아주 중요함

        throw;                                         // to do this last to prevent recursion attacks

    } else {

        Transfer(msg.sender, this, amount);             // 전송 수행

        return revenue;                                 // 판매금액 반환

    }

}


이게 새로운 토큰을 생성하지 않고 컨트렉트 주체의 잔액을 변경한다는것을 주의깊게 보아야 한다. 컨트랙트는 토큰과 이더 모두 그리고 컨트랙트 소유자를 보유할 수 있으나 가격을 설정하거나 유효한경우 일부 토큰을 생성한다. 이는 은행의 토큰이나 이더를 건드릴수는 없다. 이 컨트랙트에서 펀드를 이동시킬수 있는 유일한 방법은 구매나 판매을 하는것 뿐이다.


가치를 구매 및 판매하는것은 이더내에서 설정되지 않고 유로나 달라의 cent나 비트코인의 satoshi같은 단위인 wei가 있다. 1 이더는 1000000000000000000 wei(10경)이다. 따라서 이더로 토큰을 설정할때 18개의 0을 넣어야 한다. 무쟈게 많다. 10경이니..


컨트랙트를 생성할 때 시장에있는 모든 토큰을 다시 구매할 수 있도록 충분한 양의 이더를 보내야 한다.그렇지 않으면 컨트랙트가 파산하여 사용자가 토큰을 판매 할 수 없게 된니다.


위 샘플에서는 단일 중앙구매자와 판매자간의 컨트랙트를 설명했지만 좀더 흥미롭게 다른 사람이 다른 가격을 입찰하거나 외부에서 가격을 직접로드할 수 있습니다.


자동리필


이더리움에서 트랜잭셕이 일어날때마다 채굴자에게 일정비율의 요금을 지불하게 되는데 이 값은 컨트랙트에서 계산되어진다. 순간적으로 수수료는 이더로만 지불되므로 토큰의 모든 사용자는 이더를 필요로 한다. 소유자가 필요한 비용이 지불할 수 있을 때 까지 수수료보다 적은 잔액을 가진 계좌의 토큰은 정지(stick)된다. 하지만 어떤 경우에는 유저가 이더리움, 블록체인 또는 이더리움을 어떻게 얻을 수 있는지 몰라도 되기를 원할 수 있다. 이 경우 한가지 가능한 접근방법은 잔액이 너무 적게되면 자동으로 채워질 수 있게 하는것이다.


이렇게 하기 위해서는 먼저 임계치값을 변수로 생성해야 하며 변경할 수 있게 해야 한다. 5 finney(0.005 ether)로 설정해보자


uint minBalanceForAccounts;


function setMinBalance(uint minimumBalanceInFinney) onlyOwner {

     minBalanceForAccounts = minimumBalanceInFinney * 1 finney;

}


그리고 transfer함수를 수정한다.


/* Send coins */

function transfer(address _to, uint256 _value) {

    ...

    if(msg.sender.balance<minBalanceForAccounts)

        sell((minBalanceForAccounts-msg.sender.balance)/sellPrice);

}


송금인이 수취인에게 수수료를 지불할 수 있도록 변경할수도 있다.


/* Send coins */

function transfer(address _to, uint256 _value) {

    ...

    if(_to.balance<minBalanceForAccounts)

        _to.send(sell((minBalanceForAccounts-_to.balance)/sellPrice));

}


이러면 토큰을 받는 계좌가 수수료를 지불하는데 필요한 이더보다 적게 수수료를 지불하지 않습니다.


작업검증


수학공식을 코인과 엮는 몇가지 방안이 있다. 가장 간단한 방법은 이더로 "병합된 광산(채굴)"로 만드는것이다. 다시 말해 이더리움에서 블록을 발견한 사람은 누구나 그 불록에 대한 보상 기능을 호출하면 코인에서 보상을 받을것이다. 블록을 찾은 광부를 지칭하는 coinbase 키워드로 이를 수행할 수 있다.


function giveBlockReward() {

    balanceOf[block.coinbase] += 1;

}


이것은 또한 수식을 추가할 수 있는데 누구든 이를 수행하면 보상에서 승리할 수 있다. 다음 예에서 당신은 포인트를 얻는 현재 도전의 큐빅루트를 계산해야 하고 다음 도전을 설정할 수 있는 권한을 얻는다.


uint currentChallenge = 1; // Can you figure out the cubic root of this number?


function rewardMathGeniuses(uint answerToCurrentReward, uint nextChallenge) {

    if (answerToCurrentReward**3 != currentChallenge) throw; // If answer is wrong do not continue

    balanceOf[msg.sender] += 1;         // Reward the player

    currentChallenge = nextChallenge;   // Set the next challenge

}


물론 계산을 누군가의 머리로 하는것은 많이 어렵지만 계산기는 아주 쉽다.그래서 이 게임은 컴퓨터로는 금방 끝난다. 또한 마지막 승자가 다음 도전을 고를수 있기 때문에 다른 플레이어에게는 공정하지 않다. 인간에게는 쉽지만 기게로는 매우 어렵지만 스크립트로 코딩하는것을 매우 어렵다. 대신에 더 공정한 시스템은 기계가 할 수 있는것은 매우 어렵지만 기계가 검증하기가 그리 어렵지는 않다. 가장 적절한 후보는 도전자가 주어진 난이도보다 낮은 해시를 찾을때 까지 여러 숫자의 해시를 생성해야 하는 해시 도전을 만드는것이다.

이 프로세스는 1997년 Adam Back에 의해 hashcash로 처음 제안되었고 2008년에 satosi nakamoto의 비트코인에서 구현되었습니다. 이더리움은 보안모델을 위해 이러한 시스템을 사용하여 출시되었지만 작업증명보안모델에서 혼합된 모델(링크탭하여 더 알아보세요)로 이동하려고 계획하고 있습니다.

해싱을 코인의 랜덤발행형태로 하려는 경우 작업방행증명이 있는 자신의 이더기반 통화를 만들수 있다.


bytes32 public currentChallenge;                         // The coin starts with a challenge

uint public timeOfLastProof;                             // Variable to keep track of when rewards were given

uint public difficulty = 10**32;                         // Difficulty starts reasonably low


function proofOfWork(uint nonce){

    bytes8 n = bytes8(sha3(nonce, currentChallenge));    // Generate a random hash based on input

    if (n < bytes8(difficulty)) throw;                   // Check if it's under the difficulty


    uint timeSinceLastProof = (now - timeOfLastProof);  // Calculate time since last reward was given

    if (timeSinceLastProof <  5 seconds) throw;         // Rewards cannot be given too quickly

    balanceOf[msg.sender] += timeSinceLastProof / 60 seconds;  // The reward to the winner grows by the minute


    difficulty = difficulty * 10 minutes / timeSinceLastProof + 1;  // Adjusts the difficulty


    timeOfLastProof = now;                              // Reset the counter

    currentChallenge = sha3(nonce, currentChallenge, block.blockhash(block.number-1));  // Save a hash that will be used as the next proof

}


생성자함수도 변경해야 한다.


    timeOfLastProof = now;


컨트랙트가 온란인상태가 되면 "작업 증명"기능을 선택하고 nonce필드에 원하는 번호르 추가하여 실행해라. 확인 창이 "데이터를 실행할 수 없습니다"라는 빨간색 경고 메시지가 나타나면 거래가 진행될때까지 다른 번호를 선택하라. 이 프로세스는 임의적이다. 하나를 찾으면 마지막 보상이 주어지기 때문에 매 순간마다 1토큰을 받게되며 도전난이도는 보상당 평균 10분을 목표로 위아래로 조정된다.

보상을 제공하는 번호를 찾으려는 이 과정을 채굴이라고 부른다. 난이도가 올라가면 숫자를 찾기가 어려울 수 있지만 발견한것을 확인하는것은 항상 쉽다.



Posted by 삼스
블록체인2017. 7. 7. 13:34

https://www.facebook.com/groups/1429149120539506/



이 글은 https://ethereum.org/token 의 발번역입니다.

참고용으로만...


이글은 비트코인과 이더리움에 대한 이해가 있다는것을 가정합니다. 이더리움으로 만들 수 있는 여러가지 유형의 애플리케이션중에 토큰베이스에 대해서 설명합니다.


우리는 디지털토큰을 만들것이다. 이더리움 생태계에서 토큰은 모든 대체가능한 상품(동전, 누적포인트, 금인증서, 게임아이템등)을 나타낼수 있다. 모든 토큰들은 표준방식으로 몇가지 기본기능을 구현하기 때문에 이더리움 지갑, 다른 클라이언트 또는 동일한 표준을 사용하는 계약과 바로 호환될 수 있습니다.


아래 코드를 복붙해서 바로 사용 가능하다


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;

    }

}


토큰 컨트랙트는 상당히 복잡하다. 다음은 토큰을 구현하기 위한 최소의 코드이다.


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

    }

}


코드를 이해해 보자



지갑앱을 실행 > Contract탭 > Deploy New Contract 선택

Solidity Contract Source code 입력필드에 아래 코드 입력


contract MyToken {

    /* This creates an array with all balances */

    mapping (address => uint256) public balanceOf;

}


매핑이란 주소를 잔액과 연결하는 연관 배열을 의미한다. 주소는 16진수 이더리움 포맷이며 잔액은 0에서 115*1027 범위의 정수이다 얼마나 큰수인지 상상이 안간다면 네가 계획산 전체 토큰수보다 많을거다. public 키워드는 블록체인에서 어디서든 접근 가능하게 한다. 즉 모든 잔액이 공개되어야 한다(클라이언트가 표시해야 하는 경우).


컨트랙트를 발행 했다면 효과가 있지만 유용하지는 않다. 즉 토큰의 잔액을 주소로 조회할 수 있는 컨트랙트가 될수 있으나 토큰 하나를 만들지 않았기 때문에 모두가 0을 반환한다. 그래서 시작할때 몇개의 토큰을 만들것이다. mapping... 바로 아래 코드를 추가하라.


contract MyToken {

    /* This creates an array with all balances */

    mapping (address => uint256) public balanceOf;

    

    function MyToken() {

        balanceOf[msg.sender] = 21000000;

    }

}


function MyToken과 contract MyToken이 동일한것을 눈여겨 보아야 한다. 하나를 변경하면 나머지 하나도 변경해야 한다. 생성자 역할을 하며 네트워크에 컨트랙트가 업로드될때 한번만 호출된다. 이 함수는 컨트랙트를 전개한 사용자인 msg.sender의 잔액을 2100만 잔고로 설정한다.

이 값은 이렇게 고정된 수가 아니라 파라메터로 초기화를 하는것이 좋다.


function MyToken(uint256 initialSupply) {

    balanceOf[msg.sender] = initialSupply;

}


컨트랙트 옆에 오른쪽에 보면 드롭다운에서 "My Token"을 선택하면 Constructor parameters를 볼수 있다. 변경가능한 파라메터로 같은코드를 재사용하여 변수를 변경할 수 있다.


지금은 토큰의 잔액을 만든 계약을 가지고 있지만 아무런 변화가 없기 때문에 이제 이동에 대해 구현하겠다.


/* Send coins */

function transfer(address _to, uint256 _value) {

    /* Add and subtract new balances */

    balanceOf[msg.sender] -= _value;

    balanceOf[_to] += _value;

}


이것은 매우 직관적인 기능이다.  수신자와 값을 파라메터로 갖고 호출될때마다 해당 값을 잔액에서 차감하고 수신자의 잔액은 증가시킨다. 여기에는 명백한 문제가 있다. 잔액이 부족할 경우 어떤일이 일어날까? 이 계약에 대해 부체를 처리할것이 아니기 때문에 빠르게 확인하고 송금자의 자금이 충분치 않으면 계약 실행이 중지된다. 또한 오버플로가 있는지 확인하여 0이 되게 하는 너무 큰숫자를 피한다.


계약의 실행을 중간에 정지하려면 return 이나 throw를 호출한다. 전자는 가스비용은 적은 반면 계약의 실행에 의한 변경사항이 적용되면서 더 머리가 아파질수 있다. 반면에 throw는 모든 계약실행을 취소하고 모든 변경을 원상복구하고 가스비용으로 사용된 이더를 잃게된다. 하지만 지갑이 throw를 예측하고 경고를 함으로써 더이상 이더를 소모하는것을 막아준다.


 이 글 작성 이후 2017년 8월 현재 throw는 deprecated되었다. revert(), require(), assert()의 사용이 권장된다.


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;

}


이제 남은것은 계약에 대한 기본정보에 대한 것이다. 이 정보는 추후 토큰의 등록으로 조작이 가능하겠지만 우리는 계약에 직접 추가할것이다


string public name;

string public symbol;

uint8 public decimals;


그리고 생성자 함수를 시작할 때 업데이트한다.


/* 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는 대문자로 시작해야 하고 다음과 같이 이벤트를 선언하라.


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


이제 transfer 함수내에서 호출해주면 된다.


    /* Notify anyone listening that this transfer took place */

    Transfer(msg.sender, _to, _value);


자 이제 토근이 준비가 다 되었다.



배포방법


이더리움지값을 열어서 컨트랙트탭의 "deploy new contract"를 선택하라.

Solidity source filed에 위에서 작성한 소스코드를 복사 및 붙여넣기를 하라. 코드 컴파일이 문제가 없다면 "pick a contract"를 볼수 있을것이고 "MyToken"를 드롭박스에서 선택하라. 그러면 파라메터를 입력할 수 있는 컬럼이 보일것이다.  원하는대로 조정할 수 있지만 튜터리얼의 목적에 따라 공급 매개변수 10000개 기호는 %, 소수자릿수 2개를 선택한다. 아래 처럼.

페이지 끝으로 스크롤하면 해당 계약의 계산 비용이 대략적으로 표시되며 이더비용을 지불할 의사가 있는 요금을 선택할 수 있다. 쓰지 않는 초과 이더는 돌려 보내질 것이므로 원한다면 기본 설정을 그대로 둘 수 있다. "배포"를 누르고 계정 암호를 입력 한 후 거래가 시작될 때까지 몇 초 기다린다.


그러면  첫페이지로 이동하여 거래 확인을 기다리는 것을 볼 수 있다. Etherbase(당신의 주계정)을 클릭하면 1분이 지나면 방금 만든 공유의 100%를 계정에 표시한다. 일부를 친구에게 보내려면 친구의 주소를 복사하여 "to"필드에 집어넣고 "send"를 눌러라.


친구에게 보내면 아직 지갑에는 아무것도 표시되지 않는다. 지갑이 알고 있는 토큰만 추적하기 때문에 지갑을 수동으로 추가해야 한다. 이제 '컨트랙트'탭으로 이동하면 새로 생성 된 컨트랙트 링크가 표시된다. 해당 페이지로 이동하려면 클릭한다. 이것은 매우 간단한 컨트랙트 페이지이므로 여기서 할 일이 많지 않다. "주소 복사"를 클릭하고 컨트랙트 주소를 텍스트 편집기에 붙여 넣는다.

확인하고자하는 토큰을 추가하려면 컨트랙트 페이지로 이동 한 다음 "Watch Token"을 클릭하라. 팝업 창이 나타나면 계약서 주소 만 붙여넣는다. 토큰 이름, 기호 및 십진수는 자동으로 채워 져야하지만 그렇지 않은 경우 원하는 것을 넣을 수 있다 (지갑에 표시되는 방식에만 영향을 미침). 이렇게하면 토큰의 잔액이 자동으로 표시되어 다른 사람에게 보낼 수 있다.


이제 당신만의 암호화된 토큰을 가지게 되었다. 토큰은 로컬커뮤니티내에서 가치교환에 유용하게 사용될수 있고, 근무시간 또는 다른 로열티프로그램을 추적할 수 있다. 하지만 통화를 만들어서 본질적인 가치를 만들 수 있는가?






Posted by 삼스