「Solidity何もわからん」な状態だったので
- ERC20トークンを自分で書いてローカルなEthereum環境にデプロイ
- その後、テストネット(Goerli)にデプロイ
するところまでやってみたのでメモ。
準備するやつ
Truffle
ローカルでコントラクトを開発するためのフレームワーク的なやつ。
以下でインストールできます。
npm install -g truffle
Ganache
ローカルでEthereumノードを動かすためのツール。
ノードを動かすだけじゃなくて100ETHが入ったアカウント×10個を自動生成してくれるぽいです。
以下でインストールできます。
npm install -g ganache-cli
ちなみにGUI版もあるみたいなのですが、自分の場合はWSL2を使っているので、コマンドライン版を使いました。
テストネットにデプロイするだけならGanacheは不要ですし、何だったらTruffle自体にもローカルEthereum環境を構築する機能があるぽいので、試しにデプロイしてみるだけならTruffleだけでいい気がします。
(Truffleでもtruffle developで同じことができます)
やること
プロジェクトに準備
以下のコマンドを実行します。
# ディレクトリを作って移動 mkdir solidity-test-erc20 cd solidity-test-erc20 # 初期化 npm init -y truffle init # VScodeを開く code .
こんな感じのVScodeが開いたら成功です👇

コントラクトを書く
contractsディレクトリ配下に、コントラクトを書きます。
自分の場合は、試しにテストしてみたかっただけなので、ERC20に準拠したコードを1から書きました👇
ERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract ERC20 {
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(
address indexed _owner,
address indexed _spender,
uint256 _value
);
string public name;
string public symbols;
uint8 public decimals = 18;
uint256 public totalSupply;
mapping(address => uint256) private ownerToBalance;
mapping(address => mapping(address => uint256)) private allowances;
constructor(
string memory _name,
string memory _symbols,
uint256 _totalSupply
) {
name = _name;
symbols = _symbols;
totalSupply = _totalSupply;
ownerToBalance[msg.sender] = _totalSupply;
}
function balanceOf(address _owner) external view returns (uint256 balance) {
return ownerToBalance[_owner];
}
function transfer(address _to, uint256 _value) external returns (bool) {
_transfer(msg.sender, _to, _value);
return true;
}
function transferFrom(
address _from,
address _to,
uint256 _value
) public returns (bool) {
require(
allowances[_from][_to] >= _value,
"transfer amount exceed amount"
);
_transfer(_from, _to, _value);
allowances[_from][_to] -= _value;
return true;
}
function _transfer(
address _from,
address _to,
uint256 _value
) private {
require(_from != _to, "to == from");
require(ownerToBalance[_from] >= _value, "insufficient balance");
ownerToBalance[_from] -= _value;
ownerToBalance[_to] += _value;
emit Transfer(_from, _to, _value);
}
function approve(address _spender, uint256 _value) public returns (bool) {
allowances[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender)
public
view
returns (uint256 remaining)
{
return allowances[_owner][_spender];
}
}
本来は普通のERC20トークンを作るだけならこんなコードを書く必要はなくて、openzepplinなどで公開されているERC20.solファイルを継承して、コンストラクタを書くだけでいいはずです。
むしろそうしたほうが
- コントラクト部分を書くだけでいいので楽ちん(たぶん10行くらい書くだけでいい)
- セキュリティに強い
- +αの機能がついてる
- たとえばincreaseAllowanceみたいな関数はERC20に定義されているわけじゃない
という感じでメリットだらけです。
ですが今回は勉強のために自分で書いた感じです。
コントラクトをコンパイル
以下のコマンドで、contractsディレクトリ配下の.solファイルがコンパイルできます。
truffle compile
コンパイルが成功したら、プロジェクトの直下にbuildというディレクトリが生成されて、その中にコントラクトのABIなJSONファイルが作成されます。
デプロイ用のコードを書く
migrationsディレクトリ直下に、2_◯◯◯◯.jsというファイルを作ります。
必ず先頭に2という数字を付ける必要があります。
中身は以下のようにします。
const ERC20 = artifacts.require("ERC20");
const toWei = (number) => web3.utils.toWei(web3.utils.toBN(number), "ether");
module.exports = async function (deployer) {
await deployer.deploy(ERC20, "penpen", "PEN", toWei(10 ** 10));
};
5行目の部分は
- penpen:コントラクトの名前
- PEN:トークンのシンボル
- toWei(10 ** 10):発行数
です。(コントラクトのコンストラクターにわたす引数です)
Ganacheにデプロイ
ganache-cliでローカル環境を立ち上げます。
別ターミナルを立ち上げて、truffle migrationでデプロイします。
あとはTruffleでコンソールの中に入って、デプロイされたことを確認できます。
Goerliにデプロイ
次は本番環境のテストネットにデプロイします。
まず以下をインストールします。
npm install -D @truffle/hdwallet-provider
次に、InfuraでサインアップしてAPIキーを取得します。

▲こんな感じのAPIキー入りのURLを取得する
次にtruffle-config.jsの中のnetworksプロパティ配下に、以下のプロパティを追加します。
goerli: {
provider: () => {
return new HDWalletProvider(
"ここにニーモニックを入れる",
"https://goerli.infura.io/v3/ここに自分のAPIキーを入れる
);
},
network_id: "5", // eslint-disable-line camelcase
gas: 4465030,
gasPrice: 10000000000,
},
「ここにニーモニックを入れる」の部分は、ウォレットを作ったときに最初に表示される20個くらいのワードの組み合わせのアレです。
そのニーモニックによって生成されるウォレットの1番目が使用されます。
「何個目のウォレットを使用するか」については、new HDWalletProviderの引数で指定できます。(詳しくは公式に載ってます。)
準備ができたら、以下のコマンドでデプロイします。
truffle migrate --network goerli
EtherScanでVerify
デプロイ後は、EtherscanのGoerliページにコントラクトアドレスを入力すると確認できます。
たとえば私がデプロイしたコントラクトは以下のURLから見れます。
https://goerli.etherscan.io/address/0x4cB3208229d6F3Cf5D1017E1c409190Ef5a6B8B5#code
ただこのままだと「ソースコードをverifyしてね」な画面が表示されてしまってるのでverifyします。

以下の記事が参考になります。
https://medium.com/quick-programming/verify-a-smart-contract-on-etherscan-using-truffle-cb2656fd9c41
基本的には以下の流れを行うだけです。
- truffle-plugin-verifyというnpmパッケージを追加する
- truffle-config.jsをいじる
truffle run verify ERC20 --network goerliを実行する
これだけでverifyできます。
これで以下のようにコントラクトの中身が表示されるようになります。

Read Contractからコントラクトを操作できたりもします👇

▲きちんと発行した分が指定したアドレスが保持されていることを確認できる
おわり
コメント