Submitted by muellerberndt, also found by RadiantLabs, gumgumzum, and ahmedaghadi
Calling the RIPEMD160 precompile with certain input lengths results in a Cairo exception. As a result, some L2 smart contracts that use this precompile cannot be executed.
The bug seems to occur in line 477 of the precompile. The relevant code:
The lower part of the code is reached for some input lengths. Note that x is redefined with the line:
However, start still points to the first element of the original dict x initialized at the start of the function. Consequently, squashing the dict with default_dict_finalize(start, x, 0) will fail because start and x point to different segments.
The issue can be verified by running the following Solidity contract as an e2e-test:
While calling hashInputLength20() returns the correct result, hashInputLength32() will result in a failed test:
In the ordinary EVM, the same function returns the result:
Additionally, the following Cairo test reproduces the issue:
This will crash with the exception:
Set the pointer start to the correct value. It is also very important to finalize the previously initialized dict x as the prover can cheat otherwise.
Double-check the invocation path of the precompile exec_precompile(), and add end-to-end tests for all precompiles to make sure that they work as expected when called from L2.
Error
ClementWalter (Kakarot) confirmed and commented:
LSDan (judge) decreased severity to Medium
Kakarot mitigated:
Status: Mitigation confirmed.
