最近审计中几次遇到了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
 
                如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!