Skip to content

Commit 34c65c5

Browse files
authored
Merge pull request #575 from ethereum/new_account_address
state: Refactor `compute_new_account_address()`
2 parents bce22af + bd35f8f commit 34c65c5

File tree

4 files changed

+86
-12
lines changed

4 files changed

+86
-12
lines changed

test/state/host.cpp

+13-12
Original file line numberDiff line numberDiff line change
@@ -110,27 +110,26 @@ bool Host::selfdestruct(const address& addr, const address& beneficiary) noexcep
110110
return !std::exchange(acc.destructed, true);
111111
}
112112

113-
static address compute_new_address(const evmc_message& msg, uint64_t sender_nonce) noexcept
113+
address compute_new_account_address(const address& sender, uint64_t sender_nonce,
114+
const std::optional<bytes32>& salt, bytes_view init_code) noexcept
114115
{
115116
hash256 addr_base_hash;
116-
if (msg.kind == EVMC_CREATE)
117+
if (!salt.has_value()) // CREATE
117118
{
118119
// TODO: Compute CREATE address without using RLP library.
119-
const auto rlp_list = rlp::encode_tuple(address{msg.sender}, sender_nonce);
120+
const auto rlp_list = rlp::encode_tuple(sender, sender_nonce);
120121
addr_base_hash = keccak256(rlp_list);
121122
}
122-
else
123+
else // CREATE2
123124
{
124-
assert(msg.kind == EVMC_CREATE2);
125-
const auto init_code_hash = keccak256({msg.input_data, msg.input_size});
126-
uint8_t buffer[1 + sizeof(msg.sender) + sizeof(msg.create2_salt) + sizeof(init_code_hash)];
125+
const auto init_code_hash = keccak256(init_code);
126+
uint8_t buffer[1 + sizeof(sender) + sizeof(*salt) + sizeof(init_code_hash)];
127127
static_assert(std::size(buffer) == 85);
128128
buffer[0] = 0xff;
129-
std::copy_n(msg.sender.bytes, sizeof(msg.sender), &buffer[1]);
130-
std::copy_n(
131-
msg.create2_salt.bytes, sizeof(msg.create2_salt), &buffer[1 + sizeof(msg.sender)]);
129+
std::copy_n(sender.bytes, sizeof(sender), &buffer[1]);
130+
std::copy_n(salt->bytes, sizeof(salt->bytes), &buffer[1 + sizeof(sender)]);
132131
std::copy_n(init_code_hash.bytes, sizeof(init_code_hash),
133-
&buffer[1 + sizeof(msg.sender) + sizeof(msg.create2_salt)]);
132+
&buffer[1 + sizeof(sender) + sizeof(salt->bytes)]);
134133
addr_base_hash = keccak256({buffer, std::size(buffer)});
135134
}
136135
evmc_address new_addr{};
@@ -156,7 +155,9 @@ std::optional<evmc_message> Host::prepare_message(evmc_message msg)
156155
// Compute and fill create address.
157156
assert(msg.recipient == address{});
158157
assert(msg.code_address == address{});
159-
msg.recipient = compute_new_address(msg, sender_nonce);
158+
msg.recipient = compute_new_account_address(msg.sender, sender_nonce,
159+
(msg.kind == EVMC_CREATE2) ? std::optional{msg.create2_salt} : std::nullopt,
160+
{msg.input_data, msg.input_size});
160161

161162
// By EIP-2929, the access to new created address is never reverted.
162163
access_account(msg.recipient);

test/state/host.hpp

+13
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@ using evmc::uint256be;
1515
inline constexpr size_t max_code_size = 0x6000;
1616
inline constexpr size_t max_initcode_size = 2 * max_code_size;
1717

18+
/// Computes the address of to-be-created contract.
19+
///
20+
/// Computes the new account address for the contract creation context
21+
/// as defined by 𝐀𝐃𝐃𝐑 in Yellow Paper, 7. Contract Creation, (86).
22+
///
23+
/// @param sender The address of the message sender. YP: 𝑠.
24+
/// @param sender_nonce The sender's nonce before the increase. YP: 𝑛.
25+
/// @param salt The salt for CREATE2. If null, CREATE address is computed. YP: ζ.
26+
/// @param init_code The contract creation init code. Value only affects CREATE2. YP: 𝐢.
27+
/// @return The computed address for CREATE or CREATE2 scheme.
28+
address compute_new_account_address(const address& sender, uint64_t sender_nonce,
29+
const std::optional<bytes32>& salt, bytes_view init_code) noexcept;
30+
1831
class Host : public evmc::Host
1932
{
2033
evmc_revision m_rev;

test/unittests/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ add_executable(evmone-unittests
3030
state_bloom_filter_test.cpp
3131
state_mpt_hash_test.cpp
3232
state_mpt_test.cpp
33+
state_new_account_address_test.cpp
3334
state_rlp_test.cpp
3435
statetest_loader_test.cpp
3536
statetest_loader_tx_test.cpp
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// evmone: Fast Ethereum Virtual Machine implementation
2+
// Copyright 2023 The evmone Authors.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
#include <gtest/gtest.h>
6+
#include <test/state/host.hpp>
7+
8+
using namespace evmc;
9+
using namespace evmc::literals;
10+
inline constexpr auto addr = evmone::state::compute_new_account_address;
11+
12+
inline constexpr uint64_t nonces[] = {0, 1, 0x80, 0xffffffffffffffff};
13+
inline constexpr address senders[] = {
14+
0x00_address, 0x01_address, 0x8000000000000000000000000000000000000000_address};
15+
inline const bytes init_codes[] = {bytes{}, bytes{0xFE}};
16+
inline constexpr bytes32 salts[] = {
17+
0x00_bytes32, 0xe75fb554e433e03763a1560646ee22dcb74e5274b34c5ad644e7c0f619a7e1d0_bytes32};
18+
19+
TEST(state_new_account_address, create)
20+
{
21+
for (const auto& ic : init_codes) // Init-code doesn't affect CREATE.
22+
{
23+
auto s = senders[0];
24+
EXPECT_EQ(addr(s, nonces[0], {}, ic), 0xbd770416a3345f91e4b34576cb804a576fa48eb1_address);
25+
EXPECT_EQ(addr(s, nonces[3], {}, ic), 0x1262d73ea59d3a661bf8751d16cf1a5377149e75_address);
26+
27+
s = senders[1];
28+
EXPECT_EQ(addr(s, nonces[0], {}, ic), 0x522b3294e6d06aa25ad0f1b8891242e335d3b459_address);
29+
EXPECT_EQ(addr(s, nonces[1], {}, ic), 0x535b3d7a252fa034ed71f0c53ec0c6f784cb64e1_address);
30+
EXPECT_EQ(addr(s, nonces[2], {}, ic), 0x09c1ef8f55c61b94e8b92a55d0891d408a991e18_address);
31+
EXPECT_EQ(addr(s, nonces[3], {}, ic), 0x001567239734aeadea21023c2a7c0d9bb9ae4af9_address);
32+
33+
s = senders[2];
34+
EXPECT_EQ(addr(s, nonces[0], {}, ic), 0x3cb1045aee4a06f522ea2b69e4f3d21ed3c135d1_address);
35+
EXPECT_EQ(addr(s, nonces[3], {}, ic), 0xe1aa03e4a7b6991d69aff8ece53ceafdf347082e_address);
36+
37+
const auto beacon_deposit_address =
38+
addr(0xb20a608c624Ca5003905aA834De7156C68b2E1d0_address, 0, {}, ic);
39+
EXPECT_EQ(beacon_deposit_address, 0x00000000219ab540356cbb839cbe05303d7705fa_address);
40+
}
41+
}
42+
43+
TEST(state_new_account_address, create2)
44+
{
45+
for (const auto n : nonces) // Nonce doesn't affect CREATE2.
46+
{
47+
EXPECT_EQ(addr(senders[0], n, salts[0], init_codes[0]),
48+
0xe33c0c7f7df4809055c3eba6c09cfe4baf1bd9e0_address);
49+
50+
EXPECT_EQ(addr(senders[2], n, salts[0], init_codes[1]),
51+
0x3517dea701ed18fc4a99dc111c5946e1f1541dad_address);
52+
53+
EXPECT_EQ(addr(senders[1], n, salts[1], init_codes[0]),
54+
0x7be1c1cb3b8298f21c56add66defce03e2d32604_address);
55+
56+
EXPECT_EQ(addr(senders[2], n, salts[1], init_codes[1]),
57+
0x8f459e65c8f00a9c0c0493de7b0c61c3c27f7384_address);
58+
}
59+
}

0 commit comments

Comments
 (0)