Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add assertnonce action. #646

Merged
merged 2 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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: 2 additions & 0 deletions include/evm_runtime/evm_contract.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ class [[eosio::contract]] evm_contract : public contract
[[eosio::action]] void bridgereg(eosio::name receiver, const eosio::asset& min_fee);
[[eosio::action]] void bridgeunreg(eosio::name receiver);

[[eosio::action]] void assertnonce(eosio::name receiver, uint64_t nonce);
arhag marked this conversation as resolved.
Show resolved Hide resolved

#ifdef WITH_TEST_ACTIONS
[[eosio::action]] void testtx(const std::optional<bytes>& orlptx, const evm_runtime::test::block_info& bi);
[[eosio::action]] void
Expand Down
8 changes: 8 additions & 0 deletions src/actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,14 @@ void evm_contract::bridgeunreg(eosio::name receiver) {
message_receivers.erase(*it);
}


void evm_contract::assertnonce(eosio::name receiver, uint64_t nonce) {
nextnonces nextnonce_table(get_self(), get_self().value);

const nextnonce& next_nonce = nextnonce_table.get(receiver.value, "caller account has not been opened");
arhag marked this conversation as resolved.
Show resolved Hide resolved
eosio::check(nonce == next_nonce.next_nonce, "wrong nonce");
}

#ifdef WITH_TEST_ACTIONS
[[eosio::action]] void evm_contract::testtx( const std::optional<bytes>& orlptx, const evm_runtime::test::block_info& bi ) {
assert_unfrozen();
Expand Down
5 changes: 5 additions & 0 deletions tests/basic_evm_tester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,11 @@ transaction_trace_ptr basic_evm_tester::bridgeunreg(name receiver) {
mvo()("receiver", receiver));
}

transaction_trace_ptr basic_evm_tester::assertnonce(name receiver, uint64_t nonce) {
return basic_evm_tester::push_action(evm_account_name, "assertnonce"_n, receiver,
mvo()("receiver", receiver)("nonce", nonce));
}

transaction_trace_ptr basic_evm_tester::pushtx(const silkworm::Transaction& trx, name miner)
{
silkworm::Bytes rlp;
Expand Down
1 change: 1 addition & 0 deletions tests/basic_evm_tester.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ class basic_evm_tester : public testing::validating_tester
transaction_trace_ptr bridgereg(name receiver, asset min_fee, vector<account_name> extra_signers={evm_account_name});
transaction_trace_ptr bridgeunreg(name receiver);
transaction_trace_ptr exec(const exec_input& input, const std::optional<exec_callback>& callback);
transaction_trace_ptr assertnonce(name receiver, uint64_t nonce);
transaction_trace_ptr pushtx(const silkworm::Transaction& trx, name miner = evm_account_name);
void call(name from, const evmc::bytes& to, const evmc::bytes& value, evmc::bytes& data, uint64_t gas_limit, name actor);
void admincall(const evmc::bytes& from, const evmc::bytes& to, const evmc::bytes& value, evmc::bytes& data, uint64_t gas_limit, name actor);
Expand Down
61 changes: 57 additions & 4 deletions tests/call_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,28 +471,81 @@ BOOST_FIXTURE_TEST_CASE(deploy_contract_function, call_evm_tester) try {
auto to = evmc::bytes();

auto data = evmc::from_hex(contract_bytecode);

assertnonce("alice"_n, 0);
call("alice"_n, to, silkworm::Bytes(v), *data, 1000000, "alice"_n); // nonce 0->1

auto addr = silkworm::create_address(alice_addr, 0);

assertnonce("alice"_n, 1);
call_test(addr, 1234, "alice"_n, "alice"_n); // nonce 1->2

auto count = get_count(addr);
BOOST_REQUIRE(count == 1234);

// Advance block so we do not generate same transaction.
produce_block();

auto from = evmc::bytes{std::begin(alice_addr.bytes), std::end(alice_addr.bytes)};

assertnonce("alice"_n, 2);
admincall(from, to, silkworm::Bytes(v), *data, 1000000, evm_account_name); // nonce 2->3

addr = silkworm::create_address(alice_addr, 2);
assertnonce("alice"_n, 3);
call_test(addr, 2222, "alice"_n, "alice"_n); // nonce 3->4
assertnonce("alice"_n, 4);
count = get_count(addr);
BOOST_REQUIRE(count == 2222);
} FC_LOG_AND_RETHROW()

BOOST_FIXTURE_TEST_CASE(assetnonce_test, call_evm_tester) try {
auto alice_addr = make_reserved_address("alice"_n.to_uint64_t());

BOOST_REQUIRE_EXCEPTION(assertnonce("alice"_n, 0),
arhag marked this conversation as resolved.
Show resolved Hide resolved
eosio_assert_message_exception, eosio_assert_message_is("caller account has not been opened"));

open("alice"_n);
transfer_token("alice"_n, evm_account_name, make_asset(1000000), "alice");

evm_eoa evm1;
evmc::bytes32 v;

auto to = evmc::bytes();

auto data = evmc::from_hex(contract_bytecode);

// Fail when nonce is 0 but tested with non-zero value
BOOST_REQUIRE_EXCEPTION(assertnonce("alice"_n, 1),
eosio_assert_message_exception, eosio_assert_message_is("wrong nonce"));

assertnonce("alice"_n, 0);
call("alice"_n, to, silkworm::Bytes(v), *data, 1000000, "alice"_n); // nonce 0->1

// Advance block so we do not generate same transaction.
produce_block();

assertnonce("alice"_n, 1);
assertnonce(evm_account_name, 0);
// Fund evm1 address with 100 EOS, should NOT increase alice nonce, but increase evm nonce.
transfer_token("alice"_n, evm_account_name, make_asset(1000000), evm1.address_0x());

// Advance block so we do not generate same transaction.
produce_block();
assertnonce("alice"_n, 1);
assertnonce(evm_account_name, 1);

// Advance block so we do not generate same transaction.
produce_block();

// Fail when nonce is non-zero but tested with another value
BOOST_REQUIRE_EXCEPTION(assertnonce("alice"_n, 2),
eosio_assert_message_exception, eosio_assert_message_is("wrong nonce"));
// Fail when nonce is non-zero but tested with 0
BOOST_REQUIRE_EXCEPTION(assertnonce("alice"_n, 0),
eosio_assert_message_exception, eosio_assert_message_is("wrong nonce"));



} FC_LOG_AND_RETHROW()



BOOST_AUTO_TEST_SUITE_END()