Skip to content
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

[EVM-Equivalence-YUL] Fix compiler tester bugs #527

Merged

Conversation

gianbelinche
Copy link

@gianbelinche gianbelinche commented Jun 11, 2024

What ❔

This PR fixes bugs found using era-compiler-tester, most of them related to overflow checks.

A full description of the bugs and their fixes below.

Empty Return Data

We were not returning gas on reverts, which made a lot of tests fail on a check by the compiler-tester after execution where it tried to retrieve gas used from the return data and it was empty. We added gas on reverts so now those errors are no longer there.

mcopy

Some tests fail because compiling them with the solc version used by the project, they internally generate mcopy opcodes, which we do not support because we target Shanghai, not Cancun. We added a basic implementation of mcopy that makes tests pass, though it's very inefficient since there is no mcopy opcode on the zkEVM.

The mcopy tests are the following:

  • tests/solidity/simple/error/revert5.sol::first[f:1]
  • tests/solidity/simple/internal_function_pointers/data_structures.sol::double[calculate:1]
  • tests/solidity/simple/internal_function_pointers/data_structures.sol::triple[calculate:1]
  • tests/solidity/simple/solidity_by_example/simple/structs.sol::first[get:2]
  • tests/solidity/simple/solidity_by_example/simple/structs.sol::second[get:5]
  • tests/solidity/simple/solidity_by_example/simple/structs.sol::second[get:6]
  • tests/solidity/simple/constants/ConstantBytes.sol::long
  • tests/solidity/simple/solidity_by_example/simple/hello_world.sol::get[greet:1]
  • tests/solidity/simple/solidity_by_example/simple/variables.sol::text[text:2]
  • tests/solidity/simple/events/3_topics.sol::default[test:1]
  • tests/solidity/simple/events/4_topics.sol::default[test:1]
  • tests/solidity/simple/solidity_by_example/simple/verifying_signature.sol::test[verify:1]
  • tests/solidity/simple/solidity_by_example/simple/shadowing_inherited_state_variables.sol::test[getName:1]
  • tests/solidity/simple/try_catch/error_as_bytes.sol::main[main:1]
  • tests/solidity/simple/try_catch/revert_long_data.sol::main[main:1]
  • tests/solidity/simple/solidity_by_example/applications/merkle_tree.sol::test[#deployer:tests/solidity/simple/solidity_by_example/applications/merkle_tree.sol:Test]
  • tests/solidity/simple/solidity_by_example/applications/merkle_tree.sol::test[getRoot:1]
  • tests/solidity/simple/solidity_by_example/applications/merkle_tree.sol::test[verify:2]

returndatacopy with size less than expected

Some solidity programs (especially those using try/catch statements) pass a certain size when performing a call, but if execution reverts the actual return data size can be smaller than size. We were not handling that correctly when copying the return data; now the behaviour correctly mimics the EVM one: when saving the return data from a call we copy the minimum amount of bytes between the one requested and the return data size. You can check out the geth code for that here.

Tests that were failing because of this were:

  • tests/solidity/simple/call_with_dirty_address.sol::default[test:1]
  • tests/solidity/simple/try_catch/not_payable.sol::main[main:1]
  • tests/solidity/simple/try_catch/external_call_as_arg.sol::false_true[main:1]
  • tests/solidity/simple/try_catch/nested.sol::false_false[main:1]
  • tests/solidity/simple/try_catch/nested.sol::false_true[main:1]
  • tests/solidity/simple/try_catch/nested.sol::true_false[main:1]
  • tests/solidity/simple/function/function_type/f6.sol::test[f:1]

Truncated addresses

The following test

  • tests/solidity/simple/call_with_dirty_address.sol::default[test:1] Return data is empty

failed because we were not truncating addresses to bytes20 before calling contracts on the call opcodes.

mstore8/mstore and return data too long

These two tests try to store a value to a memory location far exceeding the maximum the interpreter allows (0x1101e0).

  • tests/solidity/simple/yul_instructions/mstore8.sol::zero_value
  • tests/solidity/simple/yul_instructions/mstore.sol::zero_value

This test:

  • tests/solidity/simple/try_catch/return_long_data_in_constructor.sol::main

fails because the return data tries to allocate more memory than is possible on the interpreter.

These three tests are the only ones that are not yet fixed, but we believe in the context of the interpreter it makes sense that they do not pass. It might be a good idea to skip them.

Overflow checks

All the other tests failed because of missing overflow checks on opcodes. They were fixed. Note that for those opcodes their implementation becomes a bit more expensive. For the special case of keccak opcode, we had to add some overflow checks before actually calling keccak only to be able to insert the gas left on reverts, because the opcode does not do it on its own.

Why ❔

Checklist

  • PR title corresponds to the body of PR (we generate changelog entries from PRs).
  • Tests for the changes have been added / updated.
  • Documentation comments have been added / updated.

@jrchatruc jrchatruc marked this pull request as ready for review June 19, 2024 14:59
@jrchatruc jrchatruc merged commit e730132 into matter-labs:evm-equivalence-yul Jul 5, 2024
15 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants