Skip to content

Commit

Permalink
test: New State transition tests
Browse files Browse the repository at this point in the history
New tests for:
- contract creation,
- account touches,
- empty coinbase,
- selfdestruct,
- extcode.
  • Loading branch information
chfast committed Mar 13, 2024
1 parent c65d75e commit b951b55
Show file tree
Hide file tree
Showing 6 changed files with 440 additions and 0 deletions.
2 changes: 2 additions & 0 deletions test/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,12 @@ target_sources(
state_transition.hpp
state_transition.cpp
state_transition_block_test.cpp
state_transition_call_test.cpp
state_transition_create_test.cpp
state_transition_eof_test.cpp
state_transition_extcode_test.cpp
state_transition_selfdestruct_test.cpp
state_transition_touch_test.cpp
state_transition_trace_test.cpp
state_transition_transient_storage_test.cpp
state_transition_tx_test.cpp
Expand Down
21 changes: 21 additions & 0 deletions test/unittests/state_transition_call_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// evmone: Fast Ethereum Virtual Machine implementation
// Copyright 2024 The evmone Authors.
// SPDX-License-Identifier: Apache-2.0

#include "../utils/bytecode.hpp"
#include "state_transition.hpp"

using namespace evmc::literals;
using namespace evmone::test;

TEST_F(state_transition, call_value_to_empty)
{
rev = EVMC_LONDON;
static constexpr auto BENEFICIARY = 0xbe_address;
tx.to = To;
pre.insert(*tx.to, {.balance = 1, .code = call(BENEFICIARY).value(1)});
pre.insert(BENEFICIARY, {});

expect.post[To].balance = 0;
expect.post[BENEFICIARY].balance = 1;
}
171 changes: 171 additions & 0 deletions test/unittests/state_transition_create_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ TEST_F(state_transition, create_tx)
expect.post[create_address].code = bytes{0xFE};
}

TEST_F(state_transition, create_tx_failure)
{
static constexpr auto create_address = 0x3442a1dec1e72f337007125aa67221498cdd759d_address;

tx.data = bytecode{} + OP_INVALID;

expect.status = EVMC_INVALID_INSTRUCTION;
expect.post[create_address].exists = false;
}

TEST_F(state_transition, create2_max_nonce)
{
tx.to = To;
Expand Down Expand Up @@ -155,3 +165,164 @@ TEST_F(state_transition, code_deployment_out_of_gas_refund_f)
expect.post[To].storage[0x00_bytes32] = to_bytes32(created);
expect.gas_used = 83140;
}

TEST_F(state_transition, create_tx_collision)
{
static constexpr auto CREATED = 0x3442a1dec1e72f337007125aa67221498cdd759d_address;

pre.insert(CREATED, {.nonce = 2});

expect.status = EVMC_FAILURE;
expect.post[CREATED].nonce = 2;
}

TEST_F(state_transition, create_collision)
{
static constexpr auto CREATED = 0x8bbc3514477d75ec797bbe4e19d7961660bb849c_address;

tx.to = To;
pre.insert(*tx.to, {.code = create()});
pre.insert(CREATED, {.nonce = 2});

expect.post[*tx.to].nonce = pre.get(*tx.to).nonce + 1;
expect.post[CREATED].nonce = pre.get(CREATED).nonce;
}

TEST_F(state_transition, create_collision_revert)
{
static constexpr auto CREATED = 0x8bbc3514477d75ec797bbe4e19d7961660bb849c_address;

tx.to = To;
pre.insert(*tx.to, {.code = create() + OP_INVALID});
pre.insert(CREATED, {.nonce = 2});

expect.status = EVMC_INVALID_INSTRUCTION;
expect.post[*tx.to].nonce = pre.get(*tx.to).nonce;
expect.post[CREATED].nonce = pre.get(CREATED).nonce;
}

TEST_F(state_transition, create_prefunded_revert)
{
static constexpr auto CREATED = 0x8bbc3514477d75ec797bbe4e19d7961660bb849c_address;

tx.to = To;
pre.insert(*tx.to, {.code = create() + OP_INVALID});
pre.insert(CREATED, {.balance = 2});

expect.status = EVMC_INVALID_INSTRUCTION;
expect.post[*tx.to].nonce = pre.get(*tx.to).nonce;
expect.post[CREATED].nonce = pre.get(CREATED).nonce;
}

TEST_F(state_transition, create_revert)
{
static constexpr auto CREATED = 0x8bbc3514477d75ec797bbe4e19d7961660bb849c_address;

tx.to = To;
pre.insert(*tx.to, {.code = create() + OP_INVALID});

expect.status = EVMC_INVALID_INSTRUCTION;
expect.post[*tx.to].nonce = pre.get(*tx.to).nonce;
expect.post[CREATED].exists = false;
}

TEST_F(state_transition, create_revert_sd)
{
rev = EVMC_SPURIOUS_DRAGON;
block.base_fee = 0;
static constexpr auto CREATED = 0x8bbc3514477d75ec797bbe4e19d7961660bb849c_address;

tx.to = To;
pre.insert(*tx.to, {.code = create() + OP_INVALID});

expect.status = EVMC_INVALID_INSTRUCTION;
expect.post[*tx.to].nonce = pre.get(*tx.to).nonce;
expect.post[CREATED].exists = false;
}

TEST_F(state_transition, create_revert_tw)
{
rev = EVMC_TANGERINE_WHISTLE;
block.base_fee = 0;
static constexpr auto CREATED = 0x8bbc3514477d75ec797bbe4e19d7961660bb849c_address;

tx.to = To;
pre.insert(*tx.to, {.code = create() + OP_INVALID});

expect.status = EVMC_INVALID_INSTRUCTION;
expect.post[*tx.to].nonce = pre.get(*tx.to).nonce;
expect.post[CREATED].exists = false;
}

TEST_F(state_transition, create_collision_empty_revert)
{
static constexpr auto CREATED = 0x8bbc3514477d75ec797bbe4e19d7961660bb849c_address;

tx.to = To;
pre.insert(*tx.to, {.code = create() + OP_INVALID});
pre.insert(CREATED, {});

expect.status = EVMC_INVALID_INSTRUCTION;
expect.post[*tx.to].nonce = pre.get(*tx.to).nonce;
expect.post[CREATED].exists = true;
}

TEST_F(state_transition, create_collision_empty_revert_tw)
{
rev = EVMC_TANGERINE_WHISTLE;
block.base_fee = 0;
static constexpr auto CREATED = 0x8bbc3514477d75ec797bbe4e19d7961660bb849c_address;

tx.to = To;
pre.insert(*tx.to, {.code = create() + OP_INVALID});
pre.insert(CREATED, {});

expect.status = EVMC_INVALID_INSTRUCTION;
expect.post[*tx.to].nonce = pre.get(*tx.to).nonce;
expect.post[CREATED].exists = true;
}

TEST_F(state_transition, touch_create_collision_empty_revert)
{
static constexpr auto CREATED = 0x11f72042f0f1c9d8a1aeffc3680d0b41dd7769a7_address;
static constexpr auto REVERT_PROXY = 0x94_address;

tx.to = To;
pre.insert(*tx.to, {.code = call(CREATED) + call(REVERT_PROXY).gas(0xffff)});
pre.insert(REVERT_PROXY, {.code = create() + OP_INVALID});

expect.post[*tx.to].nonce = pre.get(*tx.to).nonce;
expect.post[CREATED].exists = false;
expect.post[REVERT_PROXY].exists = true;
}

TEST_F(state_transition, touch_create_collision_empty_revert_tw)
{
rev = EVMC_TANGERINE_WHISTLE;
block.base_fee = 0;
static constexpr auto CREATED = 0x11f72042f0f1c9d8a1aeffc3680d0b41dd7769a7_address;
static constexpr auto REVERT_PROXY = 0x94_address;

tx.to = To;
pre.insert(*tx.to, {.code = call(CREATED) + call(REVERT_PROXY).gas(0xffff)});
pre.insert(REVERT_PROXY, {.code = create() + OP_INVALID});

expect.post[*tx.to].nonce = pre.get(*tx.to).nonce;
expect.post[CREATED].exists = true;
expect.post[REVERT_PROXY].exists = true;
}

TEST_F(state_transition, created_code_hash)
{
const auto runtime_code = bytes{0xc0};
ASSERT_EQ(runtime_code.size(), 1);
const auto initcode = mstore8(0, push(runtime_code)) + ret(0, runtime_code.size());
tx.to = To;
pre.insert(To,
{.code = mstore(0, push(initcode)) + create().input(32 - initcode.size(), initcode.size()) +
sstore(0, bytecode{OP_EXTCODEHASH})});

const auto created = compute_create_address(To, pre.get(To).nonce);
expect.post[created].code = runtime_code;
expect.post[To].storage[0x00_bytes32] = keccak256(runtime_code);
}
28 changes: 28 additions & 0 deletions test/unittests/state_transition_extcode_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,34 @@
using namespace evmc::literals;
using namespace evmone::test;

TEST_F(state_transition, extcodehash_existent)
{
rev = EVMC_ISTANBUL; // before account access
block.base_fee = 0;

static constexpr auto EXT = 0xe4_address;
tx.to = To;
pre.insert(To, {.code = sstore(0, push(EXT) + OP_EXTCODEHASH)});
pre.insert(EXT, {.code = bytecode{"1234"}});

expect.post[EXT].exists = true;
expect.post[To].storage[0x00_bytes32] = keccak256(pre.get(EXT).code);
}

TEST_F(state_transition, extcodesize_existent)
{
rev = EVMC_ISTANBUL; // before account access
block.base_fee = 0;

static constexpr auto EXT = 0xe4_address;
tx.to = To;
pre.insert(To, {.code = sstore(0, push(EXT) + OP_EXTCODESIZE)});
pre.insert(EXT, {.code = bytes(3, 0)});

expect.post[EXT].exists = true;
expect.post[To].storage[0x00_bytes32] = 0x03_bytes32;
}

constexpr auto target = 0xfffffffffffffffffffffffffffffffffffffffe_address;

TEST_F(state_transition, legacy_extcodesize_eof)
Expand Down
5 changes: 5 additions & 0 deletions test/unittests/state_transition_selfdestruct_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ TEST_F(state_transition, selfdestruct_double_revert)
expect.post[BENEFICIARY].balance = 1;
}

TEST_F(state_transition, selfdestruct_initcode)
{
tx.data = selfdestruct(0xbe_address);
}

TEST_F(state_transition, massdestruct_shanghai)
{
rev = EVMC_SHANGHAI;
Expand Down
Loading

0 comments on commit b951b55

Please sign in to comment.