Skip to content

Commit

Permalink
Add test for new EXTCODE* behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
pdobacz committed Feb 7, 2024
1 parent 586fed1 commit 80b11d7
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 5 deletions.
10 changes: 5 additions & 5 deletions test/state/host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,30 +82,30 @@ namespace
/// For EXTCODE* instructions if the target is an EOF account, then only return EF00.
/// While we only do this if the caller is legacy, it is not a problem doing this
/// unconditionally, because EOF contracts dot no have EXTCODE* instructions.
bytes_view extcode(bytes_view code) noexcept
bytes_view extcode(bytes_view code, evmc_revision rev) noexcept
{
return is_eof_container(code) ? code.substr(0, 2) : code;
return (rev >= EVMC_PRAGUE && is_eof_container(code)) ? code.substr(0, 2) : code;
}
} // namespace

size_t Host::get_code_size(const address& addr) const noexcept
{
const auto* const acc = m_state.find(addr);
return (acc != nullptr) ? extcode(acc->code).size() : 0;
return (acc != nullptr) ? extcode(acc->code, m_rev).size() : 0;
}

bytes32 Host::get_code_hash(const address& addr) const noexcept
{
// TODO: Cache code hash. It will be needed also to compute the MPT hash.
const auto* const acc = m_state.find(addr);
return (acc != nullptr && !acc->is_empty()) ? keccak256(extcode(acc->code)) : bytes32{};
return (acc != nullptr && !acc->is_empty()) ? keccak256(extcode(acc->code, m_rev)) : bytes32{};
}

size_t Host::copy_code(const address& addr, size_t code_offset, uint8_t* buffer_data,
size_t buffer_size) const noexcept
{
const auto* const acc = m_state.find(addr);
const auto code = (acc != nullptr) ? extcode(acc->code) : bytes_view{};
const auto code = (acc != nullptr) ? extcode(acc->code, m_rev) : bytes_view{};
const auto code_slice = code.substr(std::min(code_offset, code.size()));
const auto num_bytes = std::min(buffer_size, code_slice.size());
std::copy_n(code_slice.begin(), num_bytes, buffer_data);
Expand Down
1 change: 1 addition & 0 deletions test/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ target_sources(
state_transition_block_test.cpp
state_transition_create_test.cpp
state_transition_eof_test.cpp
state_transition_extcode_test.cpp
state_transition_selfdestruct_test.cpp
state_transition_trace_test.cpp
state_transition_transient_storage_test.cpp
Expand Down
94 changes: 94 additions & 0 deletions test/unittests/state_transition_extcode_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// evmone: Fast Ethereum Virtual Machine implementation
// Copyright 2023 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;

constexpr auto target = 0xfffffffffffffffffffffffffffffffffffffffe_address;
constexpr auto ones = 0x1111111111111111111111111111111111111111111111111111111111111111_bytes32;

TEST_F(state_transition, legacy_extcodesize_eof_cancun)
{
pre.insert(target, {.code = eof_bytecode("FE")});

rev = EVMC_CANCUN;
tx.to = To;
pre.insert(*tx.to, {
.code = bytecode(push(target) + sstore(1, OP_EXTCODESIZE)),
});
expect.post[*tx.to].storage[0x01_bytes32] = 0x14_bytes32;
expect.post[target].exists = true;
}

TEST_F(state_transition, legacy_extcodesize_eof)
{
pre.insert(target, {.code = eof_bytecode("FE")});

rev = EVMC_PRAGUE;
tx.to = To;
pre.insert(*tx.to, {
.code = bytecode(push(target) + sstore(1, OP_EXTCODESIZE)),
});
expect.post[*tx.to].storage[0x01_bytes32] = 0x02_bytes32;
expect.post[target].exists = true;
}

TEST_F(state_transition, legacy_extcodehash_eof_cancun)
{
pre.insert(target, {.code = eof_bytecode("FE")});

rev = EVMC_CANCUN;
tx.to = To;
pre.insert(*tx.to, {
.code = bytecode(push(target) + sstore(1, OP_EXTCODEHASH)),
});
expect.post[*tx.to].storage[0x01_bytes32] = keccak256(bytecode(eof_bytecode("FE")));
expect.post[target].exists = true;
}

TEST_F(state_transition, legacy_extcodehash_eof)
{
pre.insert(target, {.code = eof_bytecode("FE")});

rev = EVMC_PRAGUE;
tx.to = To;
pre.insert(*tx.to, {
.code = bytecode(push(target) + sstore(1, OP_EXTCODEHASH)),
});
expect.post[*tx.to].storage[0x01_bytes32] = keccak256(bytecode("EF00"));
expect.post[target].exists = true;
}

TEST_F(state_transition, legacy_extcodecopy_eof_cancun)
{
pre.insert(target, {.code = eof_bytecode("FE")});

rev = EVMC_CANCUN;
tx.to = To;
pre.insert(*tx.to, {
.code = bytecode(mstore(0, ones) + push(20) + push0() + push0() +
push(target) + OP_EXTCODECOPY + sstore(1, mload(0))),
});
expect.post[*tx.to].storage[0x01_bytes32] =
0xef000101000402000100010400000000800000fe111111111111111111111111_bytes32;
expect.post[target].exists = true;
}

TEST_F(state_transition, legacy_extcodecopy_eof)
{
pre.insert(target, {.code = eof_bytecode("FE")});

rev = EVMC_PRAGUE;
tx.to = To;
pre.insert(*tx.to, {
.code = bytecode(mstore(0, ones) + push(20) + push0() + push0() +
push(target) + OP_EXTCODECOPY + sstore(1, mload(0))),
});
expect.post[*tx.to].storage[0x01_bytes32] =
0xef00000000000000000000000000000000000000111111111111111111111111_bytes32;
expect.post[target].exists = true;
}

0 comments on commit 80b11d7

Please sign in to comment.