Comments (2)
I can confirm this. I see that in the optimized Yul code the loop is identical in both cases and the difference is only visible in assembly. This means that it must be the effect of the optimized Yul->EVM transform. We fall back to the legacy transform if the assembly blocks are not memory-safe.
Honestly, I'm not sure if this is something we'll be able to fix. I think it's likely to not be a result of a bug that can be simply "fixed", but rather a trade-off that might affect other cases. We're generally working on improving the transform, so this may also improve as a result of the upcoming changes and might not make sense to target specifically. Need @ekpyron's opinion here.
Details
The stack shuffling issue is specific to the two
staticcalls
to the SHA-256 precompile that follow. In particular, if you remove any of them, the problem is no longer observed and you get the expected behaviour of code withmemory-safe
assembly tags being slightly more performant than potentially memory unsafe assembly.
Interesting. I expected that this would be caused by stuff being optimized out without the calls, but no. When I comment out the staticcall
s the loop is still there, and still the same in both cases, just processed differently by the transform.
(Also on an unrelated note, I noticed that it is compiling
sub(shift, 6)
asadd(shift, 0xffff...ffa
which is 31 more code bytes and also seems like a minor bug...)
Maybe we should reconsider #6765 after all. I think it happens because Yul optimizer always converts sub()
to add()
and in this form this leaves the constant optimizer only the choice between add(shift, not(5))
(which is more space-efficient and chosen for lower runs
values) and add(shift, 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa)
(which is cheaper to execute). Converting it back to sub(shift, 6)
would be a much better alternative, since it's both cheaper and more space-efficient.
Workaround
I would not necessarily recommend it as a general solution, but as of 0.8.25 we still support the stackAllocation
option in Standard JSON, which lets you select the old Yul->EVM transform. Keep in mind though that we're going to deprecate it eventually.
Repro
CLI repro using Foundry. Assumes that the contract from the issue description is in a file called base64-safe.sol
.
export seed="grace crime cat remove spice bean concert lawsuit render horse collect vocal"
anvil --mnemonic "$seed"
export key=0x60b139825a56a987d58b20f0145e05dc45bed12df72cb92812b5ea988383c987
function benchmark_contract {
solc "$1".sol --via-ir --optimize --optimize-runs 100000 --bin |
sed -e '/^=======.*=======$/d' -e '/^Binary:$/d' -e '/^\s*$/d' > "$1".bin
local address
address=$(
cast send --json --private-key "$key" --create "$(cat "$1".bin)" |
jq --raw-output .contractAddress
)
gas=$(
cast send --json --private-key "$key" "$address" "bench()" |
jq --raw-output .gasUsed
)
echo "$((gas - 21000))"
}
benchmark_contract base64-safe
sed -e 's/("memory-safe")//g' base64-safe.sol > base64-unsafe.sol
benchmark_contract base64-unsafe
5104
4486
from solidity.
Thanks for the detailed response.
Another possible work around would be to split the code into separate functions, one with the loop and another with the static calls, and force the loop to not be optimized somehow (we can achieve this by having an additional external function that calls the loop function). I verified it with the above code and it had the desired effect.
Is there a better way to tell the Yul optimizer "please don't inline this function" without changing the ABI of the contract?
from solidity.
Related Issues (20)
- Verifying blobhash causes failure to obtain gasLimit HOT 2
- Security vulnerability: Why do % and MOD result in different outputs despite being technically the same function? HOT 2
- SMT logic error for a conditional with empty tuple types
- Code Deduplication Creates Wrong Source Mappings HOT 1
- Reduce default font weight for readability HOT 2
- Providing an empty string to `--yul-optimizations` without enabling yul optimization triggers uncaught exception HOT 1
- Version the `list.json` file for build information
- SMT logic error for bitwise operators HOT 2
- Abnormal execution time of the SMTChecker HOT 2
- Type conversion can trigger SMT Logic Error under certain conditions
- Standard ERC-721 "name" and "symbol" function error with Cancun EVM HOT 1
- Support named parameters in abi.encodeCall
- Inconsistent storage caused by function-type variable assignment HOT 1
- SMTChecker: Unable to support keccak256 well
- Incorrect `src` start position in ast. HOT 2
- AbiCoder v1 incorrectly encodes arrays containing overflow values
- Resuming compilation from AST import does not produce identical metadata HOT 1
- IR-based Code Generator truncates overflow values, resulting in inconsistent variable values. HOT 2
- SMTChecker: Fail to parse abi.encodeCall
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from solidity.