基于 USDT 源码学习 ERC-20 标准

本文详细介绍了 ERC-20 代币协议,作为以太坊上广泛使用的代币标准,其标准化接口提高了代币的兼容性和生态发展。同时,通过逐行分析 USDT 合约代码,揭示了 USDT 如何基于 ERC-20 实现,包括 SafeMath 库、Ownable 合约、以及各种合约组件的用途,如转账和授权功能。文章还讨论了 ERC-20 标准中易混淆的函数,并指出 USDT 在某些方面的不完全符合 ERC-20 规范。
摘要由CSDN通过智能技术生成

8d5da7472103cecbead1099e9f0dad5b.png

目前很多项目都使用 Tokens 来充当项目的代币,其实 Tokens 的本质就是合约里的一个变量,而 Tokens 那么火热的原因之一便是有相应的标准,这个标准便是本文要讨论了 ERC-20 标准。

ERC-20 是以太坊上的一个代币协议,我们可以将其理解成一组接口,基于 ERC-20 协议开发的代币便认为是标准化代币,标准化的好处便是兼容性,大家都按这个标准来玩,生态发展也会很好,比如各种以太坊钱包对 ERC-20 代币的支持,以及各种中心化或去中心化交易所对 Tokens 代币的支持。

USDT 是 ERC-20 代币里使用场景非常广泛的稳定币,所谓稳定币,即 1USDT=1 美元,不会有太大的价格波动,背后是美元背书(那美元背后是啥呢?以前是黄金,现在是石油和军事力量)。

本文,我们会先简单介绍 ERC-20 代币,然后再逐行分析 USDT 的合约代码(USDT 在不同链上都有相应的实现,本文讨论的是以太坊链上的 USDT)。

ERC-20 协议

ERC-20 是 ETH 下的用于实现代币的协议,协议的所有细节可以看:https://eips.ethereum.org/EIPS/eip-20

BSC 上有名为 BEP-20 的协议,它是 Bianca 参考 ERC-20 弄出来的具有相似功能的协议,因为定义的接口函数相同,MetaMask 同样可以连上,导致有些朋友将币转错链,从而导致代币的遗失。

通过 eip-20 可知,ERC-20 的标准接口如下:

contract ERC20 {
    function name() constant returns (string name)
    function symbol() constant returns (string symbol)
    function decimals() constant returns (uint8 decimals)
    function totalSupply() constant returns (uint totalSupply);
    function balanceOf(address _owner) constant returns (uint balance);
    function transfer(address _to, uint _value) returns (bool success);
    function transferFrom(address _from, address _to, uint _value) returns (bool success);
    function approve(address _spender, uint _value) returns (bool success);
    function allowance(address _owner, address _spender) constant returns (uint remaining);
    event Transfer(address indexed _from, address indexed _to, uint _value);
    event Approval(address indexed _owner, address indexed _spender, uint _value);
}

逐个解释一下上述的接口函数:

  • name (): 返回 string 类型的 ERC-20 代币的名称

  • symbol (): 返回 string 类型的 ERC-20 代币符号,可以理解为代币的简称

  • decimals (): 当前代币支持几位小数,如果为 3,则支持 0.001 粒度的代币。在智能合约里,其实是不存在小数的,而是通过 unit256 来存在,deciaml 用于表示 uint256 存储的值中有几位代表小数。

  • totalSupply (): 代币总发行量

  • balanceOf (address _owner): _owner 地址中代币的余额

  • transfer (address _to, uint _value): 转账函数,假设地址 A 调用了 transfer 函数,则表示将地址 A 中_value 个 token 转给地址_to

  • approve (address _spender, uint _value): 授权函数,允许_spender 地址从自己的账户地址中转移_value 个 token(很多钓鱼网站使用的函数)

  • transferFrom (address _from, address _to, uint _value): 转账函数,与 approve 函数搭配使用,通过 approve 函数获得_from 地址的授权,授权对象是当前调用 transferFrom 函数的合约地址,此时合约便可以转移_from 地址中的_value 个 token 到_to 地址中

  • allowance (address _owner, address _spender): 返回_spender 地址还能从_owner 地址中提取多少 token,当合约通过 approve 函数获得某地址授权后,默认是可以转移该地址中所有的 token 的。

  • event Transfer (address indexed _from, address indexed _to, uint _value): 转账事件,所谓事件,其本质是记录的日志,当转账事件发生时,外界是无法监听相关数据的,即不知道转账发生了,此时的解决方法便是利用事件,将信息记录起来,外界通过监听事件来判断合约做了什么,因为事件本身的作用与目的,发送事件也被称为广播事件。

  • event Approval (address indexed _owner, address indexed _spender, uint _value): 授权事件

ERC-20 标准中,transfer、approve、transferFrom 这三者是比较容易搞混的函数,这里简单解释一下:

transfer (address _to, uint _value) 是单纯的转账,假设账户 A 调用了 transfer 函数给账户 B 转账,形式为:transfer (B, 100),该函数的会检查 A 地址中是否有 100 个相关代币,如果有,则将 100 个代币转到 B 地址中。

transferFrom (address _from, address _to, uint _value) 是替别人转账,假设账户 A 中有 100 个代币,账户 A 同样想转给账户 B,但他不想直接转,此时便出现了账户 C(通常是一个合约),合约 C 会通过 approve 函数获得操作账户 A 中代币的授权,然后合约 C 通过 transferFrom 函数将账户 A 中的 100 个代币转移给账户 B。

你可能会疑惑,转账为啥要还要引入合约 C 这个第三方?直接用 transfer 函数转账不行吗?

只使用 tranfer 函数进行转账是没有问题的,但并不能满足所有的情况,比如 DeFi 的各种借贷应用,本质还是将账户 A 的代币转给账户 B,但账户 A 之所以会借是因为有借出去的代币可以产生利息收益,这个功能就需要一个独立于账户 A 与账户 B 之外的合约 C 来实现,比如 Uniswap 就会获取你账户中代币的操作权限。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

懒编程-二两

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值