-
Notifications
You must be signed in to change notification settings - Fork 1.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
Gas cost discrepancies when testing calls through a proxy #2503
Comments
Are the first gas numbers from Another thing to note is that the gas report from |
First gas numbers are from I still don't understand the separate reports you have for the proxy and the implementation, what are you saying is the difference for example for the call to As for the cold/warm storage costs, that cannot explain the gas cost difference as I am executing the exact same single unit test on There is 37,266 gas difference in the first call and 24,048 gas difference in the second call so still a lot unaccounted for. EDIT: And also why the Proxy gas costs are only shown sometimes? |
I would assume that the proxy points to I think Hardhat only produces 1 report because it looks at the transaction you directly send to the RPC. We don't have an RPC, so we decode all calls between the contracts.
It can still explain some of the difference - Hardhat does RPC calls, so 100% clean slate, where a call to a test function in Foundry necessarily is already not a 100% clean slate, since there is some setup involved with calling and executing the test function itself in the first place. It might not make up for the entire difference, but I was just noting that this is something that I expect to have an impact.
The gas reports Forge produces is without the 21000 tx gas stipend, whereas I assume Hardhat includes it - that accounts for 21000 of the difference, so we have ~16k and ~3k left to account for, I assume. I'm not entirely sure how the two scenarios differ - is there a chance you could expand a bit on it?
No that sounds pretty weird 🤔 Do you have some pointers on how I could maybe reproduce? |
I've reproduced the issue in an MVP in https://github.com/elenadimitrova/foundry-hardhat-gas-compare where you can run the two identical set of tests and see the difference between |
I don't have a lot of time currently to go in and individually dissect each opcode to find out if there is some larger thing unaccounted for, but the EVM implementation we use conforms to the Ethereum tests that all nodes use, so I am fairly confident we are not far off We've also investigated the smaller gas discrepancies more closely before, where we did account for it: https://github.com/mds1/convex-shutdown-simulation (see the note about Foundry) I'd love to hear some input/ideas from anyone who has suggestions on how we can improve the accuracy of the reports, but it does not seem like a trivial problem to solve due to how Forge executes tests vs other frameworks |
@onbjerg I have confirmed the storage slots aren't "hot" as you explain, with this commit which is testing storage slots are "cold" before writing. There is effectively around 5200-5500 unexplained gas difference in the
This is quite critical considering the importance of gas cost analysis in smart contracts for decision making, i.e. we are currently trying to weigh in the costs of the two different proxy patters and finding it difficult to trust what foundry reports. |
The account is still hot, though. For more information on what that means: https://eips.ethereum.org/EIPS/eip-2929 Specifically:
Since the contract is created in the same transaction as you are calling mint on it, the account itself is considered to be hot. I'm sure there are other such cases here that explain the discrepancy, since it is not only SLOAD/SSTORE that is affected by EIP 2929. |
This has likely been resolved by the new isolation mode enabled by default when using Tentatively closing as resolved, feel free to re-open if this is still an issue. |
Component
Forge
Have you ensured that all of these are up to date?
What version of Foundry are you on?
forge 0.2.0 (33dbaa5 2022-07-23T00:04:10.615195Z)
What command(s) is the bug in?
forge test --gas-report
Operating System
macOS (Apple Silicon)
Describe the bug
When comparing the gas cost test results between
hardhat-gas-reporter
andfoundry
they significantly differ for the following sample test cases:a) ContractA.mint() calling external contract ContractB.mint() where ContractB is the implementation of a Minimal Proxy
foundry reports 68,530 gas
hardhat reports 105,796 gas
b) ContractB.mint() getting called on top of an implementation Proxy (where ContractB is the implementation set on Proxy)
foundry reports 68,992 gas
hardhat reports 93,040 gas
I would normally expect test case a) to be more expensive than test case b) as it is doing a cross contract call (even if in test case B the proxy does an extra read from storage to get implementation address).
Additionally (as this maybe related symptom), when measuring gas costs for calls routed through a proxy referencing an implementation contract, there are two sets of gas costs
foundry
reports, one for the Proxy itself and another for the implementation contract as seen in screenshot belowHowever when a different proxy is used that does no local storage reads (e.g. a minimal proxy or the same as above but with immutable implementation instantiated in the proxy constructor) the Proxy gas cost table is no longer displayed and only implementation costs show.
The text was updated successfully, but these errors were encountered: