solidity簡單的ERC20代幣實現

行者akai發表於2023-03-20
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "hardhat/console.sol";
//ERC20 同質化代幣,每個代幣的本質或性質都是相同
//ETH 是原生代幣,它不是ERC20代幣,它們兩是不能協同工作。所以需要將ETH轉換成WETH(ERC20)
//ERC20 必須實現相應的介面(規範),參見 https://eips.ethereum.org/EIPS/eip-20

//totalSupply 代幣發行總供應量,它即可以固定不變,又可以根據業務需求而改變
//totalSupply 代幣發行總供應量是否可變,取決於合約是否存在mint或burn函式/方法
//balanceOf(owner) 獲取某個賬戶的餘額,所有賬戶餘額的總和必須等於totalSupply

//approve 授權一定數量的代幣給第三方/交易所/代理人。注意,是授權而不是傳送代幣給第三方
//approve 必須包含3個引數,Owner:誰授權代幣給第三方,Spender:第三方/交易所/代理人,Amount:授權數額
//allowance 儲存approve方法的3項資料

//transfer 轉賬,接收2個引數,from:msg.sender; to:轉入; amount:金額
//transferFrom 轉賬,接收3個引數,from:轉出; to:轉入; amount:金額
//transfer與transferFrom使用場景不一樣,transfer用在本合約轉賬,transferFrom用在第三方/去中心交易所/代理人
 
 //event Approval與Transfer 將交易等日誌資訊寫入區塊鏈,非常重要

//V1
interface IERC20V1 {
    event Approval(address indexed owner ,address indexed spender ,uint256 amount);
    event Transfer(address indexed from ,address indexed to ,uint256 amount);

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    //對應狀態變數totalSupply 代幣發行總供應量
    function totalSupply() external view returns(uint256);
    //balanceOf(owner) 獲取某個賬戶的餘額
    function balanceOf(address owner) external view returns(uint256);
    //approve 授權一定數量的代幣給第三方/交易所/代理人
    function approve(address spender, uint amount) external returns (bool);
    //allowance 儲存approve方法的3項資料
    function allowance(address owner, address spender) external view returns (uint256);
   
    function transfer(address to, uint amount) external returns(bool);

    function transferFrom(address from, address to,uint amount) external returns(bool);

}

contract ERC20V1 is IERC20V1 {

    string public constant name = "XingZheChain";
    string public constant symbol = "XZC";
    uint8 public constant decimals = 18;
    //totalSupply 代幣發行總供應量
    uint256 public totalSupply;
    mapping(address => uint256) public balanceOf;
    address public _owner;

    mapping(address => mapping(address => uint256)) public allowance;


    constructor(uint256 _initTotalSupply){
        _owner = msg.sender;
        //預挖給建立者代幣
        mint(msg.sender,_initTotalSupply);
    }

    modifier onlyOwner() {
        require(_owner == msg.sender,"Ownable:caller is not the owner");
        _;
    }
   
    //挖掘出新代幣以及挖給那個地址
    //合約建立者呼叫
    function mint(address to ,uint256 amount) public onlyOwner {
        totalSupply = totalSupply += amount;
        balanceOf[to] = balanceOf[to] += amount;
    }
    //燃燒自己的代幣
    function burn(uint256 amount) public {
        address from = msg.sender;
        balanceOf[from] = balanceOf[from] -= amount;
        totalSupply = totalSupply -= amount;
    }

    function _approve(address owner, address spender, uint amount) private {
        allowance[owner][spender] = amount;
        emit Approval(owner ,spender ,amount);
    }

    function approve(address spender, uint amount) external returns(bool) {
        _approve(msg.sender, spender, amount);
        return true;
    }

    function _transfer(address from, address to,uint amount) private {
        balanceOf[from] = balanceOf[from] -= amount;
        balanceOf[to] = balanceOf[to] += amount;
        emit Transfer(from ,to ,amount);
    }

    function transfer(address to, uint amount) external returns(bool){
        _transfer(msg.sender, to, amount);
        return true;
    }

    function transferFrom(address from, address to,uint amount) external returns(bool){
        uint256 currentAllowance = allowance[from][msg.sender];
        require(currentAllowance >= amount,"ERC20: insufficient allowance");
        allowance[from][msg.sender] = currentAllowance -= amount;
        //console.log("msg.sender ->",address(msg.sender));
        _transfer(from ,to ,amount);
        return true;
    }
}

//建議去中心化交易所
contract Dex {
    address public erc20V1;

    constructor(address _erc20V1){
        erc20V1 = _erc20V1;
    }

    function transferFromTo(address to ,uint amount) external {
        IERC20V1(erc20V1).transferFrom(msg.sender ,to ,amount);
    }

    function transferTo(address to,uint amount) external {
        IERC20V1(erc20V1).transfer(to,amount);  
    }
}


相關文章