Skip to content
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
44 changes: 29 additions & 15 deletions test/statetest/statetest_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
#include "../utils/stdx/utility.hpp"
#include "../utils/utils.hpp"
#include "statetest.hpp"
#include <test/state/precompiles.hpp>

#include <evmone/delegation.hpp>
#include <evmone/eof.hpp>
#include <nlohmann/json.hpp>

Expand Down Expand Up @@ -496,23 +499,34 @@ void validate_state(const TestState& state, evmc_revision rev)
{
for (const auto& [addr, acc] : state)
{
// TODO: Check for empty accounts after Paris.
// https://github.com/ethereum/tests/issues/1331
if (is_eof_container(acc.code))
if (state::is_precompile(rev, addr) && !acc.code.empty())
throw std::invalid_argument("unexpected code at precompile address " + hex0x(addr));

const bool allowedEF = (rev >= EVMC_PRAGUE && is_code_delegated(acc.code)) ||
(rev >= EVMC_OSAKA && is_eof_container(acc.code)) ||
// exceptions to EIP-3541 rule existing on Mainnet
acc.code == "EF"_hex || acc.code == "EFF09f918bf09f9fa9"_hex;
if (rev >= EVMC_LONDON && !allowedEF && !acc.code.empty() && acc.code[0] == 0xEF)
throw std::invalid_argument("unexpected code starting with 0xEF at " + hex0x(addr));

if (rev >= EVMC_PARIS && acc.code.empty() && acc.balance == 0 && acc.nonce == 0 &&
!acc.storage.empty())
throw std::invalid_argument("empty account with non-empty storage at " + hex0x(addr));

if (rev >= EVMC_PRAGUE && is_code_delegated(acc.code) &&
acc.code.size() != std::size(DELEGATION_MAGIC) + sizeof(evmc::address))
{
if (rev >= EVMC_OSAKA)
{
if (const auto result = validate_eof(rev, ContainerKind::runtime, acc.code);
result != EOFValidationError::success)
{
throw std::invalid_argument(
"EOF container at " + hex0x(addr) +
" is invalid: " + std::string(get_error_message(result)));
}
}
else
throw std::invalid_argument(
"EIP-7702 delegation designator at " + hex0x(addr) + " has invalid size");
}

if (rev >= EVMC_OSAKA && is_eof_container(acc.code))
{
if (const auto result = validate_eof(rev, ContainerKind::runtime, acc.code);
result != EOFValidationError::success)
{
throw std::invalid_argument("unexpected code with EOF prefix at " + hex0x(addr));
throw std::invalid_argument("EOF container at " + hex0x(addr) + " is invalid: " +
std::string(get_error_message(result)));
}
}

Expand Down
4 changes: 4 additions & 0 deletions test/unittests/state_transition_create_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ TEST_F(state_transition, create_tx_collision)

TEST_F(state_transition, create_tx_collision_storage)
{
rev = EVMC_LONDON;

// Test create address collision with an account only having storage (EIP-7610).
const auto created = compute_create_address(Sender, pre[Sender].nonce);
pre[created] = {.storage = {{0x00_bytes32, 0x01_bytes32}}};
Expand All @@ -206,6 +208,8 @@ TEST_F(state_transition, create_collision)

TEST_F(state_transition, create_collision_storage)
{
rev = EVMC_LONDON;

// Test create address collision with an account only having storage (EIP-7610).
tx.to = To;
pre[To] = {.code = sstore(0, create())};
Expand Down
46 changes: 44 additions & 2 deletions test/unittests/statetest_loader_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,57 @@ TEST(statetest_loader, validate_state_unexpected_eof)
TestState state{{0xadd4_address, {.code = "EF00"_hex}}};
EXPECT_THAT([&] { validate_state(state, EVMC_CANCUN); },
ThrowsMessage<std::invalid_argument>(
"unexpected code with EOF prefix at 0x000000000000000000000000000000000000add4"));
"unexpected code starting with 0xEF at 0x000000000000000000000000000000000000add4"));
}

TEST(statetest_loader, validate_state_zero_storage_slot)
{
TestState state{{0xadd4_address, {.storage = {{0x01_bytes32, 0x00_bytes32}}}}};
EXPECT_THAT([&] { validate_state(state, EVMC_PRAGUE); },
EXPECT_THAT([&] { validate_state(state, EVMC_LONDON); },
ThrowsMessage<std::invalid_argument>(
"account 0x000000000000000000000000000000000000add4 contains invalid zero-value "
"storage entry "
"0x0000000000000000000000000000000000000000000000000000000000000001"));
}

TEST(statetest_loader, validate_state_unexpected_ef_prefix)
{
TestState state{{0xadd4_address, {.code = "EF00"_hex}}};
EXPECT_THAT([&] { validate_state(state, EVMC_LONDON); },
ThrowsMessage<std::invalid_argument>(
"unexpected code starting with 0xEF at 0x000000000000000000000000000000000000add4"));
}

TEST(statetest_loader, validate_state_invalid_delegation_size)
{
TestState state{{0xadd4_address, {.code = "EF010000"_hex}}};
EXPECT_THAT([&] { validate_state(state, EVMC_PRAGUE); },
ThrowsMessage<std::invalid_argument>(
"EIP-7702 delegation designator at 0x000000000000000000000000000000000000add4 has "
"invalid size"));
}

TEST(statetest_loader, validate_state_unexpected_delegation)
{
TestState state{
{0xadd4_address, {.code = "EF01000000000000000000000000000000000000000001"_hex}}};
EXPECT_THAT([&] { validate_state(state, EVMC_CANCUN); },
ThrowsMessage<std::invalid_argument>(
"unexpected code starting with 0xEF at 0x000000000000000000000000000000000000add4"));
}

TEST(statetest_loader, validate_empty_account_with_storage)
{
TestState state{{0xadd4_address, {.storage = {{0x01_bytes32, 0x01_bytes32}}}}};
EXPECT_THAT([&] { validate_state(state, EVMC_CANCUN); },
ThrowsMessage<std::invalid_argument>(
"empty account with non-empty storage at 0x000000000000000000000000000000000000add4"));
}

TEST(statetest_loader, validate_code_at_precompile_address)
{
TestState state{{0x0a_address, {.code = "00"_hex}}};
EXPECT_THAT([&] { validate_state(state, EVMC_CANCUN); },
ThrowsMessage<std::invalid_argument>(
"unexpected code at precompile address 0x000000000000000000000000000000000000000a"));
}