Skip to content
This repository was archived by the owner on Apr 8, 2026. It is now read-only.

Commit ecf6ae1

Browse files
committed
tools: Add --create option to evmc run
1 parent b92f6a4 commit ecf6ae1

File tree

5 files changed

+90
-10
lines changed

5 files changed

+90
-10
lines changed

test/tools/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,11 @@ add_evmc_tool_test(
3333
"Result: +success[\r\n]+Gas used: +7[\r\n]+Output: +aabbccdd00000000000000000000000000000000000000000000000000000000[\r\n]"
3434
)
3535

36+
add_evmc_tool_test(
37+
create_return_2
38+
"--vm $<TARGET_FILE:evmc::example-vm> run --create 6960026000526001601ff3600052600a6016f3"
39+
"Result: +success[\r\n]+Gas used: +6[\r\n]+Output: +02[\r\n]"
40+
)
41+
3642
get_property(TOOLS_TESTS DIRECTORY PROPERTY TESTS)
3743
set_tests_properties(${TOOLS_TESTS} PROPERTIES ENVIRONMENT LLVM_PROFILE_FILE=${CMAKE_BINARY_DIR}/tools-%p.profraw)

test/unittests/tool_commands_test.cpp

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ std::string out_pattern(const char* rev,
1515
int gas_limit,
1616
const char* status,
1717
int gas_used,
18-
const char* output = nullptr)
18+
const char* output = nullptr,
19+
bool create = false)
1920
{
2021
std::ostringstream s;
21-
s << "Executing on " << rev << " with " << gas_limit << " gas limit\n\n"
22+
s << (create ? "Creating and executing on " : "Executing on ") << rev << " with " << gas_limit
23+
<< " gas limit\n\n"
2224
<< "Result: " << status << "\nGas used: " << gas_used << "\n";
23-
if (output)
25+
if (output != nullptr)
2426
s << "Output: " << output << "\n";
2527
return s.str();
2628
}
@@ -31,7 +33,7 @@ TEST(tool_commands, run_empty_code)
3133
auto vm = evmc::VM{evmc_create_example_vm()};
3234
std::ostringstream out;
3335

34-
const auto exit_code = cmd::run(vm, EVMC_FRONTIER, 1, "", "", out);
36+
const auto exit_code = cmd::run(vm, EVMC_FRONTIER, 1, "", "", false, out);
3537
EXPECT_EQ(exit_code, 0);
3638
EXPECT_EQ(out.str(), out_pattern("Frontier", 1, "success", 0, ""));
3739
}
@@ -41,7 +43,7 @@ TEST(tool_commands, run_return_my_address)
4143
auto vm = evmc::VM{evmc_create_example_vm()};
4244
std::ostringstream out;
4345

44-
const auto exit_code = cmd::run(vm, EVMC_HOMESTEAD, 200, "30600052596000f3", "", out);
46+
const auto exit_code = cmd::run(vm, EVMC_HOMESTEAD, 200, "30600052596000f3", "", false, out);
4547
EXPECT_EQ(exit_code, 0);
4648
EXPECT_EQ(out.str(),
4749
out_pattern("Homestead", 200, "success", 6,
@@ -56,9 +58,38 @@ TEST(tool_commands, run_copy_input_to_output)
5658

5759
const auto exit_code =
5860
cmd::run(vm, EVMC_TANGERINE_WHISTLE, 200, "600035600052596000f3",
59-
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", out);
61+
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", false, out);
6062
EXPECT_EQ(exit_code, 0);
6163
EXPECT_EQ(out.str(),
6264
out_pattern("Tangerine Whistle", 200, "success", 7,
6365
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"));
6466
}
67+
68+
TEST(tool_commands, create_return_1)
69+
{
70+
// Contract: mstore(0, 1) return(31, 1)
71+
// Create: mstore(0, 0x60016000526001601ff3) return(22, 10)
72+
auto vm = evmc::VM{evmc_create_example_vm()};
73+
std::ostringstream out;
74+
75+
const auto exit_code = cmd::run(vm, EVMC_SPURIOUS_DRAGON, 200,
76+
"6960016000526001601ff3600052600a6016f3", "", true, out);
77+
EXPECT_EQ(exit_code, 0);
78+
EXPECT_EQ(out.str(), out_pattern("Spurious Dragon", 200, "success", 6, "01", true));
79+
}
80+
81+
TEST(tool_commands, create_copy_input_to_output)
82+
{
83+
// Contract: mstore(0, calldataload(0)) return(0, msize())
84+
// Create: mstore(0, 0x600035600052596000f3) return(22, 10)
85+
auto vm = evmc::VM{evmc_create_example_vm()};
86+
std::ostringstream out;
87+
88+
const auto exit_code = cmd::run(vm, EVMC_SPURIOUS_DRAGON, 200,
89+
"69600035600052596000f3600052600a6016f3", "0c49c4", true, out);
90+
EXPECT_EQ(exit_code, 0);
91+
EXPECT_EQ(
92+
out.str(),
93+
out_pattern("Spurious Dragon", 200, "success", 7,
94+
"0c49c40000000000000000000000000000000000000000000000000000000000", true));
95+
}

tools/commands/commands.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ int run(evmc::VM& vm,
1515
int64_t gas,
1616
const std::string& code_hex,
1717
const std::string& input_hex,
18+
bool create,
1819
std::ostream& out);
1920
}
2021
} // namespace evmc

tools/commands/run.cpp

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,62 @@ namespace evmc
1111
{
1212
namespace cmd
1313
{
14+
namespace
15+
{
16+
constexpr auto deploy_address = 0x000000000000000000000000000000000c9ea7ed_address;
17+
constexpr auto deploy_gas = 10'000'000;
18+
} // namespace
19+
1420
int run(evmc::VM& vm,
1521
evmc_revision rev,
1622
int64_t gas,
1723
const std::string& code_hex,
1824
const std::string& input_hex,
25+
bool create,
1926
std::ostream& out)
2027
{
21-
out << "Executing on " << rev << " with " << gas << " gas limit\n";
28+
out << (create ? "Creating and executing on " : "Executing on ") << rev << " with " << gas
29+
<< " gas limit\n";
2230

2331
const auto code = from_hex(code_hex);
2432
const auto input = from_hex(input_hex);
33+
34+
MockedHost host;
35+
2536
evmc_message msg{};
2637
msg.gas = gas;
2738
msg.input_data = input.data();
2839
msg.input_size = input.size();
29-
MockedHost host;
3040

31-
const auto result = vm.execute(host, rev, msg, code.data(), code.size());
41+
const uint8_t* exec_code_data = nullptr;
42+
size_t exec_code_size = 0;
43+
44+
if (create)
45+
{
46+
evmc_message deploy_msg{};
47+
deploy_msg.kind = EVMC_CREATE;
48+
deploy_msg.destination = deploy_address;
49+
deploy_msg.gas = deploy_gas;
50+
51+
const auto deploy_result = vm.execute(host, rev, deploy_msg, code.data(), code.size());
52+
if (deploy_result.status_code != EVMC_SUCCESS)
53+
return 1;
54+
55+
auto& deployed_account = host.accounts[deploy_address];
56+
deployed_account.code = bytes(deploy_result.output_data, deploy_result.output_size);
57+
58+
msg.destination = deploy_address;
59+
60+
exec_code_data = deployed_account.code.data();
61+
exec_code_size = deployed_account.code.size();
62+
}
63+
else
64+
{
65+
exec_code_data = code.data();
66+
exec_code_size = code.size();
67+
}
68+
69+
const auto result = vm.execute(host, rev, msg, exec_code_data, exec_code_size);
3270

3371
const auto gas_used = msg.gas - result.gas_left;
3472

tools/evmc/main.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ int main(int argc, const char** argv)
1515
int64_t gas = 1000000;
1616
auto rev = EVMC_ISTANBUL;
1717
std::string input_hex;
18+
auto create = false;
1819

1920
CLI::App app{"EVMC tool"};
2021
const auto& version_flag = *app.add_flag("--version", "Print version information and exit");
@@ -26,6 +27,9 @@ int main(int argc, const char** argv)
2627
run_cmd.add_option("--gas", gas, "Execution gas limit", true)->check(CLI::Range(0, 1000000000));
2728
run_cmd.add_option("--rev", rev, "EVM revision", true);
2829
run_cmd.add_option("--input", input_hex, "Hex-encoded input bytes");
30+
run_cmd.add_flag(
31+
"--create", create,
32+
"Create new contract out of the code and then execute this contract with the input");
2933

3034
try
3135
{
@@ -67,7 +71,7 @@ int main(int argc, const char** argv)
6771
throw CLI::RequiredError{vm_option.get_name()};
6872

6973
std::cout << "Config: " << vm_config << "\n";
70-
return cmd::run(vm, rev, gas, code_hex, input_hex, std::cout);
74+
return cmd::run(vm, rev, gas, code_hex, input_hex, create, std::cout);
7175
}
7276

7377
return 0;

0 commit comments

Comments
 (0)