ERC20

Aus Bitcoin Wiki
Wechseln zu: Navigation, Suche
ERC20 token

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.

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]

Siehe auch[Bearbeiten]

Ressourcen[Bearbeiten]