-
Notifications
You must be signed in to change notification settings - Fork 11.8k
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
ERC20 _update customization is not practical. #4967
Comments
Another example is the capped implementation:
This could be implemented slightly more efficiently, by being located before the super in this instance, but also by being able to add this check before the total supply increment. |
Hi @BillSchumacher,
Can you elaborate what would be the problem with the following approach? abstract contract MyERC20 is ERC20 {
uint256 addressZeroBalance;
function balanceOf(address account) public view virtual returns (uint256) {
if(account === address(0)) return addressZeroBalance;
return _balances[account];
}
function _update(address from, address to, uint256 value) internal virtual override {
super._update(from, to, value);
if (to == address(0)) {
addressZeroBalance++;
}
}
} The variables are private intentionally so users DO NOT BREAK the invariants the contract assumes.
Could you elaborate on how it's more efficient? At most you'll be saving one |
This is broken because _balances is private and unavailable. A super to balanceOf does workaround that though.
In the scenario that we are at the cap two state writes are avoided saving quite a bit of gas, as displayed in the gas remaining screenshots. With the suggested workaround fixed: ~10000 more gas than required. Anyhow, I can submit a PR to fix capped if you like with the addition of course so we don't go over the cap before capping, I appreciate the insight. |
Right, this is what I meant: abstract contract MyERC20 is ERC20 {
uint256 addressZeroBalance;
function balanceOf(address account) public view virtual returns (uint256) {
if(account === address(0)) return addressZeroBalance;
return super.balanceOf(account);
}
...
}
I assume should be fine now.
This is straight false, you're measuring the gas just before executing the Please, share a detailed gas comparison using either Foundry or the Hardhat gas reporter for the whole function execution, including the optimization settings and other stuff. Without optimizations, I'd expect to save only 1 JUMPI on average for your use case. With optimizations enabled and via-ir I'd expect the difference to be waaay smaller. Note that 10 gas units saved is around 0.003 cents in mainnet at 100 gwei, that's the kind of optimizations we won't implement because it compromises other security guarantees of the contract. Variables are private for a reason. |
Why would you execute the update function if you are going to go over the cap? |
Gas measurement should take the full execution of the function into account. Why would you optimize for reverts if you can avoid it with a gas estimation? |
To avoid the state writes |
There are no state writes if you revert, sir. |
The current implementation of the ERC20 already tracks the balance of the zero address. Also, I prepared a Foundry project with both the current implementation and another custom implementation having the cap check before the You can see both implementations here. After running the following gas measurement: forge snapshot --via-ir --optimizer-runs 1000000000 --use 0.8.24 --match-test testTransfer -vvvv The result is exactly the same for both implementations:
Closing |
Indeed, thanks again. Ran 1 test for test/HelloWorld.t.sol:OverCapTest Ran 1 test for test/WorldHello.t.sol:OverCapAfterTest |
Actually I forgot the addition, it does save gas.
|
this output seems super unreliable... |
Is there a setting that I should have a certain way? |
If your test doesn't fail to a revert I don't think you're hitting the condition btw. |
You can't actually modify behavior due to the variables being private.
Let's say I want to customize the burn to increment the balance of the 0 adresss and decrement the total supply, It's not currently possible.
💻 Environment
OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)
📝 Details
🔢 Code to reproduce bug
The text was updated successfully, but these errors were encountered: