カテゴリー

【開発初級者向け】ERC20トークンの中身をVIPSトークンのテンプレートを使って解説するよ!

VIPSTARCOIN(VIPS)ではイーサリアムなどと同じようにトークンを作ることが出来ます。トークンを作る方法はWikiなどにまとまっているのですが、学習目線でトークンの中身まで解説している記事はなさそうだったので、私なりにまとめてみました。

VIPS VIPSTARCOIN

ERC20トークンとは?

ERC20は規格の名前です。変数名や関数を揃えることで共通のウォレットでトークンを扱えるようにしています。VIPSトークンのテンプレートもERC20の規格に従っています。

ソースコードを見てみよう!

ソースコードはこちら
少しづつ見ていきます。

変数:name, symbol, decimals, totalSupply

string public name;
string public symbol;
uint8 public decimals = 18;
uint256 public totalSupply;

コントラクト内に持っている変数です。トークンの基本的な情報を記録しています。
name:トークン名称
symbol:トークンシンボル
decimals:小数点以下桁数
totalSupply:総発行枚数

decimalsはコードを直接書き換えることで指定します。それ以外はトークン作成時に指定して変更できないつくりになっています。
余談ですが、イーサリアムでは最小単位が小数点以下18桁(1wei)なのでそれと揃えることが推奨されています。VIPSは小数点以下8桁なのでdecimalsは8か、小数点以下の管理が不要であれば0で良いと思います。

変数:balanceOf

mapping (address => uint256) public balanceOf;

トークンの残高を記録する変数です。固定ではなく取引のたびに変更されます。
誰(address)が何個(uint256)持っているかを配列(mapping)で管理しています。

コンストラクタ

function TokenERC20(
    uint256 initialSupply,
    string tokenName,
    string tokenSymbol
) public {
    totalSupply = initialSupply * 10 ** uint256(decimals);
    balanceOf[msg.sender] = totalSupply;
    name = tokenName;
    symbol = tokenSymbol;
}

トークンを作成する際に呼ばれる初期化処理です。
総発行枚数、トークン名、トークンシンボルを受け取ってコントラクト内の変数に記録します。トークンの残高は最初は発行者(msg.sender)が総発行枚数すべてを持つ形になります。

関数:transfer()

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

function _transfer(address _from, address _to, uint _value) internal {
    require(_to != 0x0);
    require(balanceOf[_from] >= _value);
    require(balanceOf[_to] + _value >= balanceOf[_to]);
    uint previousBalances = balanceOf[_from] + balanceOf[_to];
    balanceOf[_from] -= _value;
    balanceOf[_to] += _value;
    emit Transfer(_from, _to, _value);
    assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
}

function transfer(address _to, uint256 _value) public returns (bool success) {
    _transfer(msg.sender, _to, _value);
    return true;
}

自分の持っているトークンを他のアドレスに送る処理です。
ウォレットなどから呼ばれるのはtransfer()で、_transfer()はinternal(コントラクト内からしか呼べない)ですが、送信処理自体は_transfer()で行っています。トークンを送信するたびにTransferというイベントがブロックチェーンに書き込まれるようになっています。

変数:allowance

mapping (address => mapping (address => uint256)) public allowance;

他の人にトークンを引き出す許可を出している個数です。
AさんがBさんに許可を出しているトークンの数を配列で持っています。
アドレスの配列の中のアドレスの配列の中に数字が入っています。(ややこしい)

関数:approve()

event Approval(address indexed _owner, address indexed _spender, uint256 _value);

function approve(address _spender, uint256 _value) public
    returns (bool success) {
    allowance[msg.sender][_spender] = _value;
    emit Approval(msg.sender, _spender, _value);
    return true;
}

他の人(アドレス)に自分の持っているトークンを送信する(引き出す)許可を与えます。
まだ実際にトークンが送られるわけではありません。

関数:transferFrom()

function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
    require(_value <= allowance[_from][msg.sender]);
    allowance[_from][msg.sender] -= _value;
    _transfer(_from, _to, _value);
    return true;
}

transfer()と名前が似ていますが、こちらは自分のものではなく他人のトークンを他の人に送る処理です。approve()で持ち主から許可された数までしか送れません。

(追加機能)関数:approveAndCall()

interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) external; }

function approveAndCall(address _spender, uint256 _value, bytes _extraData)
    public
    returns (bool success) {
    tokenRecipient spender = tokenRecipient(_spender);
    if (approve(_spender, _value)) {
        spender.receiveApproval(msg.sender, _value, this, _extraData);
        return true;
    }
}

単純にapprove()を実行するのではなく、相手に許可を出したことを通知するようにしたいようなのですが動くか分かりません。

(追加機能)関数:burn()

event Burn(address indexed from, uint256 value);

function burn(uint256 _value) public returns (bool success) {
    require(balanceOf[msg.sender] >= _value);
    balanceOf[msg.sender] -= _value;
    totalSupply -= _value;
    emit Burn(msg.sender, _value);
    return true;
}

自分の持っているトークンを焼く(捨てる)処理です。総発行枚数(totalSupply)も減ります。

(追加機能)関数:burnFrom()

function burnFrom(address _from, uint256 _value) public returns (bool success) {
    require(balanceOf[_from] >= _value);
    require(_value <= allowance[_from][msg.sender]);
    balanceOf[_from] -= _value;
    allowance[_from][msg.sender] -= _value;
    totalSupply -= _value;
    emit Burn(_from, _value);
    return true;
}

他の人の持っているトークンを焼く(捨てる)処理です。
transforFrom()と同じで許可をもらってない分を勝手に焼くことはできません。

The following two tabs change content below.



    • このエントリーをはてなブックマークに追加