305. Metadata x Mint x Burn - ERC20 (ep.21)

閱讀時間約 19 分鐘

1. 代幣的名稱 function name() public view returns(string memory)

  1. 回傳一個字串, 代表這個代幣的名稱
  2. 儲存時以string來保存
  3. 通常在constructor的時候就給定

2. 代幣的簡稱/縮寫/象徵 function symbol() public view returns (string memory);

  1. 回傳一個字串, 代表這個代幣的簡稱
  • Ethereum(name) -> ETH(symbol)
  • Apple(name) -> AAPL(symbol)
  1. 儲存時以string來保存
  2. 通常在constructor的時候就給定

3. 代幣的小數點位置 function decimals() public view returns(uint8);

  1. 回傳一個uint8, 代表這個代幣的小數點位置
  2. 這個函式只用來顯示用
  • decimals = 3, 則balance=1234, 在顯示上應為1.234
  1. 基本上代幣都會把decimals設定成18
  • 人類的天性, 能抄就抄
  • 1 ether = 10^18 wei
  • 1 token = 10 ^18 uint => decimals = 18
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);

function totalSupply() external view returns (uint256);

function balanceOf(address account) external view returns(uint256);
function allowance(address owner, address spender) external view returns (uint256);

function approve(address spender, uint256 amount) external returns (bool);
function transfer(address to, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

contract ERC20 is IERC20 {
uint256 _totalSupply;
mapping(address => uint256) _balance;
mapping(address => mapping(address => uint256)) _allowance;
string _name;
string _symbol;

constructor(string memory name_, string memory symbol_){
_name = name_;
_symbol = symbol_;
_balance[msg.sender] = 10000;
_totalSupply = 10000;
}
function name() public view returns (string memory){
return _name;
}
function symbol() public view returns (string memory){
return _symbol;
}
function decimals() public pure returns (uint8){
return 18;
}


function totalSupply() public view returns (uint256){
return _totalSupply;
}

function balanceOf(address account) public view returns (uint256) {
return _balance[account];
}

function _transfer(address from, address to, uint256 amount) internal {
uint256 myBalance = _balance[from];
require(myBalance >= amount, "No money to transfer");
require(to != address(0), "Transfer to address 0");

_balance[from] = myBalance - amount;
_balance[to] = _balance[to] + amount;
emit Transfer(from, to, amount);
}
function transfer(address to, uint256 amount) public returns (bool){
_transfer(msg.sender, to, amount);
return true;
}

function allowance(address owner, address spender) public view returns (uint256){
return _allowance[owner][spender];
//_allowance => (mapping(address => mapping(address => uint256)))
//_allowance[owner] => (mapping(address => uint256))
//(_allowance[owner])[spender] => uint256
}

function _approve(address owner, address spender, uint256 amount) internal {
_allowance[owner][spender] = amount;
emit Approval(msg.sender, spender, amount);
}
function approve(address spender, uint256 amount) public returns (bool){
_approve(msg.sender, spender, amount);
return true;
}

function transferFrom(address from, address to, uint256 amount) public returns (bool){
uint256 myAllowance = _allowance[from][msg.sender];
require(myAllowance >= amount, "ERROR: myAllowance < amount");
_approve(from, msg.sender, myAllowance - amount);
_transfer(from, to, amount);
return true;
}
}


4. 鑄造新代幣function mint(address account, uint256 amount)

  1. 鑄造, 即無中生有
  2. 只有合約擁有者或者特殊權限的人才能呼叫
  3. 他同時也是一種轉帳, 由address 0x0轉到目標帳號account
  4. 由於是轉帳, 因此也要觸發Transfer事件

5. 銷毀代幣 function burn(address account, uint256 amount)

  1. 銷毀, 回歸虛無
  2. 可以根據使用者情境決定誰可以呼叫
  3. 若只有合約擁有者可以呼叫, 則通常會有account參數, 用來銷毀特定人的代幣
  4. 若任何人可以呼叫, 則不會有account參數, 主要目的是讓呼叫者msg.sender銷毀自己的代幣
  5. 同時也是一種轉帳, 由account/msg.sender轉到address 0x0
  6. 由於是轉帳, 因此也要觸發Transfer事件


// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);

function totalSupply() external view returns (uint256);

function balanceOf(address account) external view returns(uint256);
function allowance(address owner, address spender) external view returns (uint256);

function approve(address spender, uint256 amount) external returns (bool);
function transfer(address to, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

contract ERC20 is IERC20 {
uint256 _totalSupply;
mapping(address => uint256) _balance;
mapping(address => mapping(address => uint256)) _allowance;
string _name;
string _symbol;
address _owner;

modifier onlyOwner(){
require(_owner == msg.sender, "Error: only owner can access this function");
_;
}

constructor(string memory name_, string memory symbol_){
_name = name_;
_symbol = symbol_;
_owner = msg.sender;

_balance[msg.sender] = 10000;
_totalSupply = 10000;
}

function mint(address account, uint256 amount) public onlyOwner {
require(account != address(0), "ERROR: mint to address 0");
_totalSupply += amount;
_balance[account] += amount;
emit Transfer(address(0), account, amount);
}

function burn(address account, uint256 amount) public onlyOwner {
require(account != address(0), "ERROR: burn from address0");
_totalSupply -= amount;
uint256 accountBalance = _balance[account];
require(accountBalance >= amount, "Error: no more token to burn");
_balance[account] = accountBalance - amount;
emit Transfer(account, address(0), amount);
}

function name() public view returns (string memory){
return _name;
}
function symbol() public view returns (string memory){
return _symbol;
}
function decimals() public pure returns (uint8){
return 18;
}

function totalSupply() public view returns (uint256){
return _totalSupply;
}

function balanceOf(address account) public view returns (uint256) {
return _balance[account];
}

function _transfer(address from, address to, uint256 amount) internal {
uint256 myBalance = _balance[from];
require(myBalance >= amount, "No money to transfer");
require(to != address(0), "Transfer to address 0");

_balance[from] = myBalance - amount;
_balance[to] = _balance[to] + amount;
emit Transfer(from, to, amount);
}
function transfer(address to, uint256 amount) public returns (bool){
_transfer(msg.sender, to, amount);
return true;
}

function allowance(address owner, address spender) public view returns (uint256){
return _allowance[owner][spender];
//_allowance => (mapping(address => mapping(address => uint256)))
//_allowance[owner] => (mapping(address => uint256))
//(_allowance[owner])[spender] => uint256
}

function _approve(address owner, address spender, uint256 amount) internal {
_allowance[owner][spender] = amount;
emit Approval(msg.sender, spender, amount);
}
function approve(address spender, uint256 amount) public returns (bool){
_approve(msg.sender, spender, amount);
return true;
}

function transferFrom(address from, address to, uint256 amount) public returns (bool){
uint256 myAllowance = _allowance[from][msg.sender];
require(myAllowance >= amount, "ERROR: myAllowance < amount");
_approve(from, msg.sender, myAllowance - amount);
_transfer(from, to, amount);
return true;
}
}



尋大神腳印, 亦步亦趨。
留言0
查看全部
發表第一個留言支持創作者!
從 Google News 追蹤更多 vocus 的最新精選內容