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
3 changes: 3 additions & 0 deletions test/state/account.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ struct Account
/// The account has been created in the current transaction.
bool just_created = false;

// This account's code has been modified.
bool code_changed = false;

evmc_access_status access_status = EVMC_ACCESS_COLD;

[[nodiscard]] bool is_empty() const noexcept
Expand Down
34 changes: 19 additions & 15 deletions test/state/host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,26 +377,30 @@ evmc::Result Host::create(const evmc_message& msg) noexcept
evmc::Result{EVMC_FAILURE};
}

if (!code.empty() && code[0] == 0xEF)
if (!code.empty())
{
if (m_rev >= EVMC_OSAKA)
if (code[0] == 0xEF)
{
// Only EOFCREATE/EOF-creation-tx is allowed to deploy code starting with EF.
// It must be valid EOF, which was validated before execution.
if (msg.kind != EVMC_EOFCREATE)
if (m_rev >= EVMC_OSAKA)
{
// Only EOFCREATE/EOF-creation-tx is allowed to deploy code starting with EF.
// It must be valid EOF, which was validated before execution.
if (msg.kind != EVMC_EOFCREATE)
return evmc::Result{EVMC_CONTRACT_VALIDATION_FAILURE};
assert(validate_eof(m_rev, ContainerKind::runtime, code) ==
EOFValidationError::success);
}
else if (m_rev >= EVMC_LONDON)
{
// EIP-3541: Reject EF code.
return evmc::Result{EVMC_CONTRACT_VALIDATION_FAILURE};
assert(
validate_eof(m_rev, ContainerKind::runtime, code) == EOFValidationError::success);
}
else if (m_rev >= EVMC_LONDON)
{
// EIP-3541: Reject EF code.
return evmc::Result{EVMC_CONTRACT_VALIDATION_FAILURE};
}
}
}

new_acc->code_hash = keccak256(code);
new_acc->code = code;
new_acc->code_hash = keccak256(code);
new_acc->code = code;
new_acc->code_changed = true;
}

return evmc::Result{result.status_code, gas_left, result.gas_refund, msg.recipient};
}
Expand Down
2 changes: 1 addition & 1 deletion test/state/state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ StateDiff State::build_diff(evmc_revision rev) const

// Output only the new code.
// TODO: Output also the code hash. It will be needed for DB update and MPT hash.
if (m.just_created && !m.code.empty())
if (m.code_changed)
a.code = m.code;

for (const auto& [k, v] : m.storage)
Expand Down
4 changes: 2 additions & 2 deletions test/state/state_diff.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ struct StateDiff
/// TODO: Currently it is not guaranteed the value is different from the initial one.
uint256 balance;

/// New account code. If empty, it means the code has not changed.
bytes code;
/// New or modified account code. If bytes are empty, it means the code has been cleared.
std::optional<bytes> code;

/// The list of the account's storage modifications: key => new value.
/// The value 0 means the storage entry is deleted.
Expand Down
4 changes: 2 additions & 2 deletions test/state/test_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ void TestState::apply(const state::StateDiff& diff)
auto& a = (*this)[m.addr];
a.nonce = m.nonce;
a.balance = m.balance;
if (!m.code.empty())
a.code = m.code; // TODO: Consider taking rvalue ref to avoid code copy.
if (m.code.has_value())
a.code = *m.code; // TODO: Consider taking rvalue ref to avoid code copy.
for (const auto& [k, v] : m.modified_storage)
{
if (v)
Expand Down