Przejdź do głównej zawartości

Zrozumienie inteligentnego kontraktu tokenu ERC-20

inteligentne kontraktytokenysoliditypierwsze krokierc-20
Początkujący
jdourlens
EthereumDev(opens in a new tab)
5 kwietnia 2020
5 minuta czytania minute read
comp-tutorial-metadata-tip-author 0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE

Jeden z najważniejszych standardów inteligentnych kontraktów na Ethereum znany jest jako ERC-20, który stał się standardem technicznym stosowanym w odniesieniu do wszystkich inteligentnych kontraktów w blockchainie Ethereum do implementacji zamiennych tokenów.

ERC-20 określa wspólny wykaz zasad, których powinny przestrzegać wszystkie zamienne tokeny Ethereum. W konsekwencji, ten standard tokenów umożliwia deweloperom wszystkich typów dokładnie przewidzieć, jak nowe tokeny będą funkcjonować w ramach większego systemu Ethereum. Upraszcza to i ułatwia pracę deweloperom, ponieważ mogą oni kontynuować swoją pracę, wiedząc, że żaden nowy projekt nie będzie musiał być ponownie tworzony za każdym razem, gdy pojawi się nowy token, o ile będzie on zgodny z zasadami.

Oto, przedstawione w formie interfejsu, funkcje, które musi zaimplementować ERC-20. Jeśli nie jesteś pewien co do interfejsu: sprawdź nasz artykuł dotyczący Programowanie obiektowe w Solidity(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}
Pokaż wszystko
Kopiuj

Oto szczegółowe wyjaśnienie przeznaczenia każdej funkcji. Następnie przedstawimy prostą implementację tokenu ERC-20.

Getters

1function totalSupply() external view returns (uint256);
Kopiuj

Zwraca ilość istniejących tokenów. Ta funkcja jest to getter i nie modyfikuje stanu umowy. Pamiętaj, że w Solidity nie ma liczb zmiennoprzecinkowych. Dlatego większość tokenów przyjmuje 18 miejsc po przecinku i zwróci całkowitą podaż i inne wyniki w następujący sposób 100000000000000000000 dla 1 tokena. Nie każdy token ma 18 miejsc po przecinku i jest to coś, na co naprawdę musisz uważać, gdy masz do czynienia z tokenami.

1function balanceOf(address account) external view returns (uint256);
Kopiuj

Zwraca ilość tokenów będących w posiadaniu adresu (account). Ta funkcja jest to getter i nie modyfikuje stanu umowy.

1function allowance(address owner, address spender) external view returns (uint256);
Kopiuj

Standard ERC-20 umożliwia adresowi przyznanie zezwolenia na inny adres, aby móc pobrać z niego tokeny. Ten getter zwraca pozostałą liczbę tokenów, które wydawca będzie mógł wydać w imieniu właściciela. Ta funkcja jest to getter i nie modyfikuje stanu umowy. Powinna domyślnie zwracać 0.

Funkcje

1function transfer(address recipient, uint256 amount) external returns (bool);
Kopiuj

Przenosi amount tokenów z adresu wywołującego funkcję (msg.sender) na adres odbiorcy. Ta funkcja emituje zdarzenie Transfer zdefiniowane później. Zwraca prawdę, jeśli transfer był możliwy.

1function approve(address spender, uint256 amount) external returns (bool);
Kopiuj

Ustaw kwotę allowance, jaką spender może przenieść z salda wywołującego funkcję (msg.sender). Ta funkcja emituje zdarzenie zatwierdzenia. Funkcja zwraca, czy dozwolony limit (allowance) został ustawiony.

1function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
Kopiuj

Przesyła amount tokenów od sender dto recipient przy użyciu mechanizmu dozwolonego limitu. Wartość amount jest następnie odliczana od dozwolonego limitu wywołującego funkcję. Ta funkcja emituje zdarzenie Transfer.

Zdarzenia

1event Transfer(address indexed from, address indexed to, uint256 value);
Kopiuj

To zdarzenie jest emitowane, gdy ilość tokenów (wartość) jest wysyłana z adresu od na adres do.

W przypadku wybijania nowych tokenów transfer jest zazwyczaj from adresu 0x00..0000, podczas gdy w przypadku wypalania tokenów transfer jest to 0x00..0000.

1event Approval(address indexed owner, address indexed spender, uint256 value);
Kopiuj

To wydarzenie jest emitowane, gdy ilość tokenów (value) jest zatwierdzona przez owner do użycia przez spender.

Podstawowa implementacja tokenów ERC-20

Oto najprostszy kod, z którego można oprzeć swój token ERC-20:

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}
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 event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
27 event Transfer(address indexed from, address indexed to, uint tokens);
28
29
30 mapping(address => uint256) balances;
31
32 mapping(address => mapping (address => uint256)) allowed;
33
34 uint256 totalSupply_;
35
36 using SafeMath for uint256;
37
38
39 constructor(uint256 total) public {
40 totalSupply_ = total;
41 balances[msg.sender] = totalSupply_;
42 }
43
44 function totalSupply() public override view returns (uint256) {
45 return totalSupply_;
46 }
47
48 function balanceOf(address tokenOwner) public override view returns (uint256) {
49 return balances[tokenOwner];
50 }
51
52 function transfer(address receiver, uint256 numTokens) public override returns (bool) {
53 require(numTokens <= balances[msg.sender]);
54 balances[msg.sender] = balances[msg.sender].sub(numTokens);
55 balances[receiver] = balances[receiver].add(numTokens);
56 emit Transfer(msg.sender, receiver, numTokens);
57 return true;
58 }
59
60 function approve(address delegate, uint256 numTokens) public override returns (bool) {
61 allowed[msg.sender][delegate] = numTokens;
62 emit Approval(msg.sender, delegate, numTokens);
63 return true;
64 }
65
66 function allowance(address owner, address delegate) public override view returns (uint) {
67 return allowed[owner][delegate];
68 }
69
70 function transferFrom(address owner, address buyer, uint256 numTokens) public override returns (bool) {
71 require(numTokens <= balances[owner]);
72 require(numTokens <= allowed[owner][msg.sender]);
73
74 balances[owner] = balances[owner].sub(numTokens);
75 allowed[owner][msg.sender] = allowed[owner][msg.sender].sub(numTokens);
76 balances[buyer] = balances[buyer].add(numTokens);
77 emit Transfer(owner, buyer, numTokens);
78 return true;
79 }
80}
81
82library SafeMath {
83 function sub(uint256 a, uint256 b) internal pure returns (uint256) {
84 assert(b <= a);
85 return a - b;
86 }
87
88 function add(uint256 a, uint256 b) internal pure returns (uint256) {
89 uint256 c = a + b;
90 assert(c >= a);
91 return c;
92 }
93}
Pokaż wszystko
Kopiuj

Ta implementacja wykorzystuje bibliotekę SafeMath. Przeczytaj nasz samouczek, jeśli chcesz się dowiedzieć jak biblioteka pomaga Ci w obsłudze przepełnień i niedoborów w inteligentnych kontraktach(opens in a new tab).

Inną doskonałą implementacją standardu tokena ERC-20 jest implementacja OpenZeppelin ERC-20(opens in a new tab).

Ostatnia edycja: @nhsz(opens in a new tab), 15 sierpnia 2023

Czy ten samouczek był pomocny?