====== OpenZeppelin で ERC20 トークンの作成 ======
ほぼ OpenZeppelin オフィシャルの[[https://docs.openzeppelin.com/contracts/4.x/erc20|ドキュメント]]通りに ERC20 トークンを実装します。つまり、オリジナルのコインを発行します。
作成したコインは address 間で送金することもできます! それも最後で確認します。
===== 前提 =====
Truffle と npm をインストールしておいてください。
(参考) [[blockchain:truffleを使ったスマートコントラクト開発|Truffleを使ったスマートコントラクト開発]]
===== プロジェクト作成 =====
> mkdir coin_project
> cd coin_project
coin_project> truffle init
[[blockchain:truffleを使ったスマートコントラクト開発|Truffleを使ったスマートコントラクト開発]] を参考に truffle-config.js の設定をしてください。(どの ethereum ブロックチェーンに接続するか設定する必要があります。)
===== OpenZeppelin のインストール =====
npm を使用して OpenZeppelin をインストールします。
coin_project> npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help init` for definitive documentation on these fields
and exactly what they do.
Use `npm install ` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
package name: (coin_project)
version: (1.0.0)
description:
entry point: (truffle-config.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to C:\Users\miyazato\work\ethereum\coin_project\package.json:
{
"name": "coin_project",
"version": "1.0.0",
"description": "",
"main": "truffle-config.js",
"directories": {
"test": "test"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Is this OK? (yes)
coin_project> npm install --save-dev @openzeppelin/contracts
===== ERC20スマートコントラクト(コイン)の実装 =====
coin_project> truffle create contract OCCToken
coin_project> code contracts/OCCToken.sol
// contracts/OCCToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract OCCToken is ERC20 {
constructor(uint256 initialSupply) ERC20("OkinawaComputerCenter", "OCC") {
_mint(msg.sender, initialSupply);
}
}
===== マイグレーション =====
coin_project> truffle create migration OCCToken
coin_project> code .\migrations\1651976599_o_c_c_token.js
OCCToken スマートコントラクトはデプロイ時にコインの総数(initialSupply)を決定する必要があります。
マイグレーションファイルで initialSupply を10000000枚に指定してみます。
:!: _deployer.deploy の引数は「OCCToken(10000000)」ではなく「OCCToken, 10000000」と記述する必要があります。
const OCCToken = artifacts.require("OCCToken");
module.exports = function(_deployer) {
// Use deployer to state migration tasks.
_deployer.deploy(OCCToken, 10000000)
};
===== デプロイ(Mint) =====
ERC20 はデプロイ時に新しいToken(コイン)が Mint されます。
実際、OCCToken スマートコントラクトのコンストラクタ(デプロイ時に1度だけ実行される)を見ると「_mint」メソッドを呼び出しています。
coin_project> truffle migrate
===== 実行 =====
OCCToken スマートコントラクトを呼び出して、コインの総数を確認してみます。
coin_project> truffle console
truffle(development)> let OCCToken = await OCCToken.deployed();
truffle(development)> OCCToken.totalSupply()
BN {
negative: 0,
words: [ 10000000, <1 empty item> ],
length: 1,
red: null
}
truffle(development)> let address = await web3.eth.getAccounts();
truffle(development)> let deployerAddress = address[0];
truffle(development)> OCCToken.balanceOf(deployerAddress);
BN {
negative: 0,
words: [ 10000000, <1 empty item> ],
length: 1,
red: null
}
===== 送金 =====
OCCToken を他のアドレスに送金してみます。
truffle(development)> let receiverAddress = address[1];
undefined
truffle(development)> OCCToken.balanceOf(receiverAddress);
BN { negative: 0, words: [ 0, <1 empty item> ], length: 1, red: null }
truffle(development)> OCCToken.transfer(receiverAddress, 10000);
{
tx: '0xe0d508b45e2bb412f5c540d96e133a185f5ae4162eb24288d36ee09b7970e825',
receipt: {
transactionHash: '0xe0d508b45e2bb412f5c540d96e133a185f5ae4162eb24288d36ee09b7970e825',
transactionIndex: 0,
blockHash: '0xf7c10358304e2a6de5ac1e1f4e13f83df5a785f49a151df39477727b11ddfa86',
blockNumber: 5,
from: '0x0172ffd2b8ff73056a187fc242af249ac585cc3b',
to: '0xaee728a629b239fcf3b56d21067ba36a0a4dbd6c',
gasUsed: 51839,
cumulativeGasUsed: 51839,
contractAddress: null,
logs: [ [Object] ],
status: true,
logsBloom: '0x00000008001010000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000002000000000000000010000000000001000000000000000000000000000000000000010000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000',
rawLogs: [ [Object] ]
},
logs: [
{
logIndex: 0,
transactionIndex: 0,
transactionHash: '0xe0d508b45e2bb412f5c540d96e133a185f5ae4162eb24288d36ee09b7970e825',
blockHash: '0xf7c10358304e2a6de5ac1e1f4e13f83df5a785f49a151df39477727b11ddfa86',
blockNumber: 5,
address: '0xaeE728a629b239fCf3B56d21067ba36A0A4dbd6C',
type: 'mined',
id: 'log_e6c66317',
event: 'Transfer',
args: [Result]
}
]
}
truffle(development)> OCCToken.balanceOf(deployerAddress);
BN {
negative: 0,
words: [ 9990000, <1 empty item> ],
length: 1,
red: null
}
truffle(development)> OCCToken.balanceOf(receiverAddress);
BN {
negative: 0,
words: [ 10000, <1 empty item> ],
length: 1,
red: null
}
truffle(development)>
===== まとめ! =====
:!: ここまで来ると、実は ETH の実体もスマートコントラクトであることが分かります! 8-O LOL