Skip to content

Commit

Permalink
Fix/fee history base fee (kkrt-labs#853)
Browse files Browse the repository at this point in the history
* fix: use real basefee in fee history

* fix: fix docker compose

* fix pr comments

* saturating add and sub

* add comment:
  • Loading branch information
Eikix authored Mar 14, 2024
1 parent 1c6aad0 commit 4d16862
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 40 deletions.
17 changes: 10 additions & 7 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,15 @@ services:
# Always pull the latest image, until we use release tags
pull_policy: always
environment:
# Pre-funded Katana accounts
- ACCOUNT_ADDRESS=0xb3ff441a68610b30fd5e2abbf3a1548eb6ba6f3559f2862bf2dc757e5828ca
- PRIVATE_KEY=0x2bbf4f9fd0bbb2e60b0316c1fe0b76cf7a4d0198bd493ced9b8df2a3a24d68a
# EVM Private key of the Anvil default Account (address 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266)
- EVM_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
- RPC_URL=http://starknet:5050
- KATANA_RPC_URL=http://starknet:5050
- STARKNET_NETWORK=katana
volumes:
# Since STARKNET_NETWORK is not set, deployments will be saved without network folder
# Since STARKNET_NETWORK is set to katana, the deployments json files will be saved with katana network folder
- deployments:/app/kakarot/deployments
depends_on:
starknet:
Expand All @@ -50,11 +53,11 @@ services:
# First line overrides an existing .env, if any.
# This is to make sure that it is clean even though docker volume was not cleaned.
- |
echo "KAKAROT_ADDRESS=$$(jq -r '.kakarot.address' /deployments/custom-rpc/deployments.json)" > /deployments/.env;
echo "DEPLOYER_ACCOUNT_ADDRESS=$$(jq -r '.deployer_account.address' /deployments/custom-rpc/deployments.json)" >> /deployments/.env;
echo "PROXY_ACCOUNT_CLASS_HASH=$$(jq -r '.proxy' /deployments/custom-rpc/declarations.json)" >> /deployments/.env
echo "EXTERNALLY_OWNED_ACCOUNT_CLASS_HASH=$$(jq -r '.externally_owned_account' /deployments/custom-rpc/declarations.json)" >> /deployments/.env
echo "CONTRACT_ACCOUNT_CLASS_HASH=$$(jq -r '.contract_account' /deployments/custom-rpc/declarations.json)" >> /deployments/.env
echo "KAKAROT_ADDRESS=$$(jq -r '.kakarot.address' /deployments/katana/deployments.json)" > /deployments/.env;
echo "DEPLOYER_ACCOUNT_ADDRESS=$$(jq -r '.deployer_account.address' /deployments/katana/deployments.json)" >> /deployments/.env;
echo "PROXY_ACCOUNT_CLASS_HASH=$$(jq -r '.proxy' /deployments/katana/declarations.json)" >> /deployments/.env
echo "EXTERNALLY_OWNED_ACCOUNT_CLASS_HASH=$$(jq -r '.externally_owned_account' /deployments/katana/declarations.json)" >> /deployments/.env
echo "CONTRACT_ACCOUNT_CLASS_HASH=$$(jq -r '.contract_account' /deployments/katana/declarations.json)" >> /deployments/.env
volumes:
- deployments:/deployments
depends_on:
Expand Down
37 changes: 20 additions & 17 deletions src/eth_provider/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use reth_rpc_types::Index;
use reth_rpc_types::JsonStorageKey;
use reth_rpc_types::TransactionReceipt;
use reth_rpc_types::TransactionRequest;
use reth_rpc_types::U64HexOrNumber;
use reth_rpc_types::ValueOrArray;
use reth_rpc_types::{Block, BlockTransactions, RichBlock};
use reth_rpc_types::{SyncInfo, SyncStatus};
Expand Down Expand Up @@ -124,7 +125,7 @@ pub trait EthereumProvider {
/// Returns the fee history given a block count and a newest block number.
async fn fee_history(
&self,
block_count: U256,
block_count: U64HexOrNumber,
newest_block: BlockNumberOrTag,
reward_percentiles: Option<Vec<f64>>,
) -> EthProviderResult<FeeHistory>;
Expand Down Expand Up @@ -417,34 +418,31 @@ where

async fn fee_history(
&self,
mut block_count: U256,
block_count: U64HexOrNumber,
newest_block: BlockNumberOrTag,
_reward_percentiles: Option<Vec<f64>>,
) -> EthProviderResult<FeeHistory> {
if block_count == U256::ZERO {
if block_count.to() == 0 {
return Ok(FeeHistory::default());
}

let end_block = U256::from(self.tag_into_block_number(newest_block).await?);
let end_block_plus = end_block + U256::from(1);
let end_block = self.tag_into_block_number(newest_block).await?;
let end_block = end_block.to::<u64>();
let end_block_plus = end_block.saturating_add(1);

// Clamp the block count to the range [0, end_block_plus]
block_count = Ord::clamp(block_count, U256::ZERO, end_block_plus);
let start_block = end_block_plus - block_count;

let bc = usize::try_from(block_count).map_err(|e| ConversionError::ValueOutOfRange(e.to_string()))?;
// We add one to the block count and fill with 0's.
// This comes from the rpc spec: `An array of block base fees per gas.
// This includes the next block after the newest of the returned range,
// because this value can be derived from the newest block. Zeroes are returned for pre-EIP-1559 blocks.`
// Since Kakarot doesn't support EIP-1559 yet, we just fill with 0's.
let base_fee_per_gas = vec![U256::ZERO; bc + 1];
// 0 <= start_block < end_block
let start_block = end_block_plus.saturating_sub(block_count.to());

// TODO: check if we should use a projection since we only need the gasLimit and gasUsed.
// This means we need to introduce a new type for the StoredHeader.
let header_filter =
doc! {"header.number": {"$gte": format_hex(start_block, 64), "$lte": format_hex(end_block, 64)}};
let blocks: Vec<StoredHeader> = self.database.get("headers", header_filter, None).await?;

if blocks.is_empty() {
return Err(EthProviderError::ValueNotFound("Block".to_string()));
}

let gas_used_ratio = blocks
.iter()
.map(|header| {
Expand All @@ -458,10 +456,15 @@ where
})
.collect::<Vec<_>>();

let mut base_fee_per_gas =
blocks.iter().map(|header| header.header.base_fee_per_gas.unwrap_or_default()).collect::<Vec<_>>();
// TODO(EIP1559): Remove this when proper base fee computation: if gas_ratio > 50%, increase base_fee_per_gas
base_fee_per_gas.extend_from_within((base_fee_per_gas.len() - 1)..);

Ok(FeeHistory {
base_fee_per_gas,
gas_used_ratio,
oldest_block: start_block,
oldest_block: U256::from(start_block),
reward: Some(vec![]),
..Default::default()
})
Expand Down
2 changes: 1 addition & 1 deletion src/eth_rpc/servers/eth_rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ where
newest_block: BlockNumberOrTag,
reward_percentiles: Option<Vec<f64>>,
) -> Result<FeeHistory> {
Ok(self.eth_provider.fee_history(U256::from(block_count.to()), newest_block, reward_percentiles).await?)
Ok(self.eth_provider.fee_history(block_count, newest_block, reward_percentiles).await?)
}

#[tracing::instrument(skip_all, ret, err)]
Expand Down
10 changes: 5 additions & 5 deletions src/test_utils/mongo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pub async fn mock_database() -> Database {
mongodb.collection("headers"),
vec![
doc! {"header": doc! {
"hash": format!("0x{:064x}", *BLOCK_HASH),
"hash": &hash_256_zero,
"parentHash": &hash_256_zero,
"sha3Uncles": &hash_256_zero,
"miner": &address_zero,
Expand All @@ -74,7 +74,7 @@ pub async fn mock_database() -> Database {
"withdrawalsRoot": &empty_root_hash,
}},
doc! {"header": doc! {
"hash": format!("0x{:064x}", *BLOCK_HASH),
"hash": &hash_256_zero,
"parentHash": &hash_256_zero,
"sha3Uncles": &hash_256_zero,
"miner": &address_zero,
Expand All @@ -93,7 +93,7 @@ pub async fn mock_database() -> Database {
"withdrawalsRoot": &empty_root_hash,
}},
doc! {"header": doc! {
"hash": format!("0x{:064x}", *BLOCK_HASH),
"hash": &hash_256_zero,
"parentHash": &hash_256_zero,
"sha3Uncles": &hash_256_zero,
"miner": &address_zero,
Expand All @@ -112,7 +112,7 @@ pub async fn mock_database() -> Database {
"withdrawalsRoot": &empty_root_hash,
}},
doc! {"header": doc! {
"hash": format!("0x{:064x}", *BLOCK_HASH),
"hash": &hash_256_zero,
"parentHash": &hash_256_zero,
"sha3Uncles": &hash_256_zero,
"miner": &address_zero,
Expand All @@ -131,7 +131,7 @@ pub async fn mock_database() -> Database {
"withdrawalsRoot": &empty_root_hash,
}},
doc! {"header": doc! {
"hash": &hash_256_zero,
"hash": format!("0x{:064x}", *BLOCK_HASH),
"parentHash": &hash_256_zero,
"sha3Uncles": &hash_256_zero,
"miner": &address_zero,
Expand Down
22 changes: 12 additions & 10 deletions tests/eth_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use kakarot_rpc::test_utils::fixtures::{counter, katana, setup};
use kakarot_rpc::test_utils::mongo::{BLOCK_HASH, BLOCK_NUMBER};
use kakarot_rpc::test_utils::{evm_contract::KakarotEvmContract, katana::Katana};
use reth_rpc_types::request::TransactionInput;
use reth_rpc_types::{JsonStorageKey, RpcBlockHash, TransactionRequest};
use reth_rpc_types::{JsonStorageKey, RpcBlockHash, TransactionRequest, U64HexOrNumber};
use rstest::*;

use reth_primitives::{Address, BlockNumberOrTag, Bytes, B256, U256, U64};
Expand Down Expand Up @@ -263,16 +263,18 @@ async fn test_fee_history(#[future] katana: Katana, _setup: ()) {
// Given
let eth_provider = katana.eth_provider();
let newest_block = 3;
let block_count = 100usize;
let block_count = 100u64;

// When
let fee_history =
eth_provider.fee_history(U256::from(block_count), BlockNumberOrTag::Number(newest_block), None).await.unwrap();
let fee_history = eth_provider
.fee_history(U64HexOrNumber::from(block_count), BlockNumberOrTag::Number(newest_block), None)
.await
.unwrap();

// Then
let actual_block_count = min(block_count, newest_block as usize + 1);
assert_eq!(fee_history.base_fee_per_gas.len(), actual_block_count + 1);
assert_eq!(fee_history.gas_used_ratio.len(), actual_block_count);
let actual_block_count = min(block_count, newest_block + 1);
assert_eq!(fee_history.base_fee_per_gas.len(), actual_block_count as usize + 1);
assert_eq!(fee_history.gas_used_ratio.len(), actual_block_count as usize);
assert_eq!(fee_history.oldest_block, U256::ZERO);
}

Expand Down Expand Up @@ -376,15 +378,15 @@ async fn test_to_starknet_block_id(#[future] katana: Katana, _setup: ()) {
let some_block_hash = reth_rpc_types::BlockId::Hash(RpcBlockHash::from(*BLOCK_HASH));
let some_starknet_block_hash = eth_provider.to_starknet_block_id(some_block_hash).await.unwrap();

let some_block_number = reth_rpc_types::BlockId::Number(BlockNumberOrTag::Number(0));
let some_block_number = reth_rpc_types::BlockId::Number(BlockNumberOrTag::Number(1));
let some_starknet_block_number = eth_provider.to_starknet_block_id(some_block_number).await.unwrap();

let unknown_block_number = reth_rpc_types::BlockId::Number(BlockNumberOrTag::Number(u64::MAX));
let unknown_starknet_block_number = eth_provider.to_starknet_block_id(unknown_block_number).await;

// Then
assert_eq!(pending_starknet_block_id, starknet::core::types::BlockId::Tag(BlockTag::Pending));
assert_eq!(pending_starknet_block_id, starknet::core::types::BlockId::Number(0x1234_u64));
assert_eq!(some_starknet_block_hash, starknet::core::types::BlockId::Hash(FieldElement::from(0x1234_u64)));
assert_eq!(some_starknet_block_number, starknet::core::types::BlockId::Number(0_u64));
assert_eq!(some_starknet_block_number, starknet::core::types::BlockId::Tag(BlockTag::Pending));
assert!(unknown_starknet_block_number.is_err());
}

0 comments on commit 4d16862

Please sign in to comment.