ERC20代币传输给合约地址可能会丢失

Words
650
Reading
3 min
9y
Listen to this post
~4 min

此文档为个人整理学习使用,部分内容来源于网络,也期待能给你带来益处!如果转载,请保留原始链接!
https://steemit.com/@chaimyu

来源

访问ClassicEtherWallet钱包,上方大红提示一个安全警告,如下:

意思是ERC20代币不要使用transfer传输到一个合约地址,否则会导致代币丢失。

ERC20代币现在很多,我们肯定会经常用到,决定好好看一下这个安全警示到底是什么?


分析

ERC20代币传输有两种方式:

  • transfer函数
  • approve + transferFrom函数

ERC20只提供了函数原型,没有标准实现,我们来看一下这几个函数的实现,如下:

     function transfer(address _to, uint256 _value) public {
        _transfer(msg.sender, _to, _value);
    }

transfer只是调用内部函数,内部_transfer最主要的工作就是操作代币地址表,减少发消息者的代币数量,增加接收者的代币数量,如下:

        // Subtract from the sender
        balanceOf[_from] -= _value;
        // Add the same to the recipient
        balanceOf[_to] += _value;

代币合约参看 https://steemit.com/ethereum/@chaimyu/5eu2fa

从这大概能明白了,这些地址都只是智能合约中的变量,并不能区分是外部钱包地址还是合约地址,接收方没法得到任何事件通知,做任何处理!

那为什么以太币不会有这种问题呢?以太币发送到合约时,正常情况下合约是不会接收以太币并会自动回滚操作的,合约如果要接收以太币需要增加以下函数,并针对收到的以太币数量和发币地址做处理:

function () payable public { ... }

从这也明白了,Ether和ERC20代币传输之间最大的区别,一个是在以太坊链网上进行,一个是在智能合约内部进行(只是改改合约变量),所以不要用transfer直接传输代币给合约地址!

解决

针对现有的ERC20代币,建议的用的approve + transferFrom方式呢,来看看:

    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        require(_value <= allowance[_from][msg.sender]);     // Check allowance
        allowance[_from][msg.sender] -= _value;
        _transfer(_from, _to, _value);
        return true;
    }

    function approve(address _spender, uint256 _value) public
        returns (bool success) {
        allowance[msg.sender][_spender] = _value;
        return true;
    }

用这种方式,就是用户首先通过approve授权合约地址可以操作自己的代币,可以指定允许操作的数量,然后由代币接收方合约来调用transferFrom函数,这样能保证代币接收方合约知道在干什么!

新的代币标准不受这个bug影响:

ERC223 https://github.com/ethereum/EIPs/issues/223

ERC777 https://github.com/ethereum/EIPs/issues/777


参考

ERC20标准 https://github.com/ethereum/EIPs/issues/20

问题英文描述 https://gist.github.com/Dexaran/ddb3e89fe64bf2e06ed15fbd5679bd20

丢失示例 https://docs.google.com/document/d/1Feh5sP6oQL1-1NHi-X1dbgT3ch2WdhbXRevDN681Jv4/edit


感谢您阅读 chaimyu@chaimyu 的帖子,期待您能留言交流!

ERC20代币传输给合约地址可能会丢失 | Ecency