仮想通貨を自分で作ってみた~Remix上でERC20トークンを実装

最近、ブロックチェーンや暗号資産に興味があり色々調べています。理解を深めるために、まず自分で仮想通貨を作ってみました。

今回作成したのはERC20規格のトークンで、Remix上で実装したトークンをイーサリアムテストネットワークに反映します。そして自作のトークンを仮想通貨ウォレットに保存し送金するまでを確認します。トークンの作成は思ったより簡単で誰でもすぐに作ることが出来ます。

作成するトークンの概要

今回作成するトークンの概要は下記の通り

  • 名称:Shanghai Coin
  • シンボル:SHC
  • 発行枚数:100,000
  • ERC20(Ethereum Request for Comments: Token Standard #20)規格

Binance Coin:BNB(ビットコイン、イーサリアムに次ぐ時価総額3位の仮想通貨)等がこのERC20規格で実装されています。

事前準備(MetaMaskの設定)

ERC20規格に対応した仮想通貨ウォレット「MetaMask」を事前に用意します。作成したトークンの保存や送金に利用します。

1.「MetaMask」をChromeブラウザに追加

MetaMask - Chrome ウェブストア

2.イーサリアムの「Ropstenネットワーク」表示

▼Show test networksをONにしてRopstenテストネットワークを表示

f:id:denim012:20211227162225p:plain

今回はメインネットではなく、無料でテスト出来るRopstenネットワークを使用します。

3.テスト用のイーサ(ETH)を取得

▼購入→テストFaucet

f:id:denim012:20211227162242p:plain

▼「request 1 ether from faucet」をクリック

f:id:denim012:20211227162253p:plain

本物のイーサリアムネットワークでは1ETH=46万円位しますが、テストネットワークでは無料でいくらでも取得可能です。作成したトークンをデプロイする際や送金する際に手数料(ガス代)としてETHが必要となります。

4.テスト用アカウント(2つ目)を作成

▼送金テスト用にサブアカを作成

f:id:denim012:20211227162328p:plain

RemixでERC20のトークンを実装

今回はWebブラウザ上で動作する統合開発環境Remixを使用して、ERC20のトークンを実装します。

Remix - Ethereum IDE

言語はEthereumのスマートコントラクトを書く「Solidity」です。

1.コードの記述

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;

import "@openzeppelin/contracts@4.4.1/token/ERC20/ERC20.sol";

contract ShanghaiCoin is ERC20 {
    constructor() ERC20("Shanghai Coin", "SHC") {
        _mint(msg.sender, 100000 * 10 ** decimals());
    }
}

たったこれだけの記述で、トークンの作成が完了です。OpenZeppelinの「ERC20」ライブラリを継承すれば自分で処理を記述しなくても基本的な機能は全て用意されています。

2.コードをコンパイル

▼Remix上でCompileボタンを押下

f:id:denim012:20211227162455p:plain

3.Ropsten環境にデプロイ

▼EvvironmentにInjected Web3を選択しDeploy

f:id:denim012:20211227162528p:plain

deployerにこの時点でShanghai Coin:100,000枚が与えられました。(コンストラクターのmint処理が実行されトークンが作成・発行された)

4.「MetaMask」で作成したトークンを表示

▼「Import tokens」を選択し、トークンコントラクトアドレスを入力(デプロイコントラクトアドレスからコピー)

f:id:denim012:20211227162628p:plain

▼ウォレットに自作トークンShanghai Coin:100,000SHCが表示されました。

f:id:denim012:20211227162651p:plain

5.トークンの送金

MetaMaskを使用して「テストアカウント(deployer)」から別のアカウントに送金します

f:id:denim012:20211227162701p:plain

送金手数料(ガス代)としてETHが必要になります。

f:id:denim012:20211227162711p:plain

▼実際に送金した際の詳細情報

f:id:denim012:20211227165434p:plain

処理には2分ほど時間がかかりました。また、何度か送金を試してみましたが毎回手数料が大きく異なります。

トークンの機能追加

上記で作成したトークンは基本機能のみを実装したものです。今度はOpenZeppelinで提供している各種機能を取り込んだトークン「Shanghai Coin Version2」を作成します。

▼コード

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;

import "@openzeppelin/contracts@4.4.1/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts@4.4.1/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts@4.4.1/token/ERC20/extensions/ERC20Snapshot.sol";
import "@openzeppelin/contracts@4.4.1/access/Ownable.sol";
import "@openzeppelin/contracts@4.4.1/security/Pausable.sol";
import "@openzeppelin/contracts@4.4.1/token/ERC20/extensions/draft-ERC20Permit.sol";
import "@openzeppelin/contracts@4.4.1/token/ERC20/extensions/ERC20Votes.sol";
import "@openzeppelin/contracts@4.4.1/token/ERC20/extensions/ERC20FlashMint.sol";

contract ShanghaiCoinVersion2 is ERC20, ERC20Burnable, ERC20Snapshot, Ownable, Pausable, ERC20Permit, ERC20Votes, ERC20FlashMint {
    constructor()
        ERC20("Shanghai Coin Version2", "SHC2")
        ERC20Permit("Shanghai Coin Version2")
    {
        _mint(msg.sender, 100000 * 10 ** decimals());
    }

    function snapshot() public onlyOwner {
        _snapshot();
    }

    function pause() public onlyOwner {
        _pause();
    }

    function unpause() public onlyOwner {
        _unpause();
    }

    function mint(address to, uint256 amount) public onlyOwner {
        _mint(to, amount);
    }

    function _beforeTokenTransfer(address from, address to, uint256 amount)
        internal
        whenNotPaused
        override(ERC20, ERC20Snapshot)
    {
        super._beforeTokenTransfer(from, to, amount);
    }

    // The following functions are overrides required by Solidity.

    function _afterTokenTransfer(address from, address to, uint256 amount)
        internal
        override(ERC20, ERC20Votes)
    {
        super._afterTokenTransfer(from, to, amount);
    }

    function _mint(address to, uint256 amount)
        internal
        override(ERC20, ERC20Votes)
    {
        super._mint(to, amount);
    }

    function _burn(address account, uint256 amount)
        internal
        override(ERC20, ERC20Votes)
    {
        super._burn(account, amount);
    }
}

Minting(発行枚数の増加)やBurning(発行枚数の減少)等の機能を取り込んでいます。

openzeppelinの公式サイトにコード自動生成ツール「Contracts Wizard」があるため、必要な処理をチェックするだけでコードが自動生成されます。

OpenZeppelin

まとめ

ERC20トークンを作成してみました。

トークンの作成はかなり簡単で、知識ゼロ(RemixやSolidityを全く知らない状態)から数時間で作ることが出来ました。ただ、デプロイや送金などのブロックチェーン上に記述する処理では手数料(ガス代)ETHが必要で、処理に時間がかかるので扱いにくさを感じます。

作成したトークンを使用して資金を集める場合、資金決済法等の規制対象となるので要注意です。

今後は、作成したトークンを利用したDApp(分散型アプリケーション)やNFTの作り方についても調べてみようかと思います。