メインコンテンツへスキップ

ERC-20トークンのスマートコントラクトを理解する

スマートコントラクトトークンSolidityerc-20
初級
jdourlens
EthereumDev(opens in a new tab)
2020年4月5日
7 分の読書 minute read
comp-tutorial-metadata-tip-author 0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE

ERC-20は、イーサリアムで最も重要なスマートコントラクトの1つとして知られており、イーサリアムブロックチェーン上のすべてのスマートコントラクトで代替可能なトークンを実装するために用いられる規格として開発されました。

ERC-20では、すべての代替可能なイーサリアムトークンが順守すべき共通ルールを定義しています。 この規格によって、開発者はイーサリアムの大規模なシステム内で新しいトークンがどのように機能するかを正確に予測できます。 トークンが技術標準のルールに従う限り、すべてのプロジェクトにおいて、新しいトークンがリリースされるたびに最初から開発し直す必要がなくなるため、開発者の負担が軽減されます。

ERC-20で実装しなければならないインターフェイスを以下に提示します。 インターフェイスの詳細については、SolidityのOOPプログラミング(opens in a new tab)についての記事をご覧ください。

1pragma solidity ^0.6.0;
2
3interface IERC20 {
4
5 function totalSupply() external view returns (uint256);
6 function balanceOf(address account) external view returns (uint256);
7 function allowance(address owner, address spender) external view returns (uint256);
8
9 function transfer(address recipient, uint256 amount) external returns (bool);
10 function approve(address spender, uint256 amount) external returns (bool);
11 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
12
13
14 event Transfer(address indexed from, address indexed to, uint256 value);
15 event Approval(address indexed owner, address indexed spender, uint256 value);
16}
すべて表示
コピー

ここでは、それぞれの関数の役割について説明しています。 その後、ERC-20トークンの簡単な実装をご紹介します。

Getters

1function totalSupply() external view returns (uint256);
コピー

存在するトークンの総量を返します。 この関数はgetter関数であり、コントラクトの状態を変更することはありません。 Solidityには浮動小数点が存在しないことに注意してください。 したがって、ほとんどのトークンは18桁で表記され、1トークンに対して10000000000000000となるように総供給量などの結果を返します。 ただし、すべてのトークンが18桁ではないため、トークンを扱うときには注意が必要です。

1function balanceOf(address account) external view returns (uint256);
コピー

アドレス(account)が所有するトークンの量を返します。 この関数はgetter関数であり、コントラクトの状態を変更することはありません。

1function allowance(address owner, address spender) external view returns (uint256);
コピー

ERC-20は、あるアドレスが他のアドレスに権限を与え、そのアドレスからトークンを取り戻すことができます。 この関数は、spenderownerのために使用可能なトークンの残数を返します。 この関数はgetter関数であり、コントラクトの状態を変更することはありません。したがってデフォルトで0が返ってきます

関数

1function transfer(address recipient, uint256 amount) external returns (bool);
コピー

関数を呼び出したアドレス(msg.sender)から受け取りアドレスにamountのトークンを送信します。 この関数は、後で定義するTransferイベントを発行します。 トークンの送金が可能な場合、trueを返します。

1function approve(address spender, uint256 amount) external returns (bool);
コピー

関数を呼び出したアドレス(msg.sender)の残高からspenderが送金できるallowanceを設定します。 この関数は、承認イベントを発行します。 この関数は、承認が成功したか否かを返します。

1function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
コピー

amountのトークンをsenderからrecipientへ承認メカニズムを使って送金します。 関数を呼び出したアドレスから手数料が差し引かれます。 この関数は、Transferイベントを発行します。

イベント

1event Transfer(address indexed from, address indexed to, uint256 value);
コピー

トークンの量(値)がfromアドレスからtoアドレスに送信されると、このイベントが発行されます。

新しいトークンをミントする場合、送金イベントは通常from0x00...0000アドレスであるのに対し、トークンをバーンする場合はto0x00...0000となります。

1event Approval(address indexed owner, address indexed spender, uint256 value);
コピー

このイベントは、トークンの量(value)がownerによって、spenderに使用することが承認されたときに発行されるものです。

ERC-20トークンの基本的な実装

ERC-20トークンのベースとなるシンプルなコードを以下にご紹介します。

1pragma solidity ^0.8.0;
2
3interface IERC20 {
4
5 function totalSupply() external view returns (uint256);
6 function balanceOf(address account) external view returns (uint256);
7 function allowance(address owner, address spender) external view returns (uint256);
8
9 function transfer(address recipient, uint256 amount) external returns (bool);
10 function approve(address spender, uint256 amount) external returns (bool);
11 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
12
13
14 event Transfer(address indexed from, address indexed to, uint256 value);
15 event Approval(address indexed owner, address indexed spender, uint256 value);
16}
17
18
19contract ERC20Basic is IERC20 {
20
21 string public constant name = "ERC20Basic";
22 string public constant symbol = "ERC";
23 uint8 public constant decimals = 18;
24
25
26 mapping(address => uint256) balances;
27
28 mapping(address => mapping (address => uint256)) allowed;
29
30 uint256 totalSupply_ = 10 ether;
31
32
33 constructor() {
34 balances[msg.sender] = totalSupply_;
35 }
36
37 function totalSupply() public override view returns (uint256) {
38 return totalSupply_;
39 }
40
41 function balanceOf(address tokenOwner) public override view returns (uint256) {
42 return balances[tokenOwner];
43 }
44
45 function transfer(address receiver, uint256 numTokens) public override returns (bool) {
46 require(numTokens <= balances[msg.sender]);
47 balances[msg.sender] = balances[msg.sender]-numTokens;
48 balances[receiver] = balances[receiver]+numTokens;
49 emit Transfer(msg.sender, receiver, numTokens);
50 return true;
51 }
52
53 function approve(address delegate, uint256 numTokens) public override returns (bool) {
54 allowed[msg.sender][delegate] = numTokens;
55 emit Approval(msg.sender, delegate, numTokens);
56 return true;
57 }
58
59 function allowance(address owner, address delegate) public override view returns (uint) {
60 return allowed[owner][delegate];
61 }
62
63 function transferFrom(address owner, address buyer, uint256 numTokens) public override returns (bool) {
64 require(numTokens <= balances[owner]);
65 require(numTokens <= allowed[owner][msg.sender]);
66
67 balances[owner] = balances[owner]-numTokens;
68 allowed[owner][msg.sender] = allowed[owner][msg.sender]-numTokens;
69 balances[buyer] = balances[buyer]+numTokens;
70 emit Transfer(owner, buyer, numTokens);
71 return true;
72 }
73}
すべて表示
コピー

ERC-20トークン規格のもう1つのすばらしい実装として、OpenZeppelin ERC-20実装(opens in a new tab)があります。

最終編集者: @hesoponyo(opens in a new tab), 2024年4月1日

このチュートリアルは役に立ちましたか?