Skip to content

Commit

Permalink
Merge pull request #703 from eosnetworkfoundation/elmato/fix-basefee-…
Browse files Browse the repository at this point in the history
…change

Fix base-fee change on EVM block boundary
  • Loading branch information
elmato committed Apr 24, 2024
2 parents e2d91be + b11d52c commit 6928c65
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 26 deletions.
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

0 comments on commit 6928c65

Please sign in to comment.