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: 2 additions & 0 deletions include/evm_runtime/evm_contract.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ class [[eosio::contract]] evm_contract : public contract
void dispatch_tx(const runtime_config& rc, const transaction& tx);

uint64_t get_gas_price(uint64_t version);
struct statistics get_statistics() const;
void set_statistics(const struct statistics &v);
};

} // namespace evm_runtime
Expand Down
9 changes: 9 additions & 0 deletions include/evm_runtime/tables.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,5 +300,14 @@ struct [[eosio::table]] [[eosio::contract("evm_contract")]] prices_queue
EOSLIB_SERIALIZE(prices_queue, (block)(prices));
};
typedef eosio::multi_index<"pricesqueue"_n, prices_queue> prices_queue_table;
struct [[eosio::table("statistics")]] [[eosio::contract("evm_contract")]] statistics
{
unsigned_int version; // placeholder for future variant index
balance_with_dust gas_fee_income;
balance_with_dust ingress_bridge_fee_income;

EOSLIB_SERIALIZE(statistics, (version)(gas_fee_income)(ingress_bridge_fee_income));
};
typedef eosio::singleton<"statistics"_n, statistics> statistics_singleton;

} //namespace evm_runtime
43 changes: 43 additions & 0 deletions src/actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ Receipt evm_contract::execute_tx(const runtime_config& rc, eosio::name miner, Bl
}

bool deducted_miner_cut = false;
bool from_self = false;

std::optional<inevm_singleton> inevm;
auto populate_bridge_accessors = [&]() {
Expand Down Expand Up @@ -223,6 +224,8 @@ Receipt evm_contract::execute_tx(const runtime_config& rc, eosio::name miner, Bl
if (is_reserved_address(*tx.from)) {
const name ingress_account(*extract_reserved_address(*tx.from));

from_self = ingress_account == get_self();

const intx::uint512 max_gas_cost = intx::uint256(tx.gas_limit) * tx.max_fee_per_gas;
check(max_gas_cost + tx.value < std::numeric_limits<intx::uint256>::max(), "too much gas");
const intx::uint256 value_with_max_gas = tx.value + (intx::uint256)max_gas_cost;
Expand Down Expand Up @@ -359,6 +362,27 @@ Receipt evm_contract::execute_tx(const runtime_config& rc, eosio::name miner, Bl
});
}

// Statistics
if (!from_self) {
// Gas income from tx sent from self should not be counted.
// Bridge transfers can generate such txs.
uint64_t tx_gas_used = receipt.cumulative_gas_used; // Only transaction in the "block" so cumulative_gas_used is the tx gas_used.
auto s = get_statistics();
if (_config->get_evm_version() >= 1) {
intx::uint512 gas_fee = intx::uint256(tx_gas_used) * ep.evm().block().header.base_fee_per_gas.value();
check(gas_fee < std::numeric_limits<intx::uint256>::max(), "too much gas");
s.gas_fee_income += static_cast<intx::uint256>(gas_fee);
} else {
intx::uint512 gas_fee = intx::uint256(tx_gas_used) * tx.max_fee_per_gas;
check(gas_fee < std::numeric_limits<intx::uint256>::max(), "too much gas");
if (gas_fee_miner_portion.has_value()) {
gas_fee -= *gas_fee_miner_portion;
}
s.gas_fee_income += static_cast<intx::uint256>(gas_fee);
}
set_statistics(s);
}

LOGTIME("EVM EXECUTE");
return receipt;
}
Expand Down Expand Up @@ -694,6 +718,11 @@ void evm_contract::handle_evm_transfer(eosio::asset quantity, const std::string&
quantity -= _config->get_ingress_bridge_fee();
eosio::check(quantity.amount > 0, "must bridge more than ingress bridge fee");

// Statistics
auto s = get_statistics();
s.ingress_bridge_fee_income.balance += _config->get_ingress_bridge_fee();
set_statistics(s);

const std::optional<Bytes> address_bytes = from_hex(memo);
eosio::check(!!address_bytes, "unable to parse destination address");

Expand Down Expand Up @@ -967,4 +996,18 @@ uint64_t evm_contract::get_gas_price(uint64_t evm_version) {
return _config->get_gas_price();
}

statistics evm_contract::get_statistics() const {
statistics_singleton statistics_v(get_self(), get_self().value);
return statistics_v.get_or_create(get_self(), statistics {
.version = 0,
.ingress_bridge_fee_income = { .balance = eosio::asset(0, _config->get_ingress_bridge_fee().symbol), .dust = 0 },
.gas_fee_income = { .balance = eosio::asset(0, _config->get_ingress_bridge_fee().symbol), .dust = 0 },
});
}

void evm_contract::set_statistics(const statistics &v) {
statistics_singleton statistics_v(get_self(), get_self().value);
statistics_v.set(v, get_self());
}

} //evm_runtime
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ add_eosio_test_executable( unit_test
${CMAKE_SOURCE_DIR}/bridge_message_tests.cpp
${CMAKE_SOURCE_DIR}/admin_actions_tests.cpp
${CMAKE_SOURCE_DIR}/stack_limit_tests.cpp
${CMAKE_SOURCE_DIR}/statistics_tests.cpp
${CMAKE_SOURCE_DIR}/main.cpp
${CMAKE_SOURCE_DIR}/../silkworm/silkworm/core/rlp/encode.cpp
${CMAKE_SOURCE_DIR}/../silkworm/silkworm/core/rlp/decode.cpp
Expand Down
8 changes: 8 additions & 0 deletions tests/basic_evm_tester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,14 @@ config_table_row basic_evm_tester::get_config() const
return fc::raw::unpack<config_table_row>(d);
}

statistics basic_evm_tester::get_statistics() const
{
static constexpr eosio::chain::name statistics_singleton_name = "statistics"_n;
const vector<char> d =
get_row_by_account(evm_account_name, evm_account_name, statistics_singleton_name, statistics_singleton_name);
return fc::raw::unpack<statistics>(d);
}

config2_table_row basic_evm_tester::get_config2() const
{
static constexpr eosio::chain::name config2_singleton_name = "config2"_n;
Expand Down
10 changes: 10 additions & 0 deletions tests/basic_evm_tester.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,13 @@ struct balance_and_dust
bool operator!=(const balance_and_dust&) const;
};

struct statistics
{
unsigned_int version; // placeholder for future variant index
balance_and_dust gas_fee_income;
balance_and_dust ingress_bridge_fee_income;
};

struct account_object
{
enum class flag : uint32_t {
Expand Down Expand Up @@ -245,6 +252,7 @@ FC_REFLECT(evm_test::evm_version_type, (pending_version)(cached_version))
FC_REFLECT(evm_test::evm_version_type::pending, (version)(time))
FC_REFLECT(evm_test::config2_table_row,(next_account_id))
FC_REFLECT(evm_test::balance_and_dust, (balance)(dust));
FC_REFLECT(evm_test::statistics, (version)(gas_fee_income)(ingress_bridge_fee_income));
FC_REFLECT(evm_test::account_object, (id)(address)(nonce)(balance))
FC_REFLECT(evm_test::storage_slot, (id)(key)(value))
FC_REFLECT(evm_test::fee_parameters, (gas_price)(miner_cut)(ingress_bridge_fee))
Expand Down Expand Up @@ -460,6 +468,8 @@ class basic_evm_tester : public evm_validating_tester
config_table_row get_config() const;
config2_table_row get_config2() const;

statistics get_statistics() const;

void setfeeparams(const fee_parameters& fee_params);

silkworm::Transaction
Expand Down
Loading