Skip to content

Commit

Permalink
Refactor Host::execute_message() to allow CALLs with recipient != cod…
Browse files Browse the repository at this point in the history
…e_address (#1008)

This is needed to prepare for EIP-7702
#961

The main goal is to get rid of assertion that requires `recipient ==
code_address` in case `kind == EVMC_CALL`. (In 7702 world CALL can have
`code_address` pointing to a different (delegate) address.)

The idea is to split a variable `dst_acc` that was containing either
`recepient` or `code_address` account into two separate variables for
each thing.
  • Loading branch information
gumb0 committed Sep 17, 2024
2 parents 01eca77 + 7406bac commit 335d056
Showing 1 changed file with 22 additions and 14 deletions.
36 changes: 22 additions & 14 deletions test/state/host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,26 +376,34 @@ evmc::Result Host::execute_message(const evmc_message& msg) noexcept
m_state.journal_create(msg.recipient, exists);
}

assert(msg.kind != EVMC_CALL || evmc::address{msg.recipient} == msg.code_address);
auto* const dst_acc =
(msg.kind == EVMC_CALL) ? &m_state.touch(msg.recipient) : m_state.find(msg.code_address);

if (msg.kind == EVMC_CALL && !evmc::is_zero(msg.value))
if (msg.kind == EVMC_CALL)
{
// Transfer value: sender → recipient.
// The sender's balance is already checked therefore the sender account must exist.
const auto value = intx::be::load<intx::uint256>(msg.value);
assert(m_state.get(msg.sender).balance >= value);
m_state.journal_balance_change(msg.sender, m_state.get(msg.sender).balance);
m_state.journal_balance_change(msg.recipient, dst_acc->balance);
m_state.get(msg.sender).balance -= value;
dst_acc->balance += value;
if (evmc::is_zero(msg.value))
m_state.touch(msg.recipient);
else
{
// We skip touching if we send value, because account cannot end up empty.
// It will either have value, or code that transfers this value out, or will be
// selfdestructed anyway.
auto& dst_acc = m_state.get_or_insert(msg.recipient);

// Transfer value: sender → recipient.
// The sender's balance is already checked therefore the sender account must exist.
const auto value = intx::be::load<intx::uint256>(msg.value);
assert(m_state.get(msg.sender).balance >= value);
m_state.journal_balance_change(msg.sender, m_state.get(msg.sender).balance);
m_state.journal_balance_change(msg.recipient, dst_acc.balance);
m_state.get(msg.sender).balance -= value;
dst_acc.balance += value;
}
}

if (is_precompile(m_rev, msg.code_address))
return call_precompile(m_rev, msg);

const auto code = dst_acc != nullptr ? bytes_view{dst_acc->code} : bytes_view{};
// In case msg.recipient == msg.code_address, this is the second lookup of the same address.
const auto* const code_acc = m_state.find(msg.code_address);
const auto code = code_acc != nullptr ? bytes_view{code_acc->code} : bytes_view{};
return m_vm.execute(*this, m_rev, msg, code.data(), code.size());
}

Expand Down

0 comments on commit 335d056

Please sign in to comment.