更新於 2024/05/26閱讀時間約 10 分鐘

KryptoCamp ERC20教學

    以前覺得程式隔行如隔山, 一直都鴨子聽雷進入自我懷疑回圈, 特別感謝Paul老師, 願意花大量時間鉅細靡遺的介紹, 像解釋文言文一般, 悉心的一字一句清晰的解釋成白話文給我們大家, 終於找到了火山登山口的感覺, 繼續加油 🌳

    1. mapping(address account => uint256) private _balances;

    mapping -> 一個table, 左邊欄位(address)對應到右邊欄位(uint256) = 哪個地址擁有多少錢, 表示含金度

    2. mapping(address account => mapping(address spender => uint256)) private _allowances;

    allowance 紀錄: 擁有者(owner) 授權, 設定讓某個人(spender)動用多少自己的資產

    allowance 指的是一種功能,用於實現代幣擁有者(owner)授權另一個帳戶(spender)代表自己進行轉移一定數量的代幣。具體來說,ERC-20 標準中的 allowance 機制通常用於實現代幣轉移的授權管理,以及允許合約代表用戶進行轉移 - ChatGPT

    3. uint256 private _totalSupply;

    這個幣總量發了多少?

    4. string private _name;

    這個幣的名稱

    5. string private _symbol;

    這個幣的縮寫

    6. constructor(string memory name_; string memory symbol) { _name = name_; _symbol = symbol_; }

    在合約被創建時, 就要表示代幣的名稱簡稱是什麼?

    constructor 是一種特殊的函數,用於合約的初始化。當一個合約被創建時(即合約部署到區塊鏈上時),constructor 函數會被自動執行一次來初始化合約的狀態。 -ChatGPT

    7. function name() public view virtual returns (string memory) { return _name;}

    功能是取得合約的名稱

    8. function symbol() public view virtual returns (string memory) { return _symbol;}

    功能是取得合約的簡稱

    9. function decimals() public view virtual returns (uint8) { return 18;}

    功能直接把10^18固定住了, 是預設值, 但因為這是virtual, 所以繼承合約後可以覆寫override

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

    取得目前代幣總共發了多少顆?

    11. function balanceOf(address account) public view virtual returns (uint256) { return _balances(account);

    呼應前面的mapping, 取得擁有者有多少幣

    12. function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; }

    帶入你要傳送對象的地址(address to), 以及你要傳送給他的幣量(uint256 value)

    13. function allowance(address owner, address spender) public view virtual returns (uint256) { return _allowance[owner][spender];

    • 可以查詢某一個user, 授權給另一個address多少的幣
    • 在某一個function後面看到view或是pure, 就是查資料, 不會扣到gas fee,
    • 如果沒有看到 view 或是 pure, 他就認為你要改變合約狀態, 就要付gas fee

    14. function approve (address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); returns true;}

    告訴他你要授權多少幣量給哪個地址, 會寫進allowance的mapping裡

    15. function transferfrom address from, address to, uint256 value) public view returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value; _transfer(from, to, value); return true; }

    從user轉移到sender多少量, 必須先有user授權可以動用這筆資產 (這段有點聽不懂, 之後再回過頭來聽)

    16. function _mint(address account, uint256 value) internal { if(account == address(0)) { revert ERC20 InvalidReceiver(address(0), account, value);}

    提供一個internal的function, 我的合約繼承他之後, 可以一開始都發完, 不用讓用戶來mint

    老師講義

    1. 狀態變數

    • _balances: 持幣紀錄。(address => uint256)
    • _allowances: 授權關係。 (address => (address => uint256))
    • _totalSupply:代幣供給量。
    • _name: 代幣名稱。
    • _symbol: 代幣簡稱。

    2. Function

    2.1 Get: (查資料, 不會耗費gas)

    • name():取得代幣名稱。

    symbol():取得代幣簡稱。

    decimals():取得精度。

    totalSupply():取得總發行量。

    balanceOf(address account):取得「某地址」的「持幣量」。

    2.2 Write: (會改變合約狀態)

    • transfer(address to, uint256 value):轉移代幣。
    • approve(address spender, uint256 value):授權「某地址」操作「某數量」代幣。
    • transferFrom(address from, address to, uint256 value):轉移代幣,通常「被授權者」會呼叫這個。

    2.3 internal:

    • _mint(address account, uint256 value):鑄造代幣。
    • _burn(address account, uint256 value):燒掉代幣。

    Demo Code (發幣只需要27行)

    • 釣魚網站陷阱: 授權
    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.8.20;

    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

    // 幣的名稱, 以及繼承ERC20合約
    contract ERC20Example is ERC20 {

    // 定義最大供給量, 規定這個幣最多發多少
    uint256 public maxSupply;

    //建構子初始化ERC20必要參數(name與symbol),並多加設定題目要求的maxSupply
    constructor(
    string memory _name,
    string memory _symbol,
    uint256 _maxSupply
    ) ERC20(_name, _symbol){
    //執行時填入10000000000(100億) * 1000000000000000000(單位)
    maxSupply = _maxSupply;
    }
    // 為了讓用戶自己鑄造
    // 用戶輸入uint256 amount的數量
    // 要自己實作mint function,主要用來demo確認用
    function mint (uint256 amount) external {
    //判斷這筆交易若完成,是否會超出最大供給量,如果會就回傳錯誤字串"over max supply."
    require(amount + totalSupply() <= maxSupply, "over max supply.");
    _mint(msg.sender, amount); // 如果上一行成立, 就會呼叫這行執行, 右邊的數量, 轉給呼叫者
    }
    }

    [Reference]

    1. Solidity 實戰系列工作坊第 3 場精彩重播: ERC20 同質化代幣與 ERC721 NFT 非同質化代幣
    2. Week3- Token (ERC20) & NFT (ERC721), 講師 Paul Wu, 2024/5/12
    分享至
    成為作者繼續創作的動力吧!
    © 2024 vocus All rights reserved.