feat(ethers-core/block): add gas_target and next_block_base_fee fns a… (#1047)

* feat(ethers-core/block): add gas_target and next_block_base_fee fns according to EIP-1559

* fix: feature flag gas_target, and next_block_base_fee to !celo, address review comments

* fix: in decreasing base fee case max(delta, 1) is not used

Refer 599ea45b9e/EIPS/eip-1559.md?plain=1#L193
This commit is contained in:
Meet Mangukiya 2022-03-17 16:14:28 +05:30 committed by GitHub
parent 745d14ea7b
commit 42ead6252d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 75 additions and 0 deletions

View File

@ -1,5 +1,7 @@
// Taken from https://github.com/tomusdrw/rust-web3/blob/master/src/types/block.rs // Taken from https://github.com/tomusdrw/rust-web3/blob/master/src/types/block.rs
use crate::types::{Address, Bloom, Bytes, H256, U256, U64}; use crate::types::{Address, Bloom, Bytes, H256, U256, U64};
#[cfg(not(feature = "celo"))]
use core::cmp::Ordering;
use serde::{ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializer}; use serde::{ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializer};
use std::str::FromStr; use std::str::FromStr;
@ -89,6 +91,52 @@ pub struct Block<TX> {
pub epoch_snark_data: Option<EpochSnarkData>, pub epoch_snark_data: Option<EpochSnarkData>,
} }
// ref https://eips.ethereum.org/EIPS/eip-1559
#[cfg(not(feature = "celo"))]
pub const ELASTICITY_MULTIPLIER: U256 = U256([2u64, 0, 0, 0]);
// max base fee delta is 12.5%
#[cfg(not(feature = "celo"))]
pub const BASE_FEE_MAX_CHANGE_DENOMINATOR: U256 = U256([8u64, 0, 0, 0]);
impl<TX> Block<TX> {
/// The target gas usage as per EIP-1559
#[cfg(not(feature = "celo"))]
pub fn gas_target(&self) -> U256 {
self.gas_limit / ELASTICITY_MULTIPLIER
}
/// The next block's base fee, it is a function of parent block's base fee and gas usage.
/// Reference: https://eips.ethereum.org/EIPS/eip-1559
#[cfg(not(feature = "celo"))]
pub fn next_block_base_fee(&self) -> Option<U256> {
let target_usage = self.gas_target();
let base_fee_per_gas = self.base_fee_per_gas?;
match self.gas_used.cmp(&target_usage) {
Ordering::Greater => {
let gas_used_delta = self.gas_used - self.gas_target();
let base_fee_per_gas_delta = U256::max(
base_fee_per_gas * gas_used_delta /
target_usage /
BASE_FEE_MAX_CHANGE_DENOMINATOR,
U256::from(1u32),
);
let expected_base_fee_per_gas = base_fee_per_gas + base_fee_per_gas_delta;
Some(expected_base_fee_per_gas)
}
Ordering::Less => {
let gas_used_delta = self.gas_target() - self.gas_used;
let base_fee_per_gas_delta = base_fee_per_gas * gas_used_delta /
target_usage /
BASE_FEE_MAX_CHANGE_DENOMINATOR;
let expected_base_fee_per_gas = base_fee_per_gas - base_fee_per_gas_delta;
Some(expected_base_fee_per_gas)
}
Ordering::Equal => self.base_fee_per_gas,
}
}
}
#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)] #[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)]
#[cfg(feature = "celo")] #[cfg(feature = "celo")]
/// Commit-reveal data for generating randomness in the /// Commit-reveal data for generating randomness in the
@ -279,6 +327,33 @@ mod tests {
let block: Block<()> = serde_json::from_value(json).unwrap(); let block: Block<()> = serde_json::from_value(json).unwrap();
assert_eq!(block.base_fee_per_gas, Some(U256::from(7))); assert_eq!(block.base_fee_per_gas, Some(U256::from(7)));
} }
#[test]
fn test_next_block_base_fee() {
// https://etherscan.io/block/14402566
let mut block_14402566 = Block::<TxHash>::default();
block_14402566.number = Some(U64::from(14402566u64));
block_14402566.base_fee_per_gas = Some(U256::from(36_803_013_756u128));
block_14402566.gas_limit = U256::from(30_087_887u128);
block_14402566.gas_used = U256::from(2_023_848u128);
assert_eq!(block_14402566.base_fee_per_gas, Some(U256::from(36_803_013_756u128)));
assert_eq!(block_14402566.gas_target(), U256::from(15_043_943u128));
// next block decreasing base fee https://etherscan.io/block/14402567
assert_eq!(block_14402566.next_block_base_fee(), Some(U256::from(32_821_521_542u128)));
// https://etherscan.io/block/14402712
let mut block_14402712 = Block::<TxHash>::default();
block_14402712.number = Some(U64::from(14402712u64));
block_14402712.base_fee_per_gas = Some(U256::from(24_870_031_149u128));
block_14402712.gas_limit = U256::from(30_000_000u128);
block_14402712.gas_used = U256::from(29_999_374u128);
assert_eq!(block_14402712.base_fee_per_gas, Some(U256::from(24_870_031_149u128)));
assert_eq!(block_14402712.gas_target(), U256::from(15_000_000u128));
// next block increasing base fee https://etherscan.io/block/14402713
assert_eq!(block_14402712.next_block_base_fee(), Some(U256::from(27_978_655_303u128)));
}
} }
#[cfg(test)] #[cfg(test)]