###### tags: `Block Chain`
# Solidity ERC20 Practice
## [ERC20](https://eips.ethereum.org/erc)
### Must
```solidity=
// 返回代幣的總供應量
function totalSupply() public view returns (uint256)
// 返回該帳戶此代幣的餘額
function balanceOf(address _owner) public view returns (uint256 balance)
// 轉移代幣至_to地址,觸發Transfer event & throw error
function transfer(address _to, uint256 _value) public returns (bool success)
// 從_from轉移代幣至_to地址,觸發Transfer event & throw error
function transferForm(address _from,address _to, uint256 _value) public returns (bool success)
// 批准提領數,設置_spender可提取的代幣數量
function approve(address _spender, uint256 _value) public returns (bool success)
// 返回_owner批准_spender的提取數量
function allowance(address _owner, address _spender) public view returns(uint256 remaining)
```
### Option
```solidity=
// 返回代幣名稱
function name() public view returns (string)
// 返回代幣的符號 ex: etheteum->eth
function symbol() public view returns (string)
// 返回代幣使用的小數點位數
function decimals() public view returns (uint8)
```
### Event
```solidity=
// 轉移事件,代幣轉移時都必須觸發,包含0值轉移,創建代幣時也須觸發事件,_from設置為0x000
event function Transfer(address indexed _from, address indexed _to, uint256 _value)
// 成功事件,任何成功的調用都要觸發
event function Approval(address indexed _onwer, address indexed _spender,uint256 _value)
```
```solidity=
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.14;
contract Token {
// Token 名字 (幣的名字)11
string public name = "Anonymous Mask Token";
// 暱稱
string public symbol = "AMT";
// 使用的小數點位
uint8 decimals = 5;
// Event
// 轉移事件,代幣轉移時都必須觸發,包含0值轉移,創建代幣時也須觸發事件,_from設置為0x000
event Transfer(address indexed _from, address indexed _to, uint256 _value);
// 成功事件,任何成功的調用都要觸發
event Approval(address indexed _onwer, address indexed _spender,uint256 _value);
//返回該帳戶此代幣的餘額,帳號餘額map like map[address]uin256 in golang
mapping (address => uint256) public balanceOf;
// A地址允許B地址提取的代幣數量
// 返回_owner批准_spender的提取數量
mapping (address => mapping(address => uint256)) public allowance;
// 代幣總數,返回代幣的總供應量,此種寫法包含宣告變數及產生簡單的get func
uint256 public totalSupply;
/*
效用同此
uint256 totalSupply;
function totalSupply() public view returns (uint256){
return totalSupply;
}
*/
// 轉移代幣至_to地址,觸發Transfer event & throw error
function transfer(address _to, uint256 _value) public returns (bool success){
return transferFrom(msg.sender,_to,_value);
}
// 從_from轉移代幣至_to地址,觸發Transfer event & throw error
function transferFrom(address _from,address _to, uint256 _value) public returns (bool success){
// 檢查from有無足夠代幣,沒有的話throw error
require(balanceOf[_from] >= _value,"not enough token!");
// 確認當前呼叫合約者是否為from
if (msg.sender != _from) {
// 此情況為第三者要轉移from地址的代幣到to
// 確認from授予msg.sender的提領代幣數量有無大於此次轉移顆數
require(allowance[_from][msg.sender] >= _value);
}
balanceOf[_from] -= _value;
balanceOf[_to] += _value;
emit Transfer(_from,_to,_value);
return true;
}
// 批准提領數,設置_spender可提取的代幣數量
function approve(address _spender, uint256 _value) public returns (bool success) {
// @ msg.sender => 合約呼叫者
// @ _spender => 提領者
// msg.sender 允許 _spender 提領 value 顆 AMT
allowance[msg.sender][_spender] = _value;
// 觸發事件
emit Approval(msg.sender,_spender,_value);
return true;
}
// 造幣
function mint(address _to,uint value) public {
balanceOf[msg.sender] = value;
totalSupply += value;
emit Transfer(address(0),_to,value);
}
}
```
{%hackmd theme-dark %}