Skip to content

Commit

Permalink
state: Refactor compute_new_account_address()
Browse files Browse the repository at this point in the history
Refactor `compute_new_account_address()` to match Yellow Paper 𝐀𝐃𝐃𝐑.
This makes it a separate utility independent of `evmc_message`.
  • Loading branch information
chfast committed Feb 27, 2023
1 parent ca4c313 commit bd35f8f
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 59 deletions.
25 changes: 13 additions & 12 deletions test/state/host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,27 +110,26 @@ bool Host::selfdestruct(const address& addr, const address& beneficiary) noexcep
return !std::exchange(acc.destructed, true);
}

address compute_new_account_address(const evmc_message& msg, uint64_t sender_nonce) noexcept
address compute_new_account_address(const address& sender, uint64_t sender_nonce,
const std::optional<bytes32>& salt, bytes_view init_code) noexcept
{
hash256 addr_base_hash;
if (msg.kind == EVMC_CREATE)
if (!salt.has_value()) // CREATE
{
// TODO: Compute CREATE address without using RLP library.
const auto rlp_list = rlp::encode_tuple(address{msg.sender}, sender_nonce);
const auto rlp_list = rlp::encode_tuple(sender, sender_nonce);
addr_base_hash = keccak256(rlp_list);
}
else
else // CREATE2
{
assert(msg.kind == EVMC_CREATE2);
const auto init_code_hash = keccak256({msg.input_data, msg.input_size});
uint8_t buffer[1 + sizeof(msg.sender) + sizeof(msg.create2_salt) + sizeof(init_code_hash)];
const auto init_code_hash = keccak256(init_code);
uint8_t buffer[1 + sizeof(sender) + sizeof(*salt) + sizeof(init_code_hash)];
static_assert(std::size(buffer) == 85);
buffer[0] = 0xff;
std::copy_n(msg.sender.bytes, sizeof(msg.sender), &buffer[1]);
std::copy_n(
msg.create2_salt.bytes, sizeof(msg.create2_salt), &buffer[1 + sizeof(msg.sender)]);
std::copy_n(sender.bytes, sizeof(sender), &buffer[1]);
std::copy_n(salt->bytes, sizeof(salt->bytes), &buffer[1 + sizeof(sender)]);
std::copy_n(init_code_hash.bytes, sizeof(init_code_hash),
&buffer[1 + sizeof(msg.sender) + sizeof(msg.create2_salt)]);
&buffer[1 + sizeof(sender) + sizeof(salt->bytes)]);
addr_base_hash = keccak256({buffer, std::size(buffer)});
}
evmc_address new_addr{};
Expand All @@ -156,7 +155,9 @@ std::optional<evmc_message> Host::prepare_message(evmc_message msg)
// Compute and fill create address.
assert(msg.recipient == address{});
assert(msg.code_address == address{});
msg.recipient = compute_new_account_address(msg, sender_nonce);
msg.recipient = compute_new_account_address(msg.sender, sender_nonce,
(msg.kind == EVMC_CREATE2) ? std::optional{msg.create2_salt} : std::nullopt,
{msg.input_data, msg.input_size});

// By EIP-2929, the access to new created address is never reverted.
access_account(msg.recipient);
Expand Down
11 changes: 9 additions & 2 deletions test/state/host.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,15 @@ inline constexpr size_t max_initcode_size = 2 * max_code_size;
/// Computes the address of to-be-created contract.
///
/// Computes the new account address for the contract creation context
/// as defined by `ADDR()` in Yellow Paper, 7. Contract Creation, (86).
address compute_new_account_address(const evmc_message& msg, uint64_t sender_nonce) noexcept;
/// as defined by 𝐀𝐃𝐃𝐑 in Yellow Paper, 7. Contract Creation, (86).
///
/// @param sender The address of the message sender. YP: 𝑠.
/// @param sender_nonce The sender's nonce before the increase. YP: 𝑛.
/// @param salt The salt for CREATE2. If null, CREATE address is computed. YP: ΞΆ.
/// @param init_code The contract creation init code. Value only affects CREATE2. YP: 𝐒.
/// @return The computed address for CREATE or CREATE2 scheme.
address compute_new_account_address(const address& sender, uint64_t sender_nonce,
const std::optional<bytes32>& salt, bytes_view init_code) noexcept;

class Host : public evmc::Host
{
Expand Down
69 changes: 24 additions & 45 deletions test/unittests/state_new_account_address_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,63 +18,42 @@ inline constexpr bytes32 salts[] = {

TEST(state_new_account_address, create)
{
evmc_message msg{};
msg.kind = EVMC_CREATE;

for (const auto& ic : init_codes) // Init-code doesn't affect CREATE.
{
msg.input_data = ic.data();
msg.input_size = ic.size();

msg.sender = senders[0];
EXPECT_EQ(addr(msg, nonces[0]), 0xbd770416a3345f91e4b34576cb804a576fa48eb1_address);
EXPECT_EQ(addr(msg, nonces[3]), 0x1262d73ea59d3a661bf8751d16cf1a5377149e75_address);

msg.sender = senders[1];
EXPECT_EQ(addr(msg, nonces[0]), 0x522b3294e6d06aa25ad0f1b8891242e335d3b459_address);
EXPECT_EQ(addr(msg, nonces[1]), 0x535b3d7a252fa034ed71f0c53ec0c6f784cb64e1_address);
EXPECT_EQ(addr(msg, nonces[2]), 0x09c1ef8f55c61b94e8b92a55d0891d408a991e18_address);
EXPECT_EQ(addr(msg, nonces[3]), 0x001567239734aeadea21023c2a7c0d9bb9ae4af9_address);

msg.sender = senders[2];
EXPECT_EQ(addr(msg, nonces[0]), 0x3cb1045aee4a06f522ea2b69e4f3d21ed3c135d1_address);
EXPECT_EQ(addr(msg, nonces[3]), 0xe1aa03e4a7b6991d69aff8ece53ceafdf347082e_address);

msg.sender = 0xb20a608c624Ca5003905aA834De7156C68b2E1d0_address;
const auto beacon_deposit_address = addr(msg, 0);
auto s = senders[0];
EXPECT_EQ(addr(s, nonces[0], {}, ic), 0xbd770416a3345f91e4b34576cb804a576fa48eb1_address);
EXPECT_EQ(addr(s, nonces[3], {}, ic), 0x1262d73ea59d3a661bf8751d16cf1a5377149e75_address);

s = senders[1];
EXPECT_EQ(addr(s, nonces[0], {}, ic), 0x522b3294e6d06aa25ad0f1b8891242e335d3b459_address);
EXPECT_EQ(addr(s, nonces[1], {}, ic), 0x535b3d7a252fa034ed71f0c53ec0c6f784cb64e1_address);
EXPECT_EQ(addr(s, nonces[2], {}, ic), 0x09c1ef8f55c61b94e8b92a55d0891d408a991e18_address);
EXPECT_EQ(addr(s, nonces[3], {}, ic), 0x001567239734aeadea21023c2a7c0d9bb9ae4af9_address);

s = senders[2];
EXPECT_EQ(addr(s, nonces[0], {}, ic), 0x3cb1045aee4a06f522ea2b69e4f3d21ed3c135d1_address);
EXPECT_EQ(addr(s, nonces[3], {}, ic), 0xe1aa03e4a7b6991d69aff8ece53ceafdf347082e_address);

const auto beacon_deposit_address =
addr(0xb20a608c624Ca5003905aA834De7156C68b2E1d0_address, 0, {}, ic);
EXPECT_EQ(beacon_deposit_address, 0x00000000219ab540356cbb839cbe05303d7705fa_address);
}
}

TEST(state_new_account_address, create2)
{
evmc_message msg{};
msg.kind = EVMC_CREATE2;

for (const auto n : nonces) // Nonce doesn't affect CREATE2.
{
msg.sender = senders[0];
msg.input_data = init_codes[0].data();
msg.input_size = init_codes[0].size();
msg.create2_salt = salts[0];
EXPECT_EQ(addr(msg, n), 0xe33c0c7f7df4809055c3eba6c09cfe4baf1bd9e0_address);
EXPECT_EQ(addr(senders[0], n, salts[0], init_codes[0]),
0xe33c0c7f7df4809055c3eba6c09cfe4baf1bd9e0_address);

msg.sender = senders[2];
msg.input_data = init_codes[1].data();
msg.input_size = init_codes[1].size();
msg.create2_salt = salts[0];
EXPECT_EQ(addr(msg, n), 0x3517dea701ed18fc4a99dc111c5946e1f1541dad_address);
EXPECT_EQ(addr(senders[2], n, salts[0], init_codes[1]),
0x3517dea701ed18fc4a99dc111c5946e1f1541dad_address);

msg.sender = senders[1];
msg.input_data = init_codes[0].data();
msg.input_size = init_codes[0].size();
msg.create2_salt = salts[1];
EXPECT_EQ(addr(msg, n), 0x7be1c1cb3b8298f21c56add66defce03e2d32604_address);
EXPECT_EQ(addr(senders[1], n, salts[1], init_codes[0]),
0x7be1c1cb3b8298f21c56add66defce03e2d32604_address);

msg.sender = senders[2];
msg.input_data = init_codes[1].data();
msg.input_size = init_codes[1].size();
msg.create2_salt = salts[1];
EXPECT_EQ(addr(msg, n), 0x8f459e65c8f00a9c0c0493de7b0c61c3c27f7384_address);
EXPECT_EQ(addr(senders[2], n, salts[1], init_codes[1]),
0x8f459e65c8f00a9c0c0493de7b0c61c3c27f7384_address);
}
}

0 comments on commit bd35f8f

Please sign in to comment.