diff --git a/contract/include/evm_runtime/state.hpp b/contract/include/evm_runtime/state.hpp index d5e4cfbb..0cb4a53b 100644 --- a/contract/include/evm_runtime/state.hpp +++ b/contract/include/evm_runtime/state.hpp @@ -30,8 +30,12 @@ struct state : State { mutable std::map addr2id; mutable std::map addr2code; mutable db_stats stats; + std::optional _config2; explicit state(name self, name ram_payer, bool read_only=false) : _self(self), _ram_payer(ram_payer), _read_only{read_only}{} + virtual ~state() override; + + uint64_t get_next_account_id(); std::optional read_account(const evmc::address& address) const noexcept override; diff --git a/contract/include/evm_runtime/tables.hpp b/contract/include/evm_runtime/tables.hpp index 1b774853..d8639772 100644 --- a/contract/include/evm_runtime/tables.hpp +++ b/contract/include/evm_runtime/tables.hpp @@ -182,4 +182,11 @@ struct [[eosio::table]] [[eosio::contract("evm_contract")]] allowed_egress_accou typedef eosio::multi_index<"egresslist"_n, allowed_egress_account> egresslist; +struct [[eosio::table]] [[eosio::contract("evm_contract")]] config2 +{ + uint64_t next_account_id{0}; + + EOSLIB_SERIALIZE(config2, (next_account_id)); +}; + } //namespace evm_runtime \ No newline at end of file diff --git a/contract/src/actions.cpp b/contract/src/actions.cpp index 0c202c48..45380030 100644 --- a/contract/src/actions.cpp +++ b/contract/src/actions.cpp @@ -550,6 +550,7 @@ void evm_contract::withdraw(eosio::name owner, eosio::asset quantity, const eosi bool evm_contract::gc(uint32_t max) { assert_unfrozen(); + require_auth(get_self()); evm_runtime::state state{get_self(), eosio::same_payer}; return state.gc(max); diff --git a/contract/src/state.cpp b/contract/src/state.cpp index 269dda90..f9c253cd 100644 --- a/contract/src/state.cpp +++ b/contract/src/state.cpp @@ -104,7 +104,7 @@ void state::update_account(const evmc::address& address, std::optional ++stats.account.read; auto emplace = [&](auto& row) { - row.id = accounts.available_primary_key(); + row.id = get_next_account_id(); row.eth_address = to_bytes(address); row.nonce = current->nonce; row.balance = to_bytes(current->balance); @@ -214,7 +214,7 @@ void state::update_account_code(const evmc::address& address, uint64_t, const ev ++stats.account.update; } else { accounts.emplace(_ram_payer, [&](auto& row){ - row.id = accounts.available_primary_key();; + row.id = get_next_account_id();; row.eth_address = to_bytes(address); row.nonce = 0; row.code_id = code_id; @@ -245,7 +245,7 @@ void state::update_storage(const evmc::address& address, uint64_t incarnation, c uint64_t table_id; if(itr == inx.end()){ accounts.emplace(_ram_payer, [&](auto& row){ - table_id = accounts.available_primary_key(); + table_id = get_next_account_id(); row.id = table_id; row.eth_address = to_bytes(address); row.nonce = 0; @@ -329,4 +329,25 @@ evmc::bytes32 state::state_root_hash() const { return {}; } +uint64_t state::get_next_account_id() { + if(!_config2) { + eosio::singleton<"config2"_n, config2> cfg2{_self, _self.value}; + if(cfg2.exists()) { + _config2 = cfg2.get(); + } else { + account_table accounts(_self, _self.value); + _config2 = config2{accounts.available_primary_key()}; + } + } + auto id = _config2->next_account_id; + _config2->next_account_id++; + return id; +} + +state::~state() { + if(!_config2.has_value()) return; + eosio::singleton<"config2"_n, config2> cfg2{_self, _self.value}; + cfg2.set(_config2.value(), _self); +} + } // namespace evm_runtime diff --git a/contract/tests/CMakeLists.txt b/contract/tests/CMakeLists.txt index ab15b757..f093ca4e 100644 --- a/contract/tests/CMakeLists.txt +++ b/contract/tests/CMakeLists.txt @@ -25,6 +25,7 @@ include_directories( set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations") add_eosio_test_executable( unit_test + ${CMAKE_SOURCE_DIR}/account_id_tests.cpp ${CMAKE_SOURCE_DIR}/basic_evm_tester.cpp ${CMAKE_SOURCE_DIR}/evm_runtime_tests.cpp ${CMAKE_SOURCE_DIR}/init_tests.cpp diff --git a/contract/tests/account_id_tests.cpp b/contract/tests/account_id_tests.cpp new file mode 100644 index 00000000..8345fcea --- /dev/null +++ b/contract/tests/account_id_tests.cpp @@ -0,0 +1,254 @@ +#include "basic_evm_tester.hpp" +#include + +using namespace evm_test; +struct account_id_tester : basic_evm_tester { + account_id_tester() { + create_accounts({"alice"_n}); + transfer_token(faucet_account_name, "alice"_n, make_asset(10000'0000)); + init(); + } + + std::optional get_max_account_id() { + const auto& db = control->db(); + const auto* t_id = db.find( boost::make_tuple( evm_account_name, evm_account_name, "account"_n ) ); + if ( !t_id ) return {}; + + const auto& idx = db.get_index(); + if( idx.begin() == idx.end() ) return {}; + + decltype(t_id->id) next_tid(t_id->id._id + 1); + auto itr = idx.lower_bound(boost::make_tuple(next_tid)); + if(itr == idx.end() || itr->t_id == next_tid) --itr; + + if(itr->t_id._id != t_id->id._id) return {}; + return itr->primary_key; + } + + std::string int_str32(uint32_t x) { + std::stringstream hex_ss; + hex_ss << std::hex << x; + int hex_length = hex_ss.str().length(); + + std::stringstream ss; + ss << std::setfill('0') << std::setw(64 - hex_length) << 0 << std::hex << std::uppercase << x; + return ss.str(); + } + + // // SPDX-License-Identifier: MIT + // pragma solidity ^0.8.17; + // contract Factory { + // // Returns the address of the newly deployed contract + // function deploy( + // bytes32 _salt + // ) public payable returns (address) { + // return address(new TestContract{salt: _salt}()); + // } + // } + // contract TestContract { + // uint foo; + // function set_foo(uint val) public { + // foo = val; + // } + // function killme() public { + // address payable addr = payable(address(0)); + // selfdestruct(addr); + // } + // } + + const std::string factory_and_test_bytecode = "608060405234801561001057600080fd5b506102c1806100206000396000f3fe60806040526004361061001e5760003560e01c80632b85ba3814610023575b600080fd5b61003d600480360381019061003891906100d2565b610053565b60405161004a9190610140565b60405180910390f35b6000816040516100629061008a565b8190604051809103906000f5905080158015610082573d6000803e3d6000fd5b509050919050565b6101308061015c83390190565b600080fd5b6000819050919050565b6100af8161009c565b81146100ba57600080fd5b50565b6000813590506100cc816100a6565b92915050565b6000602082840312156100e8576100e7610097565b5b60006100f6848285016100bd565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061012a826100ff565b9050919050565b61013a8161011f565b82525050565b60006020820190506101556000830184610131565b9291505056fe608060405234801561001057600080fd5b50610110806100206000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806324d97a4a146037578063e5d5dfbc14603f575b600080fd5b603d6057565b005b605560048036038101906051919060b2565b6072565b005b60008073ffffffffffffffffffffffffffffffffffffffff16ff5b8060008190555050565b600080fd5b6000819050919050565b6092816081565b8114609c57600080fd5b50565b60008135905060ac81608b565b92915050565b60006020828403121560c55760c4607c565b5b600060d184828501609f565b9150509291505056fea2646970667358221220e59ba0023d9a6f99a6734000d8812c1830a2a61597b322310827ec350a4304dd64736f6c63430008120033a26469706673582212205e94c73549f6e1751509ff5704aec0a8ada3a60ab2b8cc1b9df9febc7ed2bd2f64736f6c63430008120033"; + + size_t get_storage_slots_count(uint64_t account_id) { + size_t total_slots{0}; + scan_account_storage(account_id, [&](const storage_slot& slot)->bool{ + total_slots++; + return true; + }); + return total_slots; + } + + +}; + +BOOST_AUTO_TEST_SUITE(account_id_tests) + +BOOST_FIXTURE_TEST_CASE(new_account_id_logic, account_id_tester) try { + + BOOST_CHECK(!get_max_account_id().has_value()); + BOOST_REQUIRE_EXCEPTION(get_config2(), fc::out_of_range_exception, [](const fc::out_of_range_exception& e) {return true;}); + + // Fund evm1 address with 100 EOS + evm_eoa evm1; + const int64_t to_bridge = 1000000; + transfer_token("alice"_n, evm_account_name, make_asset(to_bridge), evm1.address_0x()); + BOOST_CHECK(get_max_account_id().value() == 0); + BOOST_CHECK(get_config2().next_account_id == 1); + + // Deploy Factory and Test contracts + auto contract_addr = deploy_contract(evm1, evmc::from_hex(factory_and_test_bytecode).value()); + uint64_t contract_account_id = find_account_by_address(contract_addr).value().id; + BOOST_CHECK(get_max_account_id().value() == 1); + BOOST_CHECK(get_config2().next_account_id == 2); + + // Call 'Factory::deploy' + auto txn = generate_tx(contract_addr, 0, 1'000'000); + + silkworm::Bytes data; + data += evmc::from_hex("2b85ba38").value(); //deploy + data += evmc::from_hex(int_str32(555)).value(); //salt=555 + txn.data = data; + evm1.sign(txn); + pushtx(txn); + + BOOST_CHECK(get_max_account_id().value() == 2); + BOOST_CHECK(get_config2().next_account_id == 3); + + // Recover TestContract address + auto test_contract_address = find_account_by_id(2).value().address; + + // Call 'TestContract::set_foo(1234)' + txn = generate_tx(test_contract_address, 0, 1'000'000); + data.clear(); + data += evmc::from_hex("e5d5dfbc").value(); //set_foo + data += evmc::from_hex(int_str32(1234)).value(); //val=1234 + txn.data = data; + evm1.sign(txn); + pushtx(txn); + + BOOST_CHECK(get_storage_slots_count(2) == 1); + + // Call 'TestContract::killme' + txn = generate_tx(test_contract_address, 0, 1'000'000); + data.clear(); + data += evmc::from_hex("24d97a4a").value(); //killme + txn.data = data; + evm1.sign(txn); + pushtx(txn); + + BOOST_CHECK(get_storage_slots_count(2) == 1); + + BOOST_CHECK(get_max_account_id().value() == 1); + BOOST_CHECK(get_config2().next_account_id == 3); + + // Call 'Factory::deploy' again + txn = generate_tx(contract_addr, 0, 1'000'000); + data.clear(); + data += evmc::from_hex("2b85ba38").value(); //deploy + data += evmc::from_hex(int_str32(555)).value(); //salt=555 + txn.data = data; + evm1.sign(txn); + pushtx(txn); + + BOOST_CHECK(get_max_account_id().value() == 3); + BOOST_CHECK(get_config2().next_account_id == 4); + + BOOST_CHECK(get_storage_slots_count(3) == 0); + + BOOST_CHECK(test_contract_address == find_account_by_id(3).value().address); + + // Call 'TestContract::set_foo(1234)' + txn = generate_tx(test_contract_address, 0, 1'000'000); + data.clear(); + data += evmc::from_hex("e5d5dfbc").value(); //set_foo + data += evmc::from_hex(int_str32(1234)).value(); //val=1234 + txn.data = data; + evm1.sign(txn); + pushtx(txn); + + BOOST_CHECK(get_storage_slots_count(3) == 1); + + // Call gc(100) + gc(100); + BOOST_CHECK(get_storage_slots_count(2) == 0); + + +} FC_LOG_AND_RETHROW() + +BOOST_FIXTURE_TEST_CASE(transition_from_0_5_1, account_id_tester) try { + + // Set old code + set_code(evm_account_name, testing::contracts::evm_runtime_wasm_0_5_1()); + set_abi(evm_account_name, testing::contracts::evm_runtime_abi_0_5_1().data()); + + BOOST_CHECK(!get_max_account_id().has_value()); + + // Fund evm1 address with 100 EOS + evm_eoa evm1; + const int64_t to_bridge = 1000000; + transfer_token("alice"_n, evm_account_name, make_asset(to_bridge), evm1.address_0x()); + BOOST_CHECK(get_max_account_id().value() == 0); + + // Deploy Factory and Test contracts + auto contract_addr = deploy_contract(evm1, evmc::from_hex(factory_and_test_bytecode).value()); + uint64_t contract_account_id = find_account_by_address(contract_addr).value().id; + BOOST_CHECK(get_max_account_id().value() == 1); + + // Call 'Factory::deploy' + auto txn = generate_tx(contract_addr, 0, 1'000'000); + + silkworm::Bytes data; + data += evmc::from_hex("2b85ba38").value(); //deploy + data += evmc::from_hex(int_str32(555)).value(); //salt=555 + txn.data = data; + evm1.sign(txn); + pushtx(txn); + + BOOST_CHECK(get_max_account_id().value() == 2); + + // Recover TestContract address + auto test_contract_address = find_account_by_id(2).value().address; + + // Call 'TestContract::set_foo(1234)' + txn = generate_tx(test_contract_address, 0, 1'000'000); + data.clear(); + data += evmc::from_hex("e5d5dfbc").value(); //set_foo + data += evmc::from_hex(int_str32(1234)).value(); //val=1234 + txn.data = data; + evm1.sign(txn); + pushtx(txn); + + BOOST_CHECK(get_storage_slots_count(2) == 1); + + // Call 'TestContract::killme' + txn = generate_tx(test_contract_address, 0, 1'000'000); + data.clear(); + data += evmc::from_hex("24d97a4a").value(); //killme + txn.data = data; + evm1.sign(txn); + pushtx(txn); + + BOOST_CHECK(get_storage_slots_count(2) == 1); + BOOST_CHECK(get_max_account_id().value() == 1); + + // Make a transfer to a new address to create a new account + evm_eoa evm2; + transfer_token("alice"_n, evm_account_name, make_asset(to_bridge), evm2.address_0x()); + BOOST_CHECK(get_max_account_id().value() == 2); + + // Set new code + set_code(evm_account_name, testing::contracts::evm_runtime_wasm()); + set_abi(evm_account_name, testing::contracts::evm_runtime_abi().data()); + + BOOST_REQUIRE_EXCEPTION(get_config2(), fc::out_of_range_exception, [](const fc::out_of_range_exception& e) {return true;}); + + // Call 'Factory::deploy' again + txn = generate_tx(contract_addr, 0, 1'000'000); + data.clear(); + data += evmc::from_hex("2b85ba38").value(); //deploy + data += evmc::from_hex(int_str32(555)).value(); //salt=555 + txn.data = data; + evm1.sign(txn); + pushtx(txn); + + BOOST_CHECK(get_max_account_id().value() == 3); + BOOST_CHECK(get_config2().next_account_id == 4); + + // Make a transfer to a new address to create a new account + evm_eoa evm3; + transfer_token("alice"_n, evm_account_name, make_asset(to_bridge), evm3.address_0x()); + BOOST_CHECK(get_max_account_id().value() == 4); + BOOST_CHECK(get_config2().next_account_id == 5); + +} FC_LOG_AND_RETHROW() + +BOOST_AUTO_TEST_SUITE_END() diff --git a/contract/tests/basic_evm_tester.cpp b/contract/tests/basic_evm_tester.cpp index a9d7ece5..062d1429 100644 --- a/contract/tests/basic_evm_tester.cpp +++ b/contract/tests/basic_evm_tester.cpp @@ -247,6 +247,14 @@ config_table_row basic_evm_tester::get_config() const return fc::raw::unpack(d); } +config2_table_row basic_evm_tester::get_config2() const +{ + static constexpr eosio::chain::name config2_singleton_name = "config2"_n; + const vector d = + get_row_by_account(evm_account_name, evm_account_name, config2_singleton_name, config2_singleton_name); + return fc::raw::unpack(d); +} + void basic_evm_tester::setfeeparams(const fee_parameters& fee_params) { mvo fee_params_vo; @@ -342,6 +350,10 @@ void basic_evm_tester::withdraw(name owner, asset quantity) push_action(evm_account_name, "withdraw"_n, owner, mvo()("owner", owner)("quantity", quantity)); } +void basic_evm_tester::gc(uint32_t max) { + push_action(evm_account_name, "gc"_n, evm_account_name, mvo()("max", max)); +} + balance_and_dust basic_evm_tester::vault_balance(name owner) const { const vector d = get_row_by_account(evm_account_name, evm_account_name, "balances"_n, owner); @@ -466,6 +478,20 @@ std::optional basic_evm_tester::find_account_by_address(const ev return result; } +std::optional basic_evm_tester::find_account_by_id(uint64_t id) const +{ + static constexpr eosio::chain::name account_table_name = "account"_n; + const vector d = + get_row_by_account(evm_account_name, evm_account_name, account_table_name, name{id}); + if(d.empty()) return {}; + + partial_account_table_row row; + fc::datastream ds(d.data(), d.size()); + fc::raw::unpack(ds, row); + + return convert_to_account_object(row); +} + bool basic_evm_tester::scan_account_storage(uint64_t account_id, std::function visitor) const { static constexpr eosio::chain::name storage_table_name = "storage"_n; diff --git a/contract/tests/basic_evm_tester.hpp b/contract/tests/basic_evm_tester.hpp index 56b79940..cd83b0ef 100644 --- a/contract/tests/basic_evm_tester.hpp +++ b/contract/tests/basic_evm_tester.hpp @@ -56,6 +56,11 @@ struct config_table_row uint32_t status; }; +struct config2_table_row +{ + uint64_t next_account_id; +}; + struct balance_and_dust { asset balance; @@ -114,6 +119,7 @@ struct exec_output { FC_REFLECT(evm_test::config_table_row, (version)(chainid)(genesis_time)(ingress_bridge_fee)(gas_price)(miner_cut)(status)) +FC_REFLECT(evm_test::config2_table_row,(next_account_id)) FC_REFLECT(evm_test::balance_and_dust, (balance)(dust)); FC_REFLECT(evm_test::account_object, (id)(address)(nonce)(balance)) FC_REFLECT(evm_test::storage_slot, (id)(key)(value)) @@ -192,6 +198,7 @@ class basic_evm_tester : public testing::validating_tester void prepare_self_balance(uint64_t fund_amount = 100'0000); config_table_row get_config() const; + config2_table_row get_config2() const; void setfeeparams(const fee_parameters& fee_params); @@ -209,6 +216,8 @@ class basic_evm_tester : public testing::validating_tester void close(name owner); void withdraw(name owner, asset quantity); + void gc(uint32_t max); + balance_and_dust vault_balance(name owner) const; std::optional evm_balance(const evmc::address& address) const; std::optional evm_balance(const evm_eoa& account) const; @@ -241,6 +250,7 @@ class basic_evm_tester : public testing::validating_tester bool scan_accounts(std::function visitor) const; std::optional scan_for_account_by_address(const evmc::address& address) const; std::optional find_account_by_address(const evmc::address& address) const; + std::optional find_account_by_id(uint64_t id) const; bool scan_account_storage(uint64_t account_id, std::function visitor) const; }; diff --git a/contract/tests/contracts.hpp.in b/contract/tests/contracts.hpp.in index f606450c..ecef1ee8 100644 --- a/contract/tests/contracts.hpp.in +++ b/contract/tests/contracts.hpp.in @@ -40,6 +40,9 @@ struct contracts { static std::vector evm_read_callback_wasm() { return read_wasm("${CMAKE_CURRENT_SOURCE_DIR}/contracts/evm_read_callback/evm_read_callback.wasm"); } static std::vector evm_read_callback_abi() { return read_abi("${CMAKE_CURRENT_SOURCE_DIR}/contracts/evm_read_callback/evm_read_callback.abi"); } + static std::vector evm_runtime_wasm_0_5_1() { return read_wasm("${CMAKE_CURRENT_SOURCE_DIR}/contracts/evm_runtime_wasm_0_5_1/evm_runtime.wasm"); } + static std::vector evm_runtime_abi_0_5_1() { return read_abi("${CMAKE_CURRENT_SOURCE_DIR}/contracts/evm_runtime_wasm_0_5_1/evm_runtime.abi"); } + static std::string eth_test_folder() { return "${CMAKE_CURRENT_SOURCE_DIR}/../../silkworm/third_party/tests"; } diff --git a/contract/tests/contracts/evm_runtime_wasm_0_5_1/evm_runtime.abi b/contract/tests/contracts/evm_runtime_wasm_0_5_1/evm_runtime.abi new file mode 100644 index 00000000..e2c7a430 --- /dev/null +++ b/contract/tests/contracts/evm_runtime_wasm_0_5_1/evm_runtime.abi @@ -0,0 +1,394 @@ +{ + "version": "eosio::abi/1.2", + "types": [], + "structs": [{ + "name": "account", + "base": "", + "fields": [{ + "name": "id", + "type": "uint64" + },{ + "name": "eth_address", + "type": "bytes" + },{ + "name": "nonce", + "type": "uint64" + },{ + "name": "balance", + "type": "bytes" + },{ + "name": "code_id", + "type": "uint64?" + } + ] + },{ + "name": "account_code", + "base": "", + "fields": [{ + "name": "id", + "type": "uint64" + },{ + "name": "ref_count", + "type": "uint32" + },{ + "name": "code", + "type": "bytes" + },{ + "name": "code_hash", + "type": "bytes" + } + ] + },{ + "name": "addegress", + "base": "", + "fields": [{ + "name": "accounts", + "type": "name[]" + } + ] + },{ + "name": "allowed_egress_account", + "base": "", + "fields": [{ + "name": "account", + "type": "name" + } + ] + },{ + "name": "balance", + "base": "", + "fields": [{ + "name": "owner", + "type": "name" + },{ + "name": "balance", + "type": "balance_with_dust" + } + ] + },{ + "name": "balance_with_dust", + "base": "", + "fields": [{ + "name": "balance", + "type": "asset" + },{ + "name": "dust", + "type": "uint64" + } + ] + },{ + "name": "close", + "base": "", + "fields": [{ + "name": "owner", + "type": "name" + } + ] + },{ + "name": "config", + "base": "", + "fields": [{ + "name": "version", + "type": "varuint32" + },{ + "name": "chainid", + "type": "uint64" + },{ + "name": "genesis_time", + "type": "time_point_sec" + },{ + "name": "ingress_bridge_fee", + "type": "asset" + },{ + "name": "gas_price", + "type": "uint64" + },{ + "name": "miner_cut", + "type": "uint32" + },{ + "name": "status", + "type": "uint32" + } + ] + },{ + "name": "exec", + "base": "", + "fields": [{ + "name": "input", + "type": "exec_input" + },{ + "name": "callback", + "type": "exec_callback?" + } + ] + },{ + "name": "exec_callback", + "base": "", + "fields": [{ + "name": "contract", + "type": "name" + },{ + "name": "action", + "type": "name" + } + ] + },{ + "name": "exec_input", + "base": "", + "fields": [{ + "name": "context", + "type": "bytes?" + },{ + "name": "from", + "type": "bytes?" + },{ + "name": "to", + "type": "bytes" + },{ + "name": "data", + "type": "bytes" + },{ + "name": "value", + "type": "bytes?" + } + ] + },{ + "name": "fee_parameters", + "base": "", + "fields": [{ + "name": "gas_price", + "type": "uint64?" + },{ + "name": "miner_cut", + "type": "uint32?" + },{ + "name": "ingress_bridge_fee", + "type": "asset?" + } + ] + },{ + "name": "freeze", + "base": "", + "fields": [{ + "name": "value", + "type": "bool" + } + ] + },{ + "name": "gc", + "base": "", + "fields": [{ + "name": "max", + "type": "uint32" + } + ] + },{ + "name": "gcstore", + "base": "", + "fields": [{ + "name": "id", + "type": "uint64" + },{ + "name": "storage_id", + "type": "uint64" + } + ] + },{ + "name": "init", + "base": "", + "fields": [{ + "name": "chainid", + "type": "uint64" + },{ + "name": "fee_params", + "type": "fee_parameters" + } + ] + },{ + "name": "nextnonce", + "base": "", + "fields": [{ + "name": "owner", + "type": "name" + },{ + "name": "next_nonce", + "type": "uint64" + } + ] + },{ + "name": "open", + "base": "", + "fields": [{ + "name": "owner", + "type": "name" + } + ] + },{ + "name": "pushtx", + "base": "", + "fields": [{ + "name": "miner", + "type": "name" + },{ + "name": "rlptx", + "type": "bytes" + } + ] + },{ + "name": "removeegress", + "base": "", + "fields": [{ + "name": "accounts", + "type": "name[]" + } + ] + },{ + "name": "setfeeparams", + "base": "", + "fields": [{ + "name": "fee_params", + "type": "fee_parameters" + } + ] + },{ + "name": "storage", + "base": "", + "fields": [{ + "name": "id", + "type": "uint64" + },{ + "name": "key", + "type": "bytes" + },{ + "name": "value", + "type": "bytes" + } + ] + },{ + "name": "withdraw", + "base": "", + "fields": [{ + "name": "owner", + "type": "name" + },{ + "name": "quantity", + "type": "asset" + },{ + "name": "to", + "type": "name$" + } + ] + } + ], + "actions": [{ + "name": "addegress", + "type": "addegress", + "ricardian_contract": "" + },{ + "name": "close", + "type": "close", + "ricardian_contract": "" + },{ + "name": "exec", + "type": "exec", + "ricardian_contract": "" + },{ + "name": "freeze", + "type": "freeze", + "ricardian_contract": "" + },{ + "name": "gc", + "type": "gc", + "ricardian_contract": "" + },{ + "name": "init", + "type": "init", + "ricardian_contract": "" + },{ + "name": "open", + "type": "open", + "ricardian_contract": "" + },{ + "name": "pushtx", + "type": "pushtx", + "ricardian_contract": "" + },{ + "name": "removeegress", + "type": "removeegress", + "ricardian_contract": "" + },{ + "name": "setfeeparams", + "type": "setfeeparams", + "ricardian_contract": "" + },{ + "name": "withdraw", + "type": "withdraw", + "ricardian_contract": "" + } + ], + "tables": [{ + "name": "account", + "index_type": "i64", + "key_names": [], + "key_types": [], + "type": "account" + },{ + "name": "accountcode", + "index_type": "i64", + "key_names": [], + "key_types": [], + "type": "account_code" + },{ + "name": "balances", + "index_type": "i64", + "key_names": [], + "key_types": [], + "type": "balance" + },{ + "name": "config", + "index_type": "i64", + "key_names": [], + "key_types": [], + "type": "config" + },{ + "name": "egresslist", + "index_type": "i64", + "key_names": [], + "key_types": [], + "type": "allowed_egress_account" + },{ + "name": "gcstore", + "index_type": "i64", + "key_names": [], + "key_types": [], + "type": "gcstore" + },{ + "name": "inevm", + "index_type": "i64", + "key_names": [], + "key_types": [], + "type": "balance_with_dust" + },{ + "name": "nextnonces", + "index_type": "i64", + "key_names": [], + "key_types": [], + "type": "nextnonce" + },{ + "name": "storage", + "index_type": "i64", + "key_names": [], + "key_types": [], + "type": "storage" + } + ], + "ricardian_clauses": [], + "error_messages": [], + "abi_extensions": [], + "variants": [], + "action_results": [{ + "name": "gc", + "result_type": "bool" + } + ] +} \ No newline at end of file diff --git a/contract/tests/contracts/evm_runtime_wasm_0_5_1/evm_runtime.wasm b/contract/tests/contracts/evm_runtime_wasm_0_5_1/evm_runtime.wasm new file mode 100644 index 00000000..7b83b735 Binary files /dev/null and b/contract/tests/contracts/evm_runtime_wasm_0_5_1/evm_runtime.wasm differ