Skip to content

Conversation

SDartayet
Copy link
Contributor

Description

This PR adds a check for the case where a system contract code is empty. This is required to pass a few Hive tests recently added that ask to return an error in such a case.

@github-actions github-actions bot added the L1 Ethereum client label Oct 1, 2025
Copy link

github-actions bot commented Oct 1, 2025

Lines of code report

Total lines added: 13
Total lines removed: 0
Total lines changed: 13

Detailed view
+---------------------------------------+-------+------+
| File                                  | Lines | Diff |
+---------------------------------------+-------+------+
| ethrex/crates/vm/backends/levm/mod.rs | 470   | +9   |
+---------------------------------------+-------+------+
| ethrex/crates/vm/system_contracts.rs  | 66    | +4   |
+---------------------------------------+-------+------+

Copy link

github-actions bot commented Oct 1, 2025

Benchmark Results Comparison

No significant difference was registered for any benchmark run.

Detailed Results

Benchmark Results: BubbleSort

Command Mean [s] Min [s] Max [s] Relative
main_revm_BubbleSort 4.758 ± 0.005 4.748 4.763 1.02 ± 0.00
main_levm_BubbleSort 4.643 ± 0.018 4.622 4.677 1.00
pr_revm_BubbleSort 4.796 ± 0.095 4.756 5.064 1.03 ± 0.02
pr_levm_BubbleSort 4.680 ± 0.066 4.638 4.849 1.01 ± 0.01

Benchmark Results: ERC20Approval

Command Mean [s] Min [s] Max [s] Relative
main_revm_ERC20Approval 1.548 ± 0.005 1.543 1.559 1.00
main_levm_ERC20Approval 1.634 ± 0.005 1.627 1.642 1.06 ± 0.00
pr_revm_ERC20Approval 1.575 ± 0.025 1.536 1.618 1.02 ± 0.02
pr_levm_ERC20Approval 1.641 ± 0.003 1.638 1.648 1.06 ± 0.00

Benchmark Results: ERC20Mint

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_ERC20Mint 185.3 ± 6.1 182.7 202.6 1.01 ± 0.03
main_levm_ERC20Mint 197.0 ± 0.5 196.5 197.9 1.08 ± 0.01
pr_revm_ERC20Mint 183.2 ± 1.5 181.6 186.5 1.00
pr_levm_ERC20Mint 197.7 ± 0.5 197.0 198.4 1.08 ± 0.01

Benchmark Results: ERC20Transfer

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_ERC20Transfer 351.1 ± 2.4 349.4 357.3 1.00 ± 0.01
main_levm_ERC20Transfer 384.5 ± 1.3 382.8 387.0 1.10 ± 0.01
pr_revm_ERC20Transfer 350.9 ± 3.8 347.8 361.3 1.00
pr_levm_ERC20Transfer 390.3 ± 3.2 387.1 398.2 1.11 ± 0.02

Benchmark Results: Factorial

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_Factorial 235.4 ± 2.9 233.9 243.4 1.00
main_levm_Factorial 281.6 ± 8.6 276.3 302.4 1.20 ± 0.04
pr_revm_Factorial 236.0 ± 3.3 234.1 244.7 1.00 ± 0.02
pr_levm_Factorial 279.2 ± 2.5 277.0 285.4 1.19 ± 0.02

Benchmark Results: FactorialRecursive

Command Mean [s] Min [s] Max [s] Relative
main_revm_FactorialRecursive 1.672 ± 0.032 1.606 1.713 1.00
main_levm_FactorialRecursive 8.738 ± 0.089 8.614 8.873 5.23 ± 0.11
pr_revm_FactorialRecursive 1.692 ± 0.030 1.666 1.766 1.01 ± 0.03
pr_levm_FactorialRecursive 8.778 ± 0.051 8.718 8.904 5.25 ± 0.10

Benchmark Results: Fibonacci

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_Fibonacci 213.5 ± 2.6 210.7 219.9 1.00
main_levm_Fibonacci 261.5 ± 1.2 259.9 263.9 1.22 ± 0.02
pr_revm_Fibonacci 213.8 ± 1.8 212.7 218.8 1.00 ± 0.01
pr_levm_Fibonacci 262.5 ± 3.7 260.4 272.7 1.23 ± 0.02

Benchmark Results: FibonacciRecursive

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_FibonacciRecursive 923.4 ± 23.2 882.0 957.3 1.01 ± 0.03
main_levm_FibonacciRecursive 1054.6 ± 4.6 1048.7 1062.0 1.16 ± 0.01
pr_revm_FibonacciRecursive 911.6 ± 6.6 902.6 921.7 1.00
pr_levm_FibonacciRecursive 1050.6 ± 6.4 1042.0 1065.3 1.15 ± 0.01

Benchmark Results: ManyHashes

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_ManyHashes 12.3 ± 0.1 12.3 12.4 1.00
main_levm_ManyHashes 13.6 ± 0.1 13.6 13.8 1.10 ± 0.01
pr_revm_ManyHashes 12.4 ± 0.1 12.3 12.4 1.00 ± 0.01
pr_levm_ManyHashes 13.7 ± 0.1 13.6 14.1 1.11 ± 0.01

Benchmark Results: MstoreBench

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_MstoreBench 264.3 ± 0.7 263.2 265.4 1.00
main_levm_MstoreBench 757.0 ± 1.5 754.0 758.7 2.86 ± 0.01
pr_revm_MstoreBench 266.5 ± 2.9 264.0 272.9 1.01 ± 0.01
pr_levm_MstoreBench 758.0 ± 2.2 755.4 763.2 2.87 ± 0.01

Benchmark Results: Push

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_Push 298.2 ± 6.0 295.6 315.2 1.01 ± 0.02
main_levm_Push 830.2 ± 2.4 828.0 836.1 2.80 ± 0.01
pr_revm_Push 296.5 ± 0.7 295.9 298.3 1.00
pr_levm_Push 839.1 ± 8.1 832.6 857.9 2.83 ± 0.03

Benchmark Results: SstoreBench_no_opt

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_SstoreBench_no_opt 218.3 ± 2.2 216.7 224.4 2.40 ± 0.04
main_levm_SstoreBench_no_opt 90.9 ± 1.3 89.3 93.0 1.00
pr_revm_SstoreBench_no_opt 217.7 ± 0.9 216.6 219.7 2.40 ± 0.04
pr_levm_SstoreBench_no_opt 91.7 ± 1.4 89.6 94.2 1.01 ± 0.02

@SDartayet SDartayet marked this pull request as ready for review October 6, 2025 13:00
@SDartayet SDartayet requested a review from a team as a code owner October 6, 2025 13:00
@ethrex-project-sync ethrex-project-sync bot moved this to In Review in ethrex_l1 Oct 6, 2025
..Default::default()
};

if !(contract_address == HISTORY_STORAGE_ADDRESS.address
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be better to have a vec of system contracts somewhere? Otherwise it will be easy to miss this when a new system contract is added?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do have a vec of system contracts. However this case is more specific; it's not any given system contract but those that have code (the function in which this check is in is already only reached when a system contract is called). We could build a vec specifically for the system contracts that do have code though (or add a has_code attribute to the existing ones)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

if vm.current_call_frame.gas_limit < min_gas_limit {
return Err(TxValidationError::IntrinsicGasTooLow.into());
if vm.current_call_frame.gas_limit < floor_cost_by_tokens {
return Err(TxValidationError::IntrinsicGasBelowFloorGasCost.into());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

..Default::default()
};

if !(contract_address == HISTORY_STORAGE_ADDRESS.address
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd personally add a comment that we have this code in order to pass the tests and that it's impossible in real scenarios. I am not in favor of adding the check but if we want it I'd just add that comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, done here. Let me know if you think the comment is adequate

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's great, thanks

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible that the changes in this file are somehow unrelated to the PR title? Like the PR is for when the code is empty in system contract calls, this is for other scenario, isn't it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also did you add this because you saw a test that made it necessary or what?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those changes were from a separate PR I made before this one. That one already got merged though, so I'm not sure why those are showing up in the diff for this one

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those are from this PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok there, merging the latest version of main into the branch fixed it, the files changed should show up properly now

@SDartayet SDartayet requested a review from JereSalo October 9, 2025 13:29
Copy link
Contributor

@JereSalo JereSalo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the deposit contract belong to the const of the contracts? Like I know the other two belong here because of EIP-2935 but I'm not sure about the other one. It does no harm anyway but I think it doesn't belong here.

Also, make sure to link the corresponding EIP for each contract that says that it should fail if there's no code
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7251.md
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7002.md#empty-code-failure

.filter(move |system_contract| system_contract.active_since_fork <= fork)
}

pub const SYSTEM_CONTRACTS_WITH_CODE: [SystemContract; 3] = [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is an accurate name. The contracts that should be here are just 2, the EIP 7002 and EIP 7251 contracts. Idk if we can call them PRAGUE_SYSTEM_CONTRACTS or any name representative of that

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example, the beacon root contract is a system contract with code but doesn't belong to the check we are trying to make. Correct me if I'm wrong

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair, I didn't know the details of the beacon roots contract. As for the rest, I'll fix it in a sec. I thought the deposits contract should be included too but I guess thinking about it now it needn't

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SDartayet SDartayet requested a review from JereSalo October 9, 2025 16:15
@JereSalo
Copy link
Contributor

JereSalo commented Oct 9, 2025

Also, make sure to link the corresponding EIP for each contract that says that it should fail if there's no code https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7251.md#empty-code-failure https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7002.md#empty-code-failure

this is still missing

@SDartayet
Copy link
Contributor Author

Adding links to EIPs

Sorry, my bad, idk how I missed that comment. Fixed it here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

L1 Ethereum client

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

3 participants