Zrozumienie inteligentnego kontraktu tokenu ERC-20
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.
1pragma solidity ^0.6.0;23interface IERC20 {45 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);89 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);121314 event Transfer(address indexed from, address indexed to, uint256 value);15 event Approval(address indexed owner, address indexed spender, uint256 value);16}Pokaż wszystkoOto szczegółowe wyjaśnienie przeznaczenia każdej funkcji. Następnie przedstawimy prostą implementację tokenu ERC-20.
Getters
1function totalSupply() external view returns (uint256);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);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);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);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);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);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);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);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;23interface IERC20 {45 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);89 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);121314 event Transfer(address indexed from, address indexed to, uint256 value);15 event Approval(address indexed owner, address indexed spender, uint256 value);16}171819contract ERC20Basic is IERC20 {2021 string public constant name = "ERC20Basic";22 string public constant symbol = "ERC";23 uint8 public constant decimals = 18;242526 event Approval(address indexed tokenOwner, address indexed spender, uint tokens);27 event Transfer(address indexed from, address indexed to, uint tokens);282930 mapping(address => uint256) balances;3132 mapping(address => mapping (address => uint256)) allowed;3334 uint256 totalSupply_;3536 using SafeMath for uint256;373839 constructor(uint256 total) public {40 totalSupply_ = total;41 balances[msg.sender] = totalSupply_;42 }4344 function totalSupply() public override view returns (uint256) {45 return totalSupply_;46 }4748 function balanceOf(address tokenOwner) public override view returns (uint256) {49 return balances[tokenOwner];50 }5152 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 }5960 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 }6566 function allowance(address owner, address delegate) public override view returns (uint) {67 return allowed[owner][delegate];68 }6970 function transferFrom(address owner, address buyer, uint256 numTokens) public override returns (bool) {71 require(numTokens <= balances[owner]);72 require(numTokens <= allowed[owner][msg.sender]);7374 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}8182library SafeMath {83 function sub(uint256 a, uint256 b) internal pure returns (uint256) {84 assert(b <= a);85 return a - b;86 }8788 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ż wszystkoTa 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.
Inną doskonałą implementacją standardu tokena ERC-20 jest implementacja OpenZeppelin ERC-20.