Optimize Create2.computeAddress#3600
Conversation
|
Hello @ToweringTopaz and thank you for your PR. IMO, this kind of optimization negatively affect readability and auditability of the code. I'm not sure how significant the gas savings are. We would need number on that. |
|
I ran both versions of the code with similar input. Going from solidity to assembly saves 122 gas. I tried setting the free memory ptr to a large value before running the code, to see if memory depth would affect the cost of the solidity version and would cause a more significant different. That was not the case. |
| bytes memory bytecode | ||
| ) internal returns (address) { | ||
| address addr; | ||
| ) internal returns (address addr) { |
There was a problem hiding this comment.
It that change optimizing anything? If not, I would revert it and focus on the computeAddress function
Co-authored-by: Hadrien Croubois <[email protected]>
In addition to the savings on execution, this reduces deployment size by 360 bytes for a simple contract. That's a lot of bytecode, saving 77,000 gas on deployment. |
Were the optimizations turned on when you tested that ? I'm getting "just" 13k gas difference. That might depend on the number of use if the function is inlined. |
Optimization was off. Another factor that might apply is if abi.encodePacked is used elsewhere in the same contract. Would it be helpful to add comments to the assembly code, or is it self-explanatory enough? |
|
I think it's self explanatory. How would abi.encodePacked been used elsewhere affect the produced code. Can you measure that? |
If abi.encodePacked(bytes1,address,bytes32,bytes32) is used elsewhere, the new method only saves 27 bytes of bytecode with optimizations turned off and 60 with optimizations on, via-IR, 200 runs. This is the extreme "minimum benefit" case, so in all cases the new method provides a cost savings. |
that is deployment cost saving, right ? I guess its because the corresponding logic would be included anyway (like a private function). |
Right. Of course this is the most extreme example offering the least savings. Not many other things pack (bytes1,address,bytes32,bytes32) in this manner, in practice. |
|
I am not comfortable with overwriting the free memory pointer in this way. The Gitter discussion is not a strong enough guarantee. The reality is that this use of memory is outside of what is assumed by Solidity in memory-safe blocks, according to the documentation (source). In this PR I haven't seen how much gas is saved on execution. Is most of the gas saved due to avoiding memory expansion or is it due to an optimized code path? It would be okay and memory-safe if instead of doing this we simply write on free memory without updating the free memory pointer. We would be expanding memory slightly but it may not be that bad in context. If we move forward with my suggestion, the assembly block also needs a comment explaining what it does. |
@Amxx calculated gas savings of 122 using the unmodified method. Using free memory reduces this a bit due to ADD opcodes and 3 words of memory expansion in some cases, but it's still an optimized code path. |
|
I've added a "visual explanation" of how the assembly write to memory |
frangio
left a comment
There was a problem hiding this comment.
LGTM.
I want to add some detail. I consider this optimization to be almost too small to matter and something that the compiler should be taking care of. However, the assembly required is simple enough, and evidently the compiler is not taking care of it, so I agree with merging.
Co-authored-by: Hadrien Croubois <[email protected]> Co-authored-by: Francisco <[email protected]>
This is a more efficient method of computing a create2 address, utilizing the scratch space and (temporarily) the free memory pointer slot. See this discussion with solc devs regarding the memory-safety of this method.
For consistency and simplicity, also refactored the deploy function to use a named return variable.
PR Checklist