Skip to content

Commit

Permalink
Merge pull request #575 from ethereum/new_account_address
Browse files Browse the repository at this point in the history
state: Refactor `compute_new_account_address()`
  • Loading branch information
chfast authored Feb 27, 2023
2 parents bce22af + bd35f8f commit 34c65c5
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 12 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);
}

static address compute_new_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_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
13 changes: 13 additions & 0 deletions test/state/host.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@ using evmc::uint256be;
inline constexpr size_t max_code_size = 0x6000;
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 𝐀𝐃𝐃𝐑 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
{
evmc_revision m_rev;
Expand Down
1 change: 1 addition & 0 deletions test/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ add_executable(evmone-unittests
state_bloom_filter_test.cpp
state_mpt_hash_test.cpp
state_mpt_test.cpp
state_new_account_address_test.cpp
state_rlp_test.cpp
statetest_loader_test.cpp
statetest_loader_tx_test.cpp
Expand Down
59 changes: 59 additions & 0 deletions test/unittests/state_new_account_address_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// evmone: Fast Ethereum Virtual Machine implementation
// Copyright 2023 The evmone Authors.
// SPDX-License-Identifier: Apache-2.0

#include <gtest/gtest.h>
#include <test/state/host.hpp>

using namespace evmc;
using namespace evmc::literals;
inline constexpr auto addr = evmone::state::compute_new_account_address;

inline constexpr uint64_t nonces[] = {0, 1, 0x80, 0xffffffffffffffff};
inline constexpr address senders[] = {
0x00_address, 0x01_address, 0x8000000000000000000000000000000000000000_address};
inline const bytes init_codes[] = {bytes{}, bytes{0xFE}};
inline constexpr bytes32 salts[] = {
0x00_bytes32, 0xe75fb554e433e03763a1560646ee22dcb74e5274b34c5ad644e7c0f619a7e1d0_bytes32};

TEST(state_new_account_address, create)
{
for (const auto& ic : init_codes) // Init-code doesn't affect CREATE.
{
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)
{
for (const auto n : nonces) // Nonce doesn't affect CREATE2.
{
EXPECT_EQ(addr(senders[0], n, salts[0], init_codes[0]),
0xe33c0c7f7df4809055c3eba6c09cfe4baf1bd9e0_address);

EXPECT_EQ(addr(senders[2], n, salts[0], init_codes[1]),
0x3517dea701ed18fc4a99dc111c5946e1f1541dad_address);

EXPECT_EQ(addr(senders[1], n, salts[1], init_codes[0]),
0x7be1c1cb3b8298f21c56add66defce03e2d32604_address);

EXPECT_EQ(addr(senders[2], n, salts[1], init_codes[1]),
0x8f459e65c8f00a9c0c0493de7b0c61c3c27f7384_address);
}
}

0 comments on commit 34c65c5

Please sign in to comment.