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

Fix base-fee change on EVM block boundary #703

Merged
merged 3 commits into from
Apr 24, 2024
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
6 changes: 3 additions & 3 deletions include/evm_runtime/tables.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,12 +339,12 @@ struct [[eosio::table]] [[eosio::contract("evm_contract")]] config

struct [[eosio::table]] [[eosio::contract("evm_contract")]] price_queue
{
uint64_t time;
uint64_t block;
uint64_t price;

uint64_t primary_key()const { return time; }
uint64_t primary_key()const { return block; }

EOSLIB_SERIALIZE(price_queue, (time)(price));
EOSLIB_SERIALIZE(price_queue, (block)(price));
};

typedef eosio::multi_index<"pricequeue"_n, price_queue> price_queue_table;
Expand Down
19 changes: 12 additions & 7 deletions src/config_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,16 @@ void config_wrapper::set_gas_price(uint64_t gas_price) {

void config_wrapper::enqueue_gas_price(uint64_t gas_price) {
price_queue_table queue(_self, _self.value);
auto time = eosio::current_time_point() + eosio::seconds(grace_period_seconds);
auto time_us = time.elapsed.count();
auto activation_time = get_current_time() + eosio::seconds(grace_period_seconds);

eosevm::block_mapping bm(get_genesis_time().sec_since_epoch());
auto activation_block_num = bm.timestamp_to_evm_block_num(activation_time.time_since_epoch().count()) + 1;

auto it = queue.end();
if( it != queue.begin()) {
--it;
eosio::check(time_us >= it->time, "internal error");
if(it->time == time_us) {
eosio::check(activation_block_num >= it->block, "internal error");
if(activation_block_num == it->block) {
queue.modify(*it, eosio::same_payer, [&](auto& el) {
el.price = gas_price;
});
Expand All @@ -95,20 +97,23 @@ void config_wrapper::enqueue_gas_price(uint64_t gas_price) {
}

queue.emplace(_self, [&](auto& el) {
el.time = time_us;
el.block = activation_block_num;
el.price = gas_price;
});

}

void config_wrapper::process_price_queue() {
auto now = eosio::current_time_point().elapsed.count();
eosevm::block_mapping bm(get_genesis_time().sec_since_epoch());
auto current_block_num = bm.timestamp_to_evm_block_num(get_current_time().time_since_epoch().count());

price_queue_table queue(_self, _self.value);
auto it = queue.begin();
while( it != queue.end() && now >= it->time ) {
while( it != queue.end() && current_block_num >= it->block ) {
set_gas_price(it->price);
it = queue.erase(it);
}

}

uint32_t config_wrapper::get_miner_cut()const {
Expand Down
4 changes: 2 additions & 2 deletions tests/basic_evm_tester.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,13 @@ struct account_code {
using bridge_message = std::variant<bridge_message_v0>;

struct price_queue {
uint64_t time;
uint64_t block;
uint64_t price;
};

} // namespace evm_test

FC_REFLECT(evm_test::price_queue, (time)(price))
FC_REFLECT(evm_test::price_queue, (block)(price))
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))
Expand Down
32 changes: 20 additions & 12 deletions tests/gas_fee_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using namespace eosio::testing;
using namespace evm_test;

#include <eosevm/block_mapping.hpp>

struct gas_fee_evm_tester : basic_evm_tester
{
evm_eoa faucet_eoa;
Expand Down Expand Up @@ -305,6 +307,10 @@ BOOST_FIXTURE_TEST_CASE(set_gas_price_queue, gas_fee_evm_tester)
try {
init();

auto cfg = get_config();

eosevm::block_mapping bm(cfg.genesis_time.sec_since_epoch());

setversion(1, evm_account_name);
produce_blocks(2);

Expand All @@ -325,50 +331,52 @@ try {

// Queue change of gas_price to 10Gwei
setfeeparams({.gas_price = ten_gwei});
auto t1 = control->pending_block_time()+fc::seconds(price_queue_grace_period);

auto t1 = (control->pending_block_time()+fc::seconds(price_queue_grace_period)).time_since_epoch().count();
auto b1 = bm.timestamp_to_evm_block_num(t1)+1;

auto q = get_price_queue();
BOOST_CHECK_EQUAL(q.size(), 1);
BOOST_CHECK_EQUAL(q[0].time, t1.time_since_epoch().count());
BOOST_CHECK_EQUAL(q[0].block, b1);
BOOST_CHECK_EQUAL(q[0].price, ten_gwei);

produce_blocks(100);

// Queue change of gas_price to 30Gwei
setfeeparams({.gas_price = 3*ten_gwei});
auto t2 = control->pending_block_time()+fc::seconds(price_queue_grace_period);
auto t2 = (control->pending_block_time()+fc::seconds(price_queue_grace_period)).time_since_epoch().count();
auto b2 = bm.timestamp_to_evm_block_num(t2)+1;

q = get_price_queue();
BOOST_CHECK_EQUAL(q.size(), 2);
BOOST_CHECK_EQUAL(q[0].time, t1.time_since_epoch().count());
BOOST_CHECK_EQUAL(q[0].block, b1);
BOOST_CHECK_EQUAL(q[0].price, ten_gwei);
BOOST_CHECK_EQUAL(q[1].time, t2.time_since_epoch().count());
BOOST_CHECK_EQUAL(q[1].block, b2);
BOOST_CHECK_EQUAL(q[1].price, 3*ten_gwei);

// Overwrite queue change (same block) 20Gwei
setfeeparams({.gas_price = 2*ten_gwei});

q = get_price_queue();
BOOST_CHECK_EQUAL(q.size(), 2);
BOOST_CHECK_EQUAL(q[0].time, t1.time_since_epoch().count());
BOOST_CHECK_EQUAL(q[0].block, b1);
BOOST_CHECK_EQUAL(q[0].price, ten_gwei);
BOOST_CHECK_EQUAL(q[1].time, t2.time_since_epoch().count());
BOOST_CHECK_EQUAL(q[1].block, b2);
BOOST_CHECK_EQUAL(q[1].price, 2*ten_gwei);

while(control->pending_block_time() != t1) {
while(bm.timestamp_to_evm_block_num(control->pending_block_time().time_since_epoch().count()) != b1) {
produce_blocks(1);
}
trigger_price_queue_processing();

auto cfg = get_config();
cfg = get_config();
BOOST_CHECK_EQUAL(cfg.gas_price, ten_gwei);

q = get_price_queue();
BOOST_CHECK_EQUAL(q.size(), 1);
BOOST_CHECK_EQUAL(q[0].time, t2.time_since_epoch().count());
BOOST_CHECK_EQUAL(q[0].block, b2);
BOOST_CHECK_EQUAL(q[0].price, 2*ten_gwei);

while(control->pending_block_time() != t2) {
while(bm.timestamp_to_evm_block_num(control->pending_block_time().time_since_epoch().count()) != b2) {
produce_blocks(1);
}
trigger_price_queue_processing();
Expand Down
10 changes: 8 additions & 2 deletions tests/gas_param_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using namespace eosio::testing;
using namespace evm_test;

#include <eosevm/block_mapping.hpp>

BOOST_AUTO_TEST_SUITE(evm_gas_param_tests)

struct gas_param_evm_tester : basic_evm_tester
Expand Down Expand Up @@ -111,8 +113,12 @@ BOOST_FIXTURE_TEST_CASE(basic, gas_param_evm_tester) try {
// Change in the gas parameters now takes effect immediately, but not gas price
updtgasparam(asset(10'0000, native_symbol), 1'000'000'000, evm_account_name);

auto t0 = control->pending_block_time() + fc::seconds(price_queue_grace_period);
while(control->pending_block_time() != t0) {
auto cfg = get_config();
eosevm::block_mapping bm(cfg.genesis_time.sec_since_epoch());

auto t0 = (control->pending_block_time() + fc::seconds(price_queue_grace_period)).time_since_epoch().count();
auto b0 = bm.timestamp_to_evm_block_num(t0)+1;
while(bm.timestamp_to_evm_block_num(control->pending_block_time().time_since_epoch().count()) != b0) {
produce_blocks(1);
}

Expand Down
Loading