Skip to content

Commit

Permalink
Add assertnonce action.
Browse files Browse the repository at this point in the history
  • Loading branch information
yarkinwho committed Aug 30, 2023
1 parent c460b54 commit 19dfb5f
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 4 deletions.
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);

#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");
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),
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()

0 comments on commit 19dfb5f

Please sign in to comment.