0

Assume balanceOf[msg.sender] is typed as uint256, and a user wants to withdraw _amount units from her balances (_amount is also typed uint256). In that case

balanceOf[msg.sender] -= _amount;

will revert if balanceOf[msg.sender] < _amount. Does this make the following requirement unnecessary?

require(balanceOf[msg.sender] >= _amount);

It now seems redundant.

Eric Falkenstein
  • 701
  • 1
  • 5
  • 18
  • I looked at OpenZeppelin's latest ERC20 token contract, and see the have

    uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; }

    I presume this is best practice, but I can't understand why. First, they maintain the seemingly redundant check require(fromBalance >= amount), but this become relevant because they then apply the decrement using 'unchecked,' which turns off the math overflow reversion built int to Solidity 8.0.

    – Eric Falkenstein Apr 21 '22 at 14:33
  • Yes, that check is now redundant, though it doesn't hurt to perform it so you can throw a custom error. Check out my modern implementation of ERC-20. – Paul Razvan Berg Apr 21 '22 at 17:42

1 Answers1

0

I discovered that if you use the OpenZeppelin method you save 300 to 2000 gas. For some reason the internal math overflow method is not very efficient, so if you do not mind wordiness, you add the 'unchecked' to a 'require' statement.

Eric Falkenstein
  • 701
  • 1
  • 5
  • 18