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