本文主要介绍 SHIBA INU 合约。
该合约是一个简单的 ERC20 代币合约。
目前,本文包括两部分:
- 第一部分是 SafeMath 库 ,包含了基础算术运算。
- 第二部分,是合约中出现的主要函数。
SafeMath
SafeMath 是一个在合约中定义的库。在 SHIB 合约中,它被实现为对基本算术:加减乘除的安全操作。并且,这些操作将被应用在所有 uint256 变量上。
1 | library SafeMath { |
上述代码可知,一旦不满足计算需求(require),将抛出异常,终止合约执行。
根据 官方文档,库和合约类似,但是它的目的,被定位为一次部署,其它代码复用(使用 EVM 的消息调用特性完成调用)。这就意味着,库中函数的调用,是执行在调用合约的上下文环境中,也因此,其中的 this
是指向调用合约(calling contract)。
库中的函数,应是无状态的(stateless),因此,即为 view
或者 pure
,它不修改状态。
同时,它还具有以下特性:
- 无法被继承也无法继承
- 不能发送 eth
- 无法被销毁
函数
totalSupply() -> uint256
现存的 token 总量。这个函数是一个 getter 方法,因此不会修改合约状态。需要注意的是,在 Solidity 中没有浮点(早期版本),因此,对于一个采用了 18位小数精度的 token,返回值 1000000000000000000 代表 1 个 token。
如果合约允许,total supply 是可变的。比如,你可以挖出新的 token,这时,total supply 就是增加的,如果你销毁了部分 token,此时 total supply 将减少相应的数额。
一种另类的销毁 token 的方式,是将 token 发送到一个不知道私钥的账户地址,比如 0 地址,这种方式和销毁有着相同的功效,但是,其并不会使 token 的总量变少。
balanceOf(address account) → uint256
获取指定账户所拥有的 token 量。只要有 address,都可以查询该地址所拥有的 token,所有数据都公开在区块链上。
1 | mapping(address => uint256) private _balances; |
transfer(address recipient, uint256 amount) → bool
从调用者处转移指定 amount
的 token 给 recipient
。如果转账成功,将返回 true。需要注意的是,该方法不会检查接收地址的有效性。换句话说,任何 40 个十六进制字符,都是合法地址。转账时,也不会验证接收方是否存在。
1 | function transfer(address recipient, uint256 amount) public returns (bool) { |
approve(address spender, uint256 amount) → bool
调用者(委托方)给 spender 授权 amount
数量的 token(限额),使得 spender 作为受托方可以从委托方账户中完成最多 amount
数量的交易给其它第三方。
1 | function approve(address spender, uint256 value) public returns (bool) { |
从上述关系中,我们可以知道这种授权关系,其实是记录在 _allowances
map 中,其建立了所有从 owner
到 spender
的授权额度。而且,这个额度也是可以调整的,下面将进行介绍。
allowance(address owner, address spender) → uint256
查询当前 owner
授权给 sender
token 的数量。
1 | // 查询某个地址的授权额度 |
transferFrom(address sender, address recipient, uint256 amount) → bool
approve 调用完成了委托方向受托方的 token 定量授权。此后,受托方调用合约中的 transferFrom 方法,帮助委托方完成交易。
1 | function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { |
approve/transferFrom
机制,主要解决 三方 之间的转账问题。有时,发送者希望授权第二方能够代表他完成有限数量 token 的转移。
举个例子:
- 调用
X合约
(我随便定义的一个合约,以和Uniswap合约
对比)中approve
方法将允许Uniswap合约
在自己账户中转移出 N 个 token - 此时,可以调用
Uniswap 合约
中的 兑换函数,兑换一些 ETH。该函数将自动调用X合约
中的transferFrom
函数,实现从你的账户中转移出 N 个 token ,并将对应的 ETH 转入到你的账户。所有上述过程,将发生在同一个交易中。
_burn(address account, uint256 amount) internal
该方法也不属于标准的 ERC20 协议。账户销毁指定 amount 的 token。
1 | function _burn(address account, uint256 value) internal { |
_burnFrom(address account, uint256 amount) internal
减少 sender
的授权额度,并将这个额度销毁。其实是 _burn
和 _approve
的结合,二合一,减少外部调用次数。
1 | function _burnFrom(address account, uint256 amount) internal { |
burn(uint256 value) public
外部真正暴露的 burn 函数。
1 | function burn(uint256 value) public { |
_mint(address account, uint256 amount) internal
与 _burn
相对立的函数。同样的,其不仅仅给某个账户新增加了 amount
的token,同时还将增量同步到了 _totalSupply
。
1 | function _mint(address account, uint256 amount) internal { |
constructor
1 | constructor(string memory name, string memory symbol, uint8 decimals, uint256 totalSupply, address payable feeReceiver, address tokenOwnerAddress) public payable { |
参考链接
Solidity Tutorial: all about Libraries
UNDERSTAND THE ERC-20 TOKEN SMART CONTRACT
understanding-erc-20-token-contracts
Sending a transaction to a non-existent address
What is the use case of transferFrom function in ERC20 token contract?