Skip to content

EIP-3541 london test fixes #2029

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

Merged
merged 2 commits into from
Sep 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion eth/vm/forks/london/computation.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ class LondonComputation(BerlinComputation):
opcodes = LONDON_OPCODES

@classmethod
def validate_new_contract_code(cls, contract_code: bytes) -> None:
def validate_contract_code(cls, contract_code: bytes) -> None:
super().validate_contract_code(contract_code)

if contract_code[:1] == EIP3541_RESERVED_STARTING_BYTE:
raise ReservedBytesInCode(
"Contract code begins with EIP3541 reserved byte '0xEF'."
Expand Down
30 changes: 12 additions & 18 deletions eth/vm/forks/spurious_dragon/computation.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,31 +51,22 @@ def apply_create_message(
else:
contract_code = computation.output

if contract_code and len(contract_code) >= EIP170_CODE_SIZE_LIMIT:
computation.error = OutOfGas(
f"Contract code size exceeds EIP170 limit of {EIP170_CODE_SIZE_LIMIT}."
f" Got code of size: {len(contract_code)}"
)
state.revert(snapshot)
elif contract_code:
contract_code_gas_cost = len(contract_code) * constants.GAS_CODEDEPOSIT
if contract_code:
try:
cls.validate_contract_code(contract_code)

contract_code_gas_cost = len(contract_code) * constants.GAS_CODEDEPOSIT
computation.consume_gas(
contract_code_gas_cost,
reason="Write contract code for CREATE",
)
except OutOfGas as err:
except VMError as err:
# Different from Frontier: reverts state on gas failure while
# writing contract code.
computation.error = err
state.revert(snapshot)
cls.logger.debug2(f"VMError setting contract code: {err}")
else:
try:
cls.validate_new_contract_code(contract_code)
except VMError as err:
state.revert(snapshot)
raise err

if cls.logger:
cls.logger.debug2(
"SETTING CODE: %s -> length: %s | hash: %s",
Expand All @@ -91,6 +82,9 @@ def apply_create_message(
return computation

@classmethod
def validate_new_contract_code(cls, contract_code: bytes) -> None:
# helps facilitate EIP-3541 validation in LondonComputation
pass
def validate_contract_code(cls, contract_code: bytes) -> None:
if len(contract_code) >= EIP170_CODE_SIZE_LIMIT:
raise OutOfGas(
f"Contract code size exceeds EIP170 limit of {EIP170_CODE_SIZE_LIMIT}."
f" Got code of size: {len(contract_code)}"
)
2 changes: 1 addition & 1 deletion fixtures
32 changes: 12 additions & 20 deletions tests/core/vm/test_london.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from eth.chains.mainnet import (
MAINNET_VMS,
)
from eth.exceptions import InvalidInstruction, ReservedBytesInCode
from eth.exceptions import InvalidInstruction
from eth.vm.forks import BerlinVM
from eth.tools.factories.transaction import (
new_dynamic_fee_transaction, new_transaction,
Expand Down Expand Up @@ -182,10 +182,7 @@ def test_revert_on_reserved_0xEF_byte_for_CREATE_and_CREATE2_post_london(
)

assert revert_create_computation.is_error
assert isinstance(revert_create_computation.error, ReservedBytesInCode)
assert "0xef" in repr(revert_create_computation.error).lower()

assert revert_create_computation.get_gas_used() == 40000 # assert gas is consumed
assert 35000 < revert_create_computation.get_gas_used() < 40000 # assert gas is still consumed
assert revert_create_computation.get_gas_refund() == 0


Expand Down Expand Up @@ -259,24 +256,19 @@ def test_state_revert_on_reserved_0xEF_byte_for_create_transaction_post_london(
data=data,
)

with pytest.raises(ReservedBytesInCode):
block_import, _, computations = chain.mine_all(
[create_contract_txn_reserved_byte],
gas_limit=84082
)
block_import, _, computations = chain.mine_all(
[create_contract_txn_reserved_byte],
gas_limit=84082
)

reverted_computation = computations[0]
mined_header = block_import.imported_block.header
end_balance = reverted_computation.state.get_balance(funded_address)
reverted_computation = computations[0]
mined_header = block_import.imported_block.header

assert reverted_computation.is_error
assert isinstance(reverted_computation.error, ReservedBytesInCode)
assert "0xef" in repr(reverted_computation.error).lower()
assert reverted_computation.is_error
assert "0xef" in repr(reverted_computation.error).lower()

assert reverted_computation.get_nonce(funded_address) == 1 # assert nonce is still 1
# reverted txn consumes the gas:
assert mined_header.gas_used == 60000
assert end_balance == new_balance - 60000
# reverted txn consumes the gas:
assert mined_header.gas_used == 60000


@pytest.mark.parametrize(
Expand Down