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

evm: Fix base fee calculation #2098

Merged
merged 4 commits into from
Jun 21, 2023
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
1 change: 1 addition & 0 deletions lib/ain-cpp-imports/src/bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ pub mod ffi {
fn getMinRelayTxFee() -> u64;
fn getEthPrivKey(key_id: [u8; 20]) -> [u8; 32];
fn getStateInputJSON() -> String;
fn pastChangiIntermediateHeight2() -> bool;
}
}
8 changes: 8 additions & 0 deletions lib/ain-cpp-imports/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ mod ffi {
pub fn getStateInputJSON() -> String {
unimplemented!("{}", UNIMPL_MSG)
}
pub fn pastChangiIntermediateHeight2() -> bool {
unimplemented!("{}", UNIMPL_MSG)
}
}

pub fn get_chain_id() -> Result<u64, Box<dyn Error>> {
Expand Down Expand Up @@ -119,5 +122,10 @@ pub fn get_state_input_json() -> Option<String> {
}
}

pub fn past_changi_intermediate_height_2_height() -> Result<bool, Box<dyn Error>> {
let height = ffi::pastChangiIntermediateHeight2();
Ok(height)
}

#[cfg(test)]
mod tests {}
202 changes: 180 additions & 22 deletions lib/ain-evm/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,99 @@ impl BlockHandler {
self.storage.set_base_fee(block.header.hash(), base_fee);
}

fn pre_changi_intermediate_2_base_fee_calculation(
&self,
parent_gas_used: u64,
parent_gas_target: u64,
parent_base_fee: U256,
base_fee_max_change_denominator: U256,
initial_base_fee: U256,
) -> U256 {
match parent_gas_used.cmp(&parent_gas_target) {
// TODO: incorrect calculation, remove before mainnet launch
Ordering::Less => parent_base_fee,
Ordering::Equal => {
let gas_used_delta = parent_gas_used - parent_gas_target;
let base_fee_per_gas_delta = max(
parent_base_fee * gas_used_delta
/ parent_gas_target
/ base_fee_max_change_denominator,
U256::one(),
);

max(parent_base_fee + base_fee_per_gas_delta, initial_base_fee)
}
Ordering::Greater => {
let gas_used_delta = parent_gas_target - parent_gas_used;
let base_fee_per_gas_delta = parent_base_fee * gas_used_delta
/ parent_gas_target
/ base_fee_max_change_denominator;

max(parent_base_fee - base_fee_per_gas_delta, initial_base_fee)
}
}
}

pub fn post_changi_intermediate_2_base_fee_calculation(
&self,
parent_gas_used: u64,
parent_gas_target: u64,
parent_base_fee: U256,
base_fee_max_change_denominator: U256,
initial_base_fee: U256,
) -> U256 {
match parent_gas_used.cmp(&parent_gas_target) {
Ordering::Equal => parent_base_fee,
Ordering::Greater => {
let gas_used_delta = parent_gas_used - parent_gas_target;
let base_fee_per_gas_delta = max(
parent_base_fee * gas_used_delta
/ parent_gas_target
/ base_fee_max_change_denominator,
U256::one(),
);

max(parent_base_fee + base_fee_per_gas_delta, initial_base_fee)
}
Ordering::Less => {
let gas_used_delta = parent_gas_target - parent_gas_used;
let base_fee_per_gas_delta = parent_base_fee * gas_used_delta
/ parent_gas_target
/ base_fee_max_change_denominator;

max(parent_base_fee - base_fee_per_gas_delta, initial_base_fee)
}
}
}

pub fn get_base_fee(
&self,
parent_gas_used: u64,
parent_gas_target: u64,
parent_base_fee: U256,
base_fee_max_change_denominator: U256,
initial_base_fee: U256,
) -> U256 {
match ain_cpp_imports::past_changi_intermediate_height_2_height()
.expect("Unable to get Changi intermediate height 2")
{
true => self.post_changi_intermediate_2_base_fee_calculation(
parent_gas_used,
parent_gas_target,
parent_base_fee,
base_fee_max_change_denominator,
initial_base_fee,
),
false => self.pre_changi_intermediate_2_base_fee_calculation(
parent_gas_used,
parent_gas_target,
parent_base_fee,
base_fee_max_change_denominator,
initial_base_fee,
),
}
}

pub fn calculate_base_fee(&self, parent_hash: H256) -> U256 {
// constants
let base_fee_max_change_denominator = U256::from(8);
Expand All @@ -70,28 +163,13 @@ impl BlockHandler {
let parent_gas_target =
parent_block.header.gas_limit.as_u64() / elasticity_multiplier.as_u64();

match parent_gas_used.cmp(&parent_gas_target) {
Ordering::Less => parent_base_fee,
Ordering::Equal => {
let gas_used_delta = parent_gas_used - parent_gas_target;
let base_fee_per_gas_delta = max(
parent_base_fee * gas_used_delta
/ parent_gas_target
/ base_fee_max_change_denominator,
U256::one(),
);

max(parent_base_fee + base_fee_per_gas_delta, INITIAL_BASE_FEE)
}
Ordering::Greater => {
let gas_used_delta = parent_gas_target - parent_gas_used;
let base_fee_per_gas_delta = parent_base_fee * gas_used_delta
/ parent_gas_target
/ base_fee_max_change_denominator;

max(parent_base_fee - base_fee_per_gas_delta, INITIAL_BASE_FEE)
}
}
self.get_base_fee(
parent_gas_used,
parent_gas_target,
parent_base_fee,
base_fee_max_change_denominator,
INITIAL_BASE_FEE,
)
}

pub fn fee_history(
Expand Down Expand Up @@ -261,3 +339,83 @@ impl BlockHandler {
base_fee + priority_fee
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_base_fee_equal() {
let block = BlockHandler::new(Arc::new(Storage::new()));
assert_eq!(
U256::from(20_000_000_000u64),
block.post_changi_intermediate_2_base_fee_calculation(
15_000_000,
15_000_000,
U256::from(20_000_000_000u64),
U256::from(8),
U256::from(10_000_000_000u64)
)
)
}

#[test]
fn test_base_fee_max_increase() {
let block = BlockHandler::new(Arc::new(Storage::new()));
assert_eq!(
U256::from(22_500_000_000u64), // should increase by 12.5%
block.post_changi_intermediate_2_base_fee_calculation(
30_000_000,
15_000_000,
U256::from(20_000_000_000u64),
U256::from(8),
U256::from(10_000_000_000u64)
)
)
}

#[test]
fn test_base_fee_increase() {
let block = BlockHandler::new(Arc::new(Storage::new()));
assert_eq!(
U256::from(20_833_333_333u64), // should increase by ~4.15%
block.post_changi_intermediate_2_base_fee_calculation(
20_000_000,
15_000_000,
U256::from(20_000_000_000u64),
U256::from(8),
U256::from(10_000_000_000u64)
)
)
}

#[test]
fn test_base_fee_max_decrease() {
let block = BlockHandler::new(Arc::new(Storage::new()));
assert_eq!(
U256::from(17_500_000_000u64), // should decrease by 12.5%
block.post_changi_intermediate_2_base_fee_calculation(
0,
15_000_000,
U256::from(20_000_000_000u64),
U256::from(8),
U256::from(10_000_000_000u64)
)
)
}

#[test]
fn test_base_fee_decrease() {
let block = BlockHandler::new(Arc::new(Storage::new()));
assert_eq!(
U256::from(19_166_666_667u64), // should increase by ~4.15%
block.post_changi_intermediate_2_base_fee_calculation(
10_000_000,
15_000_000,
U256::from(20_000_000_000u64),
U256::from(8),
U256::from(10_000_000_000u64)
)
)
}
}
1 change: 1 addition & 0 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,7 @@ class CChangiParams : public CChainParams {
consensus.GrandCentralEpilogueHeight = 1438200;
consensus.NextNetworkUpgradeHeight = 1586750;
consensus.ChangiIntermediateHeight = 1717800;
consensus.ChangiIntermediateHeight2 = 1717493;

consensus.pos.diffLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
consensus.pos.nTargetTimespan = 5 * 60; // 5 min == 10 blocks
Expand Down
1 change: 1 addition & 0 deletions src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ struct Params {
int GrandCentralEpilogueHeight;
int NextNetworkUpgradeHeight;
int ChangiIntermediateHeight; // To be changed to NextNetworkUpgradeHeight on mainnet release
int ChangiIntermediateHeight2; // To be changed to NextNetworkUpgradeHeight on mainnet release

/** Foundation share after AMK, normalized to COIN = 100% */
CAmount foundationShareDFIP1;
Expand Down
4 changes: 4 additions & 0 deletions src/ffi/ffiexports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,7 @@ std::array<uint8_t, 32> getEthPrivKey(std::array<uint8_t, 20> keyID) {
rust::string getStateInputJSON() {
return gArgs.GetArg("-ethstartstate", "");
}

bool pastChangiIntermediateHeight2() {
return ::ChainActive().Height() >= Params().GetConsensus().ChangiIntermediateHeight2;
}
1 change: 1 addition & 0 deletions src/ffi/ffiexports.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ uint64_t getNativeTxSize(rust::Vec<uint8_t> rawTransaction);
uint64_t getMinRelayTxFee();
std::array<uint8_t, 32> getEthPrivKey(std::array<uint8_t, 20> keyID);
rust::string getStateInputJSON();
bool pastChangiIntermediateHeight2();

#endif // DEFI_FFI_FFIEXPORTS_H