ERC20学习

ERC20简介

ERC20是一种代币标准,用于创建可替代的代币。

ERC20是在以太坊网络上实现的代币标准,它为数字资产或代币定义了一套规则和接口。这些符合ERC20标准的代币在性质上是完全相同的。即每一个代币都可以被另一个同类型的代币替代,这种属性确保了代币的互可操作性和统一性,使得它们可以在不同的平台和钱包之间自由转移和交换。

IERC20

IERC20是ERC20代币标准的接口合约,规定了ERC20需要实现的函数和事件。

  • 接口(IERC20):
    • 接口只包含函数和事件的定义,而不包含它们的实现
    • 接口用于描述一个合约应该遵循的规则,而不涉及具体的实现细节
    • 使用接口可以确保合约遵守特定的标准或规范,同时允许开发者自由的实现这些功能。
  • 合约(ERC20):
    • 合约包含函数的实现代码
    • ERC20是一个具体的代币合约标准,它提供了一组规则和指导,告诉开发者如何编写代币合约的代码。
  • 使用IERC20的好处:
    • 灵活性:通过使用接口,开发者可以自由的实现接口中的函数,而不收特定实现的限制,这允许不同的代币项目根据其特定需求进行定制。
    • 可升级性:如果将来ERC20标准需要更新,使用接口的合约更容易的进行升级,因为它们依赖于抽象的接口定义,而不是具体的实现。
    • 兼容性:IERC20接口确保了所有遵循该接口的代币合约都具有相同的功能和行为,这使得它们可以被广泛接受和使用。
    • 安全性:接口可以帮助开发者进行更安全的变成,因为它们只能调用已定义的函数和事件,而不能访问合约的内部状态。

代码

ERC20
solidity 复制代码
pragma solidity ^0.8.4;
//导入IERC20
import "./IERC20.sol";

//继承IERC20合约
contract ERC20 is IERC20 {

    //名为ballanceOf的公共映射,它降低至映射到无符号整数,用于存储每个地址的代币余额
    mapping(address => uint256) public override balanceOf;

    //名为allowance的映射,将地址映射到另一个映射,内部映射降低至映射到无符号整数,该映射用于存储每个地址对其它地址的授权额度
    mapping(address => mapping(address => uint256)) public override allowance;

    uint256 public override totalSupply;   // 代币总供给

    string public name;   // 名称
    string public symbol;  // 代号
    
    uint8 public decimals = 18; // 小数位数

    //初始化代币的名称和符号
    constructor(string memory name_, string memory symbol_){
        name = name_;
        symbol = symbol_;
    }

    //代币转账逻辑
    function transfer(address recipient, uint amount) external override returns (bool) {
        balanceOf[msg.sender] -= amount;
        balanceOf[recipient] += amount;
        emit Transfer(msg.sender, recipient, amount);
        return true;
    }

    //授权逻辑
    function approve(address spender, uint amount) external override returns (bool) {
        allowance[msg.sender][spender] = amount;
        emit Approval(msg.sender, spender, amount);
        return true;
    }

    //授权转账逻辑
    function transferFrom(address sender, address recipient, uint amount) external override returns (bool) {
        allowance[sender][msg.sender] -= amount;
        balanceOf[sender] -= amount;
        balanceOf[recipient] += amount;
        emit Transfer(sender, recipient, amount);
        return true;
    }

    //代币铸造,铸造amount数量代币,将调用者余额增加amount,总供应量totalSupply也增加amount
    //最后,触发一个Transfer事件,表示从地址0(通常代表合约创建者或者系统)向msg.sender转账了amount数量的代币。
    function mint(uint amount) external {
        balanceOf[msg.sender] += amount;
        totalSupply += amount;
        emit Transfer(address(0), msg.sender, amount);
    }

    //代币销毁,销毁amount数量代币,调用者余额减少amount数量,总供应量减少amount
    //最后,触发一个Transfer事件,表示从msg.sender向地址0(通常代表销毁或者回收)转账了amount数量的代币。
    function burn(uint amount) external {
        balanceOf[msg.sender] -= amount;
        totalSupply -= amount;
        emit Transfer(msg.sender, address(0), amount);
    }
}
IERC20
solidity 复制代码
pragma solidity ^0.8.4;

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);

     //从调用该合约的账户转账给to账户amount单位代币,转账成功返回true并释放Transfer事件
    function transfer(address to, uint256 amount) external returns (bool);

     //返回owner账户授权给spender账户的额度,默认为0,当approve或者transferFrom被调用时,allowance会改变
    function allowance(address owner, address spender) external view returns (uint256);

     //调用合约的账户给spender账户授权amount单位代币,如果成功返回true并释放Approval事件
    function approve(address spender, uint256 amount) external returns (bool);
       
     //通过授权机制从from账户向to账户转账amunt数量代币,转账的部分会从调用者的allowance中扣除
     //注意,A授权B可以用自己amount代币,但代币还是在A手中,该函数就相当于B要给C转账,但是这里调用合约的是B,from是A,to是C,注意不要混淆from和调用合约的地址
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

发行代币

  • 编译好合约后,在部署栏中输入构造函数的参数,然后点击transact键进行部署

  • 这样我们就创建了代币,运行mint函数来给自己铸造一些代币,这里我铸造了100个代币,右边有显示详细信息,事件Transfer,铸币地址0x0000000000000000000000000000000000000000,接收地址0x5B38Da6a701c568545dCfcB03FcB875f56beddC4等

  • 然后我们使用balanceOf函数来查询该地址余额

  • 然后我们使用transfer函数给该地址转账,在查询该地址余额,注意哈,这里调用该合约的地址是发起转账的地址,而不是接收转账的地址


  • 然后我们可以用approve函数使A地址给B地址授权一些代币,我们这里的A地址就用我们最开始铸币100个那个地址,B地址就用刚刚转了2个代币的地址,具体用啥看自己,前提是代币要够才能授权

  • 然后我们用allowance查看授权信息

  • 这会B地址已经被授权了50个代币,自己还有俩,总共可以使用52个,现在我们调用transferFrom给C地址转账,C地址自己随便找一个吧,记得调用合约的是B地址,切换地址就在图四中所示地方点击切换,该函数内写的是拥有代币的 A地址以及要接收转账的c地址和转账数量,然后查询C地址余额

  • 销毁代币,调用burn函数

  • 查询总供给,直接点击totalSupply,现在应该是98个,因为总共铸币100个,销毁了俩
相关推荐
kida_yuan11 天前
【以太来袭】4. Geth 原理与解析
区块链
西岸行者12 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意12 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码13 天前
嵌入式学习路线
学习
毛小茛13 天前
计算机系统概论——校验码
学习
babe小鑫13 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms13 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下13 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。13 天前
2026.2.25监控学习
学习
im_AMBER13 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode