-
Notifications
You must be signed in to change notification settings - Fork 11.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Why not wrap the _balances[to] += amount
instruction in an unchecked
block?
#3512
Comments
Indeed, the I think we haven't done that previously because we were not fully comfortable with using unchecked with a low granularity, but this is an obvious gas improvement that we should implement! Would you like to open a PR for that? |
Good catch!
Thanks for letting me do it. Here it is! |
So for the record I want to explain why we did not have this optimization before and why we're going to merge it now. The reasoning until now was that we use require(amount <= balances[to]);
unchecked {
balances[to] -= amount;
} We know The property that What is happening now is we're relaxing the requirements to use This makes the case for For future reference, this optimization of ~130 gas, in my opinion, only barely meets the threshold to be worth the extra complexity (complexity to prove the correctness of the contract!). |
"local reasoning" is such an apt way to describe the problem situation, @frangio! I had the same concern in mind when I said that the only argument I can think of in favor of keeping checked arithmetic is the precautionary principle - if an OpenZeppelin user inherits from ERC20 and implements a way to increase the |
Fixed in #3513. |
This issue is related to #2875, but my question comes from a different angle:
Why not wrap all calculations in the
_transfer
function in anunchecked
block? I'm specifically referring to line 241 in the_transfer
function:openzeppelin-contracts/contracts/token/ERC20/ERC20.sol
Line 241 in e734b42
It seems to me that the balance of the
to
account can never overflow (it's an invariant), due to the fact that the_mint
function uses checked arithmetic (and rightly so).I looked at the tests for the
transfer
function and couldn't find a test that checks for an overflow on line 241:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/e734b42fc2245b520372bca0099870f40f1e6f38/test/token/ERC20/ERC20.behavior.js
The only argument that I can think of in favor of keeping the current behavior is the precautionary principle: many people inherit
ERC20
and modify it according to their project idea, which in some cases might involve changing the_balances
mapping outside of_mint
.Thoughts?
The text was updated successfully, but these errors were encountered: