ERC20
ERC20 ist der Ethereum-Token-Standard, der für Ethereum-Smart-Verträge verwendet wird. Der 2015 entwickelte ERC-20 definiert eine gemeinsame Liste von Regeln, die ein Ethereum-Token implementieren muss. Entwicklern die Möglichkeit zu geben, wie neue Tokens innerhalb des Ethereum-Ökosystems funktionieren. Dieses Token-Protokoll wurde bei Crowdfunding-Unternehmen via ICO beliebt.
Das Global Messaging Token von Mercury Protocol ist ein Beispiel für eine Anwendung, die auf ERC20-Tokens basiert.
Der Token-Standard ERC20 beschreibt die Funktionen und Ereignisse, die ein Ethereum-Token-Vertrag implementieren muss.
Inhaltsverzeichnis
Die ERC20 Token Standardschnittstelle[Bearbeiten]
Es folgt ein Schnittstellenvertrag, der die erforderlichen Funktionen und Ereignisse zur Erfüllung des ERC20-Standards festlegt:
1 // ----------------------------------------------------------------------------
2 // ERC Token Standard #20 Interface
3 // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
4 // ----------------------------------------------------------------------------
5 contract ERC20Interface {
6 function totalSupply() public constant returns (uint);
7 function balanceOf(address tokenOwner) public constant returns (uint balance);
8 function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
9 function transfer(address to, uint tokens) public returns (bool success);
10 function approve(address spender, uint tokens) public returns (bool success);
11 function transferFrom(address from, address to, uint tokens) public returns (bool success);
12
13 event Transfer(address indexed from, address indexed to, uint tokens);
14 event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
15 }
Die meisten wichtigen Token der Ethereum-Blockchain sind ERC-20-konform. Das GNT Golem Network Token ist nur teilweise ERC20 Blockchain-konform, da es die Funktionen approve (…)
, allowance (..)
und transferFrom (...)
sowie das Approval (...)
Event nicht implementiert.
Einige der Token enthalten weitere Informationen, die den Token-Vertrag beschreiben:
1 string public constant name = "Token Name";
2 string public constant symbol = "SYM";
3 uint8 public constant decimals = 18; // 18 is the most common number of decimal places
Wie funktioniert der ERC-20-Token-Vertrag?[Bearbeiten]
Es folgt ein Fragment eines Token-Vertrags, um zu demonstrieren, wie ein Token-Vertrag das Token-Guthaben von Ethereum-Konten beibehält:
1 contract TokenContractFragment {
2
3 // Balances for each account
4 mapping(address => uint256) balances;
5
6 // Owner of account approves the transfer of an amount to another account
7 mapping(address => mapping (address => uint256)) allowed;
8
9 // Get the token balance for account `tokenOwner`
10 function balanceOf(address tokenOwner) public constant returns (uint balance) {
11 return balances[tokenOwner];
12 }
13
14 // Transfer the balance from owner's account to another account
15 function transfer(address to, uint tokens) public returns (bool success) {
16 balances[msg.sender] = balances[msg.sender].sub(tokens);
17 balances[to] = balances[to].add(tokens);
18 Transfer(msg.sender, to, tokens);
19 return true;
20 }
21
22 // Send `tokens` amount of tokens from address `from` to address `to`
23 // The transferFrom method is used for a withdraw workflow, allowing contracts to send
24 // tokens on your behalf, for example to "deposit" to a contract address and/or to charge
25 // fees in sub-currencies; the command should fail unless the _from account has
26 // deliberately authorized the sender of the message via some mechanism; we propose
27 // these standardized APIs for approval:
28 function transferFrom(address from, address to, uint tokens) public returns (bool success) {
29 balances[from] = balances[from].sub(tokens);
30 allowed[from][msg.sender] = allowed[from][msg.sender].sub(tokens);
31 balances[to] = balances[to].add(tokens);
32 Transfer(from, to, tokens);
33 return true;
34 }
35
36 // Allow `spender` to withdraw from your account, multiple times, up to the `tokens` amount.
37 // If this function is called again it overwrites the current allowance with _value.
38 function approve(address spender, uint tokens) public returns (bool success) {
39 allowed[msg.sender][spender] = tokens;
40 Approval(msg.sender, spender, tokens);
41 return true;
42 }
43 }
Blockchain Token Balance[Bearbeiten]
Nehmen wir als Beispiel an, dass dieser Token-Vertrag zwei Token-Inhaber hat:
-
0x1111111111111111111111111111111111111111
mit einer Bilanz von 100 Einheiten -
0x2222222222222222222222222222222222222222
mit einer Bilanz von 200 Einheiten
Die ’Balances’
des Token Vertrags enthält die folgenden Informationen:
balances[0x1111111111111111111111111111111111111111] = 100 balances[0x2222222222222222222222222222222222222222] = 200
Der balanceOf (…)
Funktion gibt die folgenden Werte zurück:
tokenContract.balanceOf(0x1111111111111111111111111111111111111111) will return 100 tokenContract.balanceOf(0x2222222222222222222222222222222222222222) will return 200
Transfer Token Balance[Bearbeiten]
Wenn 0x1111111111111111111111111111111111111111
10 Tokens zu 0x2222222222222222222222222222222222222222
übertragen möchte, führt 0x1111111111111111111111111111111111111111
die Funktion aus:
tokenContract.transfer(0x2222222222222222222222222222222222222222, 10)
Die transfer (...) <code/> Funktion des Token-Vertrags ändert die Datenstruktur der Salden, um folgende Informationen zu enthalten:
balances[0x1111111111111111111111111111111111111111] = 90 balances[0x2222222222222222222222222222222222222222] = 210
Die Funktion <code>balanceOf (…) gibt nun die folgenden Werte zurück:
tokenContract.balanceOf(0x1111111111111111111111111111111111111111) will return 90 tokenContract.balanceOf(0x2222222222222222222222222222222222222222) will return 210
Approve And TransferFrom Token Balance[Bearbeiten]
ERC20 Source code Wenn 0x1111111111111111111111111111111111111111<code/> eine Autorisierung von <code>0x2222222222222222222222222222222222222222
für die Übertragung einiger Token an 0x2222222222222222222222222222222222222222
wünscht, führt 0x1111111111111111111111111111111111111111
die Funktion aus:
tokenContract.approve(0x2222222222222222222222222222222222222222, 30)
Die Datenstruktur approve
enthält nun folgende Informationen:
tokenContract.allowed[0x1111111111111111111111111111111111111111][0x2222222222222222222222222222222222222222] = 30
Wenn 0x2222222222222222222222222222222222222222
später einige Tokens von 0x1111111111111111111111111111111111111111
auf sich selbst übertragen möchte, führt 0x2222222222222222222222222222222222222222
die Funktion transferFrom (…)
aus:
tokenContract.transferFrom(0x1111111111111111111111111111111111111111, 0x2222222222222222222222222222222222222222, 20)
Die balances
Datenstruktur wird so geändert, dass sie folgende Informationen enthält:
tokenContract.balances[0x1111111111111111111111111111111111111111] = 70 tokenContract.balances[0x2222222222222222222222222222222222222222] = 230
Und die Datenstruktur approve
enthält jetzt die folgenden Informationen:
tokenContract.allowed[0x1111111111111111111111111111111111111111][0x2222222222222222222222222222222222222222] = 10
0x2222222222222222222222222222222222222222
kann immer noch 10 Tokens von 0x1111111111111111111111111111111111111111
ausgeben.
Die Funktion balanceOf (…)
gibt nun die folgenden Werte zurück:
tokenContract.balanceOf(0x1111111111111111111111111111111111111111) will return 70 tokenContract.balanceOf(0x2222222222222222222222222222222222222222) will return 230
Sample Fixed Supply Token Contract[Bearbeiten]
Es folgt ein Beispiel eines Fixed Supply Token-Vertrags mit einer festen Lieferung von 1.000.000 Einheiten, die ursprünglich dem Eigentümer des Vertrags zugewiesen wurden. Dieser Token hat 18 Dezimalstellen: ERC20 Code:
1 pragma solidity ^0.4.18;
2
3 // ----------------------------------------------------------------------------
4 // 'FIXED' 'Example Fixed Supply Token' token contract
5 //
6 // Symbol : FIXED
7 // Name : Example Fixed Supply Token
8 // Total supply: 1,000,000.000000000000000000
9 // Decimals : 18
10 //
11 // Enjoy.
12 //
13 // (c) BokkyPooBah / Bok Consulting Pty Ltd 2017. The MIT Licence.
14 // ----------------------------------------------------------------------------
15
16
17 // ----------------------------------------------------------------------------
18 // Safe maths
19 // ----------------------------------------------------------------------------
20 library SafeMath {
21 function add(uint a, uint b) internal pure returns (uint c) {
22 c = a + b;
23 require(c >= a);
24 }
25 function sub(uint a, uint b) internal pure returns (uint c) {
26 require(b <= a);
27 c = a - b;
28 }
29 function mul(uint a, uint b) internal pure returns (uint c) {
30 c = a * b;
31 require(a == 0 || c / a == b);
32 }
33 function div(uint a, uint b) internal pure returns (uint c) {
34 require(b > 0);
35 c = a / b;
36 }
37 }
38
39
40 // ----------------------------------------------------------------------------
41 // ERC Token Standard #20 Interface
42 // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
43 // ----------------------------------------------------------------------------
44 contract ERC20Interface {
45 function totalSupply() public constant returns (uint);
46 function balanceOf(address tokenOwner) public constant returns (uint balance);
47 function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
48 function transfer(address to, uint tokens) public returns (bool success);
49 function approve(address spender, uint tokens) public returns (bool success);
50 function transferFrom(address from, address to, uint tokens) public returns (bool success);
51
52 event Transfer(address indexed from, address indexed to, uint tokens);
53 event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
54 }
55
56
57 // ----------------------------------------------------------------------------
58 // Contract function to receive approval and execute function in one call
59 //
60 // Borrowed from MiniMeToken
61 // ----------------------------------------------------------------------------
62 contract ApproveAndCallFallBack {
63 function receiveApproval(address from, uint256 tokens, address token, bytes data) public;
64 }
65
66
67 // ----------------------------------------------------------------------------
68 // Owned contract
69 // ----------------------------------------------------------------------------
70 contract Owned {
71 address public owner;
72 address public newOwner;
73
74 event OwnershipTransferred(address indexed _from, address indexed _to);
75
76 function Owned() public {
77 owner = msg.sender;
78 }
79
80 modifier onlyOwner {
81 require(msg.sender == owner);
82 _;
83 }
84
85 function transferOwnership(address _newOwner) public onlyOwner {
86 newOwner = _newOwner;
87 }
88 function acceptOwnership() public {
89 require(msg.sender == newOwner);
90 OwnershipTransferred(owner, newOwner);
91 owner = newOwner;
92 newOwner = address(0);
93 }
94 }
95
96
97 // ----------------------------------------------------------------------------
98 // ERC20 Token, with the addition of symbol, name and decimals and an
99 // initial fixed supply
100 // ----------------------------------------------------------------------------
101 contract FixedSupplyToken is ERC20Interface, Owned {
102 using SafeMath for uint;
103
104 string public symbol;
105 string public name;
106 uint8 public decimals;
107 uint public _totalSupply;
108
109 mapping(address => uint) balances;
110 mapping(address => mapping(address => uint)) allowed;
111
112
113 // ------------------------------------------------------------------------
114 // Constructor
115 // ------------------------------------------------------------------------
116 function FixedSupplyToken() public {
117 symbol = "FIXED";
118 name = "Example Fixed Supply Token";
119 decimals = 18;
120 _totalSupply = 1000000 * 10**uint(decimals);
121 balances[owner] = _totalSupply;
122 Transfer(address(0), owner, _totalSupply);
123 }
124
125
126 // ------------------------------------------------------------------------
127 // Total supply
128 // ------------------------------------------------------------------------
129 function totalSupply() public constant returns (uint) {
130 return _totalSupply - balances[address(0)];
131 }
132
133
134 // ------------------------------------------------------------------------
135 // Get the token balance for account `tokenOwner`
136 // ------------------------------------------------------------------------
137 function balanceOf(address tokenOwner) public constant returns (uint balance) {
138 return balances[tokenOwner];
139 }
140
141
142 // ------------------------------------------------------------------------
143 // Transfer the balance from token owner's account to `to` account
144 // - Owner's account must have sufficient balance to transfer
145 // - 0 value transfers are allowed
146 // ------------------------------------------------------------------------
147 function transfer(address to, uint tokens) public returns (bool success) {
148 balances[msg.sender] = balances[msg.sender].sub(tokens);
149 balances[to] = balances[to].add(tokens);
150 Transfer(msg.sender, to, tokens);
151 return true;
152 }
153
154
155 // ------------------------------------------------------------------------
156 // Token owner can approve for `spender` to transferFrom(...) `tokens`
157 // from the token owner's account
158 //
159 // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
160 // recommends that there are no checks for the approval double-spend attack
161 // as this should be implemented in user interfaces
162 // ------------------------------------------------------------------------
163 function approve(address spender, uint tokens) public returns (bool success) {
164 allowed[msg.sender][spender] = tokens;
165 Approval(msg.sender, spender, tokens);
166 return true;
167 }
168
169
170 // ------------------------------------------------------------------------
171 // Transfer `tokens` from the `from` account to the `to` account
172 //
173 // The calling account must already have sufficient tokens approve(...)-d
174 // for spending from the `from` account and
175 // - From account must have sufficient balance to transfer
176 // - Spender must have sufficient allowance to transfer
177 // - 0 value transfers are allowed
178 // ------------------------------------------------------------------------
179 function transferFrom(address from, address to, uint tokens) public returns (bool success) {
180 balances[from] = balances[from].sub(tokens);
181 allowed[from][msg.sender] = allowed[from][msg.sender].sub(tokens);
182 balances[to] = balances[to].add(tokens);
183 Transfer(from, to, tokens);
184 return true;
185 }
186
187
188 // ------------------------------------------------------------------------
189 // Returns the amount of tokens approved by the owner that can be
190 // transferred to the spender's account
191 // ------------------------------------------------------------------------
192 function allowance(address tokenOwner, address spender) public constant returns (uint remaining) {
193 return allowed[tokenOwner][spender];
194 }
195
196
197 // ------------------------------------------------------------------------
198 // Token owner can approve for `spender` to transferFrom(...) `tokens`
199 // from the token owner's account. The `spender` contract function
200 // `receiveApproval(...)` is then executed
201 // ------------------------------------------------------------------------
202 function approveAndCall(address spender, uint tokens, bytes data) public returns (bool success) {
203 allowed[msg.sender][spender] = tokens;
204 Approval(msg.sender, spender, tokens);
205 ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);
206 return true;
207 }
208
209
210 // ------------------------------------------------------------------------
211 // Don't accept ETH
212 // ------------------------------------------------------------------------
213 function () public payable {
214 revert();
215 }
216
217
218 // ------------------------------------------------------------------------
219 // Owner can transfer out any accidentally sent ERC20 tokens
220 // ------------------------------------------------------------------------
221 function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) {
222 return ERC20Interface(tokenAddress).transfer(owner, tokens);
223 }
224 }
Weitere Informationen zum ERC20-Netzwerk und Token-Plattform[Bearbeiten]
- Ethereum.org Tokenseite: https://www.ethereum.org/token.
- Etherscan Token Auswahl beliebter Tokens: https://etherscan.io/tokens
- EtherCScan ERC20 Tokensuche: https://etherscan.io/token-search
- Der HumanStandardToken: eine Spezialisierung von ERC20, die einen Namen, Dezimalzahlen, ein Symbol und eine Version als öffentliche Variablen bereitstellt, so dass diese aus dem Vertrag gelesen werden können und nicht konfiguriert werden müssen: https://github.com/ConsenSys/Tokens/blob/master/Token_Contracts/contracts/HumanStandardToken.sol
- Token Factory, eine Anwendung, mit der Sie diese Tokens erstellen können, nur um mit: https://tokenfactory.surge.sh
- ERC 20 Blockchain-Bibliotheken:
- OpenZeppelin: https://github.com/OpenZeppelin/zeppelin-solidity/tree/master/contracts/token
- Minime-Token-Vertrag, der es erlaubt, sich selbst zu klonen, so dass er für Dinge wie das Voting oder sogar das Abspalten eines Tokens für eine separate Anwendung verwendet werden kann: https://github.com/Giveth/minime