从导致SMT被黑的transferProxy函数看EOS体系的安全解决方案

下面这段就是导致SMT被黑客攻击导致价值归零、以及各大交易所纷纷停止提币的核心代码

    /*
     * Proxy transfer SmartMesh token. When some users of the ethereum account has no ether,
     * he or she can authorize the agent for broadcast transactions, and agents may charge agency fees
     * @param _from
     * @param _to
     * @param _value
     * @param feeSmt
     * @param _v
     * @param _r
     * @param _s
     */
    function transferProxy(address _from, address _to, uint256 _value, uint256 _feeSmt,
        uint8 _v,bytes32 _r, bytes32 _s) public transferAllowed(_from) returns (bool){

        if(balances[_from] < _feeSmt + _value) revert();

        uint256 nonce = nonces[_from];
        bytes32 h = keccak256(_from,_to,_value,_feeSmt,nonce);
        if(_from != ecrecover(h,_v,_r,_s)) revert();

        if(balances[_to] + _value < balances[_to]
            || balances[msg.sender] + _feeSmt < balances[msg.sender]) revert();
        balances[_to] += _value;
        Transfer(_from, _to, _value);

        balances[msg.sender] += _feeSmt;
        Transfer(_from, msg.sender, _feeSmt);

        balances[_from] -= _value + _feeSmt;
        nonces[_from] = nonce + 1;
        return true;
    }

这是黑客利用漏洞完成SMT无限增发的合约调用
https://etherscan.io/tx/0x1abab4c8db9a30e703114528e31dee129a3a758f7f8abc3b6494aad3d304e43f

方法涉及的角色:
角色1 需要转SMT、但地址里面没有ETH的人 – 合约中的_from
角色2 帮助角色1来转SMT,并支付ETH的gas费用 – 合约中的msg.sender,也是调用这个合约的人
角色3 SMT接收方

方法的目的:
角色1想要转SMT给角色3,但自己又没有ETH来支付手续费,于是角色1找到有ETH的角色2说:我给你一些SMT当做手续费,你来通过调用transferProxy来把我的SMT转给角色3,因为你有ETH

方法的漏洞:
漏洞利用前几天导致BEC归零类似的uint256溢出,绕过了if的判断,所以解决这类问题还是需要使用SafeMath来做加减乘除。

EOS体系的解决方案:

1 关于转账手续费
虽然EOS主网还没有上,但根据EOS白皮书的说法,EOS体系转账是需要手续费的,但EOS允许收款人支付。这样角色1可以把中间人角色2排除,直接与角色3交易。

2 关于智能合约漏洞
当“势不可挡的应用程序”以不可预知的方式发挥作用时,使用EOS.IO软件的区块链允许区块生产者(超级节点)替换账户的代码,而不分叉整个区块链。这类似冻结账户的过程,这个代码的替换需要选出的15/21的区块生产者投票。

3 权限管理
proxyTransfer方法里的角色B获得角色授权进行资金操作的情况,在EOS中可以通过权限映射+多签名阈值来实现,虽然没有ETH上这么灵活,但从编程友好和安全的角度是有优势的。

以太坊的智能合约的灵活性是很高的,但也对智能合约开发者提出了很高的要求,而EOS有针对性对这些做了自己的结构设计。