OpenZeppelin 实现ERC20 的transferFrom 时,为什么先调用_transfer(),然后再检查withdrawer allowance

In OpenZeppelin's implementation of ERC20's transferFrom, why is _transfer() called before withdrawer allowance is checked

这取自 OpenZeppelin 的 ERC20 transferFrom 实现:

    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        _approve(sender, _msgSender(), currentAllowance - amount);

        return true;
    }

在检查取款人 (msg.sender) 津贴之前调用 _transfer 是否有原因?

如果先进行津贴 require 检查,transferFrom 还能正常工作吗?

我在 OpenZeppelin GitHub Issues 上发现了关于同一主题的讨论,代码的作者确认该顺序在 ERC-20 的上下文中是不相关的

In the case of ERC20, the order is irrelevant because _transfer and _approve are independent and never call any other contract: they are executed atomically.

此外,他指出,在有人想要覆盖功能的情况下,保持顺序稳定很重要。

However, this is very relevant for users that intent to override _transfer or _approve with their own implementations: we should be clear about the order in which these things happen.

来源:https://github.com/OpenZeppelin/openzeppelin-contracts/issues/2030#issuecomment-568487500


所以假设您没有在重写的 _transfer()_approve() 内部函数中使用自定义逻辑,如果您切换顺序,transferFrom() 仍然可以正常工作。

其实我也在找同样的东西,然后我发现了这个讨论 [https://forum.openzeppelin.com/t/in-erc20-tranferfrom-why-transfer-before-checking-allowance/5312/3] 它提供了更多细节并阐明了其背后的原因。