安全审计中WETH的transferFrom问题

  • SmileBits
  • 更新于 2024-05-06 15:40
  • 阅读 1130

最近审计中几次遇到了WETH的transferFrom,类似如上的代码,大家觉得这个代码会有问题吗?

——答案揭晓。 该代码在主网上运行不会有什么问题。但是在Arbitrum, Blast等l2上就会revert。

contract WETH_TEST{
    IWETH public immutable WETH;
    constructor(address _wethAddress){
        WETH = IWETH(_wethAddress);
    }
    function transferWETH(address to, uint256 amount)  public onlyOwner{
        require(to!=address(0), "Invalid address");
        require(amount > 0,"Invalid amount ");
        WETH.transferFrom(address(this), to, amount);
    }

}

最近审计中几次遇到了WETH的transferFrom,类似如上的代码,大家觉得这个代码会有问题吗?

——答案揭晓。 该代码在主网上运行不会有什么问题。但是在Arbitrum, Blast等l2上就会revert。 原因: (1)首先是代码使用不规范,该使用transfer的使用了transferFrom (2)主网上的WETH的实现,检查了 msg.sender和src的关系;而在l2上则是类似标准的ERC20的实现方式,会判断allowance, 而allowance[msg.sender][msg.sender]=0,就算是自己转移自己的资金也会报错。

主网上的实现:

function transferFrom(address src, address dst, uint wad)
        public
        returns (bool)
    {
        require(balanceOf[src] >= wad);

        if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) {
            require(allowance[src][msg.sender] >= wad);
            allowance[src][msg.sender] -= wad;
        }

        balanceOf[src] -= wad;
        balanceOf[dst] += wad;

        Transfer(src, dst, wad);

        return true;
    }

参考:https://etherscan.io/token/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code

而Blast, 上的实现。

function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual returns (bool) {
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

        balanceOf[from] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);

        return true;
    }

参考链接: https://blastscan.io/address/0x83acb050aa232f97810f32afacde003303465ca5#code

Arbitrum上的实现

/**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

参考链接 https://arbiscan.io/address/0x8b194beae1d3e0788a1a35173978001acdfba668#code

点赞 1
收藏 1
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
SmileBits
SmileBits
智能合约安全审计