·回傳代幣的發行總量
·使用狀態變數uint256_totalSupply來儲存
·給定一個賬戶(address),回傳該賬戶擁有的代幣餘額(uint256)
·使用mapping來儲存:
·mapping(address => uint256) _balance;
·呼叫者「msg.sender」,轉移「amount」數量的代幣給特定賬戶「to」
·成功時回傳true,反之,回傳false
·有些檢查需要做:
·amount是否超過餘額
·是否轉移給address 0x0代表銷燬的意思
event Transfer(
address indexed from,
address indexed to,
uint256 value,
);
·當發生代幣轉移時,必須觸發此事件,即使轉移的數量為「0」也是
·給定兩個賬戶(address),回傳「owner」授權給「spender」的額度(uint256)
·使用mapping來儲存:
·mapping(address =>
·mapping(address => uint256) _allowance;
注:mapping查詢節省燃料
·呼叫者「msg.sender」,授權「amount」數量的代幣額度給第三方賬戶「spender」
·成功時回傳true,反之,回傳false
event Approval(
address indexed owner,
address indexed spender,
uint256 value,
);
·當授權額度時,必須觸發此事件,即使數量為「0」也要觸發
·呼叫者(msg.sender)從代幣持有者(from)轉賬給接收者(to)「amount」數量的代幣
·其中:
·需檢查呼叫者是否擁有足夠的額度可用
·轉賬時要檢查持有者是否足夠的餘額
·轉賬時需要同時減少額度
4.補充概念:
interface IERC20Metadata{
function name() public view returns(string memory);
function symbol() public view returns(string memory);
function decimals() public view returns(uint8);
}
·回傳一個字元,代表這個代幣的名稱
·儲存是以string來儲存
·通常在constructor的時候就給定
·回傳一個字串,代表這個代幣的簡稱
·Ethereum(name)→ETH(symbol)
·Apple(name)→AAPL(symbol)
·儲存時以string來儲存
·通常在constructor的時候就給定
·回傳一個uint8,代表這個代幣的小數點位置
·這個函數只用來顯示用
·decimals=3,則balance=1234,在顯示為1.234
·基本上代幣都會把decimals設定為18
·這是因為最開始就是設計的18,後來因為人類天性,能抄就抄
·1ether=1018wei
·1token=1018uint => decimals=18
interface IERC20{
function mint(address account,uin256 amount);
function burn(address account,uint256 amount);
}
·鑄造,即「無中生有」
·只有合約擁有者或者特殊許可權的人才能呼叫
·他同時也是一種轉賬,由address 0x0轉到目標賬號(account)
·由於是轉賬,因此也要觸發「Transfer」事件
·銷燬,即「迴歸虛無」
·可以根據使用情況決定誰可以呼叫
·若只有合約擁有者可以呼叫,則通常會有account引數,用來銷燬特定人的代幣
·若任何人都可以呼叫,則不會有account引數,用來銷燬特定人的代幣
·若任何人都可以呼叫,則不會有account引數,主要目的是請求呼叫者(msg.sender)銷燬自己的代幣同時也是一種轉賬,由account/msg.sender轉到address 0x0
·由於是轉賬,因此也要觸發「Transfer」事件
//SPDX-License-Identifier:MIT
pragma solidity ^0.8.17;
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 balance0f(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, uint amount) external returns (bool);
function trnasferFrom(address from, address to, uint256 amount) external returns (bool);
}
contract ERC20 is IERC20 {
uint _totalSupply;//定義一個數
mapping(address => uint256) _balance;//定義了一個賬號
mapping(address => mapping(address => uint256)) _allowance;
//查詢授權額度
function allowance(address owner, address spender) public view returns (uint256) {
return _allowance[owner][spender];//返回自己和第三方
}
function _approve(address owner, address spender, uint256 amount) internal {
_allowance[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
//授權
function approve(address spender, uint256 amount) public returns (bool) {
_approve(msg.sender, spender, amount);
return true;
}
//發行代幣,啟動最初代幣
constructor () {
_balance[msg.sender] = 10000;
_totalSupply = 10000;
}
function totalSupply() public view returns (uint256) {
//回傳總髮行量
return _totalSupply;
}
function balance0f(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");//不準轉賬到地址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 trnasferFrom(address from, address to, uint256 amount) external 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;
}
}