diff --git a/docker-compose.yaml b/docker-compose.yaml index 0cdae19fa..29092a9a7 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -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: @@ -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: diff --git a/src/eth_provider/provider.rs b/src/eth_provider/provider.rs index fcc0f3ffb..476dd5bb8 100644 --- a/src/eth_provider/provider.rs +++ b/src/eth_provider/provider.rs @@ -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}; @@ -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>, ) -> EthProviderResult; @@ -417,34 +418,31 @@ where async fn fee_history( &self, - mut block_count: U256, + block_count: U64HexOrNumber, newest_block: BlockNumberOrTag, _reward_percentiles: Option>, ) -> EthProviderResult { - 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::(); + 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 = 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| { @@ -458,10 +456,15 @@ where }) .collect::>(); + let mut base_fee_per_gas = + blocks.iter().map(|header| header.header.base_fee_per_gas.unwrap_or_default()).collect::>(); + // 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() }) diff --git a/src/eth_rpc/servers/eth_rpc.rs b/src/eth_rpc/servers/eth_rpc.rs index a8a8442d9..0d7888f07 100644 --- a/src/eth_rpc/servers/eth_rpc.rs +++ b/src/eth_rpc/servers/eth_rpc.rs @@ -184,7 +184,7 @@ where newest_block: BlockNumberOrTag, reward_percentiles: Option>, ) -> Result { - 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)] diff --git a/src/test_utils/mongo/mod.rs b/src/test_utils/mongo/mod.rs index 7458b55ca..fb7cbad15 100644 --- a/src/test_utils/mongo/mod.rs +++ b/src/test_utils/mongo/mod.rs @@ -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, @@ -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, @@ -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, @@ -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, @@ -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, diff --git a/tests/eth_provider.rs b/tests/eth_provider.rs index 0aeee6b02..a325b4a25 100644 --- a/tests/eth_provider.rs +++ b/tests/eth_provider.rs @@ -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}; @@ -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); } @@ -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()); }