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
2 changes: 1 addition & 1 deletion test/state/transaction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ struct Transaction
uint64_t nonce = 0;
intx::uint256 r;
intx::uint256 s;
uint8_t v = 0;
uint64_t v = 0;
AuthorizationList authorization_list;
};

Expand Down
26 changes: 26 additions & 0 deletions test/unittests/statetest_loader_tx_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,32 @@ TEST(statetest_loader, tx_max_chain_id)
EXPECT_EQ(tx.chain_id, std::numeric_limits<uint64_t>::max());
}

TEST(statetest_loader, tx_max_legacy_chain_id)
{
// A legacy EIP-155 transaction encodes the chain ID inside `v` as
// v = chain_id*2 + 35 + parity (parity in {0, 1}). Because `v` is loaded as uint64, the
// largest chain ID a legacy transaction can carry is the one whose `v` reaches uint64 max:
// chain_id = 0x7fffffffffffffee with parity 0 gives v = 0xffffffffffffffff. A larger chain ID
// would overflow `v`.
constexpr std::string_view input = R"({
"input": "b0b1",
"gas": "0x9091",
"chainId": "0x7fffffffffffffee",
"value": "0xe0e1",
"sender": "a0a1",
"gasPrice": "0x7071",
"nonce": "0",
"r": "0x1111111111111111111111111111111111111111111111111111111111111111",
"s": "0x2222222222222222222222222222222222222222222222222222222222222222",
"v": "0xffffffffffffffff"
})";

const auto tx = test::from_json<state::Transaction>(json::json::parse(input));
EXPECT_EQ(tx.chain_id, 0x7fffffffffffffee);
EXPECT_EQ(tx.v, std::numeric_limits<uint64_t>::max());
EXPECT_EQ(tx.v, tx.chain_id * 2 + 35); // EIP-155 with y-parity 0.
}

TEST(statetest_loader, tx_eip1559)
{
constexpr std::string_view input = R"({
Expand Down
39 changes: 39 additions & 0 deletions test/unittests/tooling_t8n_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,3 +248,42 @@ TEST(tooling_t8n, max_chain_id)
EXPECT_NO_THROW(tooling::t8n(vm, args));
EXPECT_THAT(out_result.str(), HasSubstr("\"transactionHash\""));
}

TEST(tooling_t8n, max_v)
{
evmc::VM vm{evmc_create_evmone()};

// Legacy EIP-155 `v` is chainId*2 + 35 + parity, exceeding 0xff for chainId > 110.
// The maximum `v` (uint64 max = 0xffffffffffffffff) must be parsed and executed without
// overflow; regression test for `v` being loaded as `uint8_t`, which threw
// `from_json<uint8_t>: value > 0xFF`.
static constexpr auto TX_MAX_V = R"([{
"to": null,
"input": "0x60015ff3",
"gas": "0x186a0",
"nonce": "0x0",
"value": "0x0",
"gasPrice": "0x32",
"chainId": "0x1",
"sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"v": "0xffffffffffffffff",
"r": "0x468a915f087692bb9be503831a3dfef2cf9c8dee26deb40ff2ec99e8d22665ae",
"s": "0x5cedae0810c3851ecd1004bfdbfe6ddc7753c2d665993bb01ce75af7857b13dc"
}])";

std::istringstream env{ENV_JSON};
std::istringstream alloc{ALLOC_JSON};
std::istringstream txs{TX_MAX_V};
std::ostringstream out_result;

tooling::T8NArgs args;
args.rev = EVMC_SHANGHAI;
args.chain_id = 1;
args.alloc = &alloc;
args.env = &env;
args.txs = &txs;
args.out_result = &out_result;

EXPECT_NO_THROW(tooling::t8n(vm, args));
EXPECT_THAT(out_result.str(), HasSubstr("\"transactionHash\""));
}
2 changes: 1 addition & 1 deletion test/utils/statetest_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ state::Transaction from_json<state::Transaction>(const json::json& j)
o.nonce = from_json<uint64_t>(j.at("nonce"));
o.r = from_json<intx::uint256>(j.at("r"));
o.s = from_json<intx::uint256>(j.at("s"));
o.v = from_json<uint8_t>(j.at("v"));
o.v = from_json<uint64_t>(j.at("v"));

return o;
}
Expand Down