ERC20 标准再学习

ERC20 标准,是ETH上的一种合约标准。固定了事件和对应的接口

contract ERC20Interface {
  	function totalSupply() public constant returns (uint);
  	function balanceOf(address tokenOwner) public constant returns (uint balance);
   	function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
 	  function transfer(address to, uint tokens) public returns (bool success);
  	function approve(address spender, uint tokens) public returns (bool success);
  	function transferFrom(address from, address to, uint tokens) public returns (bool success);

  	event Transfer(address indexed from, address indexed to, uint tokens);
  	event Approval(address indexed tokenOwner, address indexed spender, uint tokens);

    string public constant name = "TEST Token";
    string public constant symbol = "TST";
    uint8 public constant decimals = 18;  // 18 is the most common number of decimal places
		uint256 public _totalSupply;
}

合约分为 函数和事件变量,三个部分,

变量

变量在 contract 里面是全局的。定义了Token 的名称符号和精度。

函数

totalSupply

可以看到函数部分,只是规定了接口名称。其中的实现逻辑就是开发者自行定义了。

比如这里的totalSupply 就是一个可以自定义的函数,这里的返回逻辑可以是一个定值。 或者是一个自动Burn的逻辑。

balanceOf

这里的balanceOf,就要说到 ETH 的模型了。ETH 是账户模型,不是UTXO 的模型。所以这里的 balance 在合约里面是有状态的。地址和与余额之间有着对应的关系。

// 这里保存着这个账户下的该Token的余额
mapping (address => uint256) public balances
// 这里是一个重要的授权额度,也就是允许 外层addr 操作 内层 addr 的该Token 的数量。
// 所以一般的 授权额度就是这里。
mapping (address => mapping (address => uint256)) public allowed

那么balanceOf这个就很好实现了,传入地址,返回地址在这个map 中的数量即可

function balanceOf(address tokenOwner) public constant returns (uint balance) {
       return balances[tokenOwner];
}

transfer

前面提到的 Token 实际上只是一个 账户的mapping,我们可以理解这个合约存储了每个人的账户以及余额。你的 Token 实际上只是这张合约里面的数据而已,实际上并没有进行转出。所以在这里的逻辑其实和在支付宝中进行转账一样。直接对db中的数据进行操作。

function transfer(address to, uint tokens) public returns (bool success) {
    balances[msg.sender] = balances[msg.sender].sub(tokens);
    balances[to] = balances[to].add(tokens);
    emit Transfer(msg.sender, to, tokens);
    return true;
}

这里的msg.sender 是 保留字,实际上就是调用这个合约的账户(钱包 或者 另一个合约)

可以通过代码看到,在sender 的账户上 减去一定数量的token, 接受转账的账户上再增加一定的数量。就完成了最简单的转账操作。如果想实现,收5% 的转账手续费这种逻辑的话,就直接在前面加上一行转给合约方的逻辑就好。

所以这里实现的是本人向另一个账户来进行转账

另外这里emit了 Transfer ,在转账逻辑中没有实际的功能。在这里是一个事件。

详解Solidity事件Event – 完全搞懂事件的使用

如果我们不emit 这个事件的话,实际上我们的逻辑是已经完成了。但是,如果我们想,把完成转账的事件让大家知道,那么这里就需要去emit 这该事件。


var infoContract = web3.eth.contract(ABI INFO);
var info = infoContract.at('CONTRACT ADDRESS');
// 这里的Transfer 是通过ABI 获取的
var transferEvent = info.Transfer();
// 这里进行事件的监听,如果触发了 Transfer 就执行
var transferEvent.watch(function(error, result){
    // handle result.args.from  result.args.to
});

transferFrom

有了上面的Transfer 逻辑,这里的TransferFrom 也好理解了,其函数基本定义如下

function transferFrom(address from, address to, uint tokens) public returns (bool success){
        balances[from] = balances[from].sub(tokens);
        allowed[from][msg.sender] = allowed[from][msg.sender].sub(tokens);
        balances[to] = balances[to].add(tokens);
        Transfer(from, to, tokens);
        return true;
 }

这里的逻辑比上面复杂一点,第一行是在from 的账户来减去转账的份额。这点很好理解。

第二行稍稍复杂慢慢讲,刚刚前面提到来授权额度。

allowed[from][msg.sender] 这里表示的是 From 账户对 sender(合约调用者)的授权额度,也就是说允许 sender 来对我这一部分钱来进行操作。

所以这里有两个sub,一个是从From 账户中减去这一部分转账额,另一部分是从授权额度中减去from对该sender 的授权额度。(如果失败那么触发回滚,后面再讲)

所以简单来说这部分实现的是一个委托转账的功能

后面的就是换汤不换药的, To 账户增加对应的Token,触发Transfer 事件。

approve

刚刚已经讲了授权额度的事情,就是 A允许B对自己的一部分Token 来进行操作。那么这里的approve 就是来进行这一部分授权的。

function approve(address spender, uint tokens) public returns (bool success) {
        allowed[msg.sender][spender] = tokens;
        Approval(msg.sender, spender, tokens);
        return true;
 }

可以看到,两个参数一个是 被授权的地址,还有一个是 授权的 Token 份额。前面的委托转账的部分,就是需要在这里进行份额的扣除。

同样的这里有 Approval 事件,用于通知Dapp,这里的动作完成。

allowance

用于检查当前的授权额度,直接进行return来进行返回。

function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
				reutrn allowed[_owner][_spender]
}

totalBalance

这里返回总的调用量,经典的实现,就是直接返回 _totalSupply

function totalSupply() public constant returns (uint) {
				return _totalSupply
}

当然,这里拓展一下,除了协议的本身逻辑我们也可以进行自我拓展。

比如我这里就可以搞一个增发的逻辑,之前的total 的数量不够。

function mintToken(address target, uint256 mintedAmount) onlyOwner public {
        balances[target] += mintedAmount;
        _totalSupply += mintedAmount;
        emit Transfer(address(0), address(this), mintedAmount);
        emit Transfer(address(this), target, mintedAmount);
    }

过了五年的时间,又一次开始学习智能合约。科技如果不去发展它得到的不是停止不前,而是退步。

上个世纪美国登上了月球,现在却上不去了。

希望这次自己可以坚定的学下去。知道自己想要什么就很幸福。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注