diff --git a/src/contracts/erc20.rs b/src/contracts/erc20.rs index 960e35dd5..0a3ea0d07 100644 --- a/src/contracts/erc20.rs +++ b/src/contracts/erc20.rs @@ -13,6 +13,7 @@ use starknet_crypto::FieldElement; use crate::contracts::kakarot_contract::KakarotCoreReader; use crate::contracts::kakarot_contract::Uint256 as CairoUint256; +use crate::into_via_wrapper; use crate::models::block::EthBlockId; use crate::models::felt::Felt252Wrapper; use crate::starknet_client::constants::TX_ORIGIN_ZERO; @@ -49,7 +50,7 @@ impl EthereumErc20

{ let block_id = EthBlockId::new(block_id); let block_id: StarknetBlockId = block_id.try_into()?; - let origin = Felt252Wrapper::from(*TX_ORIGIN_ZERO); + let origin = into_via_wrapper!(*TX_ORIGIN_ZERO); let kakarot_reader = KakarotCoreReader::new(self.kakarot_address, &self.provider); @@ -58,7 +59,7 @@ impl EthereumErc20

{ let (_, return_data, success, _) = kakarot_reader .eth_call( - &origin.into(), + &origin, &self.address, &gas_limit, &gas_price, diff --git a/src/eth_rpc/servers/eth_rpc.rs b/src/eth_rpc/servers/eth_rpc.rs index 8e525be05..17d91c93e 100644 --- a/src/eth_rpc/servers/eth_rpc.rs +++ b/src/eth_rpc/servers/eth_rpc.rs @@ -1,6 +1,5 @@ use std::sync::Arc; -use crate::into_via_wrapper; use crate::models::block::EthBlockId; use crate::models::event::StarknetEvent; use crate::models::event_filter::EthEventFilter; @@ -11,6 +10,7 @@ use crate::starknet_client::constants::{CHAIN_ID, CHUNK_SIZE_LIMIT}; use crate::starknet_client::errors::EthApiError; use crate::starknet_client::helpers::try_from_u8_iterator; use crate::starknet_client::{ContractAccountReader, KakarotClient}; +use crate::{into_via_try_wrapper, into_via_wrapper}; use jsonrpsee::core::{async_trait, RpcResult as Result}; use reth_primitives::{AccessListWithGasUsed, Address, BlockId, BlockNumberOrTag, Bytes, H256, H64, U128, U256, U64}; use reth_rpc_types::{ @@ -181,11 +181,11 @@ impl EthApiServer for KakarotEthRpc

{ #[tracing::instrument(skip_all, ret, fields(hash = %hash))] async fn transaction_receipt(&self, hash: H256) -> Result> { // TODO: Error when trying to transform 32 bytes hash to FieldElement - let transaction_hash: Felt252Wrapper = hash.try_into().map_err(EthApiError::from)?; + let transaction_hash = into_via_try_wrapper!(hash); let starknet_tx_receipt: TransactionReceiptWrapper = match self .kakarot_client .starknet_provider() - .get_transaction_receipt::(transaction_hash.into()) + .get_transaction_receipt::(transaction_hash) .await { Err(_) => return Ok(None), @@ -225,14 +225,14 @@ impl EthApiServer for KakarotEthRpc

{ let block_id = block_id.unwrap_or(BlockId::Number(BlockNumberOrTag::Latest)); let starknet_block_id: StarknetBlockId = EthBlockId::new(block_id).try_into().map_err(EthApiError::from)?; - let starknet_contract_address = - self.kakarot_client.compute_starknet_address(&address, &starknet_block_id).await?; + let starknet_contract_address = self.kakarot_client.compute_starknet_address(&address).await?; let provider = self.kakarot_client.starknet_provider(); // Get the nonce of the contract account -> a storage variable - let contract_account = ContractAccountReader::new(starknet_contract_address, &provider); - let (_, bytecode) = contract_account.bytecode().call().await.map_err(EthApiError::from)?; + let contract_account = ContractAccountReader::new(starknet_contract_address, provider); + let (_, bytecode) = + contract_account.bytecode().block_id(starknet_block_id).call().await.map_err(EthApiError::from)?; Ok(Bytes::from(try_from_u8_iterator::<_, Vec>(bytecode.0.into_iter()))) } diff --git a/src/models/block.rs b/src/models/block.rs index e5d7790ad..3511f142d 100644 --- a/src/models/block.rs +++ b/src/models/block.rs @@ -7,6 +7,7 @@ use starknet::core::types::{ use starknet::providers::Provider; use super::felt::Felt252Wrapper; +use crate::into_via_try_wrapper; use crate::models::errors::ConversionError; use crate::starknet_client::constants::{EARLIEST_BLOCK_NUMBER, GAS_LIMIT, GAS_USED, SIZE}; use crate::starknet_client::KakarotClient; @@ -23,10 +24,7 @@ impl TryFrom for StarknetBlockId { type Error = ConversionError; fn try_from(eth_block_id: EthBlockId) -> Result { match eth_block_id.0 { - EthereumBlockId::Hash(hash) => { - let hash: Felt252Wrapper = hash.block_hash.try_into()?; - Ok(Self::Hash(hash.into())) - } + EthereumBlockId::Hash(hash) => Ok(Self::Hash(into_via_try_wrapper!(hash.block_hash))), EthereumBlockId::Number(block_number_or_tag) => { let block_number_or_tag: EthBlockNumberOrTag = block_number_or_tag.into(); Ok(block_number_or_tag.into()) diff --git a/src/models/errors.rs b/src/models/errors.rs index 48c0f5d38..48d8ee2af 100644 --- a/src/models/errors.rs +++ b/src/models/errors.rs @@ -1,8 +1,9 @@ +use jsonrpsee::types::ErrorObject; use ruint::FromUintError; use starknet::core::types::FromByteArrayError; use thiserror::Error; -use crate::starknet_client::helpers::DataDecodingError; +use crate::starknet_client::{errors::EthApiError, helpers::DataDecodingError}; #[derive(Debug, Error)] /// Conversion error @@ -38,3 +39,10 @@ impl From> for ConversionError { Self::UintConversionError(err.to_string()) } } + +impl From for ErrorObject<'static> { + fn from(err: ConversionError) -> Self { + let err = EthApiError::from(err); + err.into() + } +} diff --git a/src/models/event.rs b/src/models/event.rs index 88467693b..e4ce1cb13 100644 --- a/src/models/event.rs +++ b/src/models/event.rs @@ -1,4 +1,4 @@ -use reth_primitives::{Address, Bytes, H256, U256}; +use reth_primitives::{Bytes, H256, U256}; use reth_rpc_types::Log; use starknet::core::types::Event; use starknet::providers::Provider; @@ -43,7 +43,7 @@ impl StarknetEvent { let (evm_contract_address, keys) = self.0.keys.split_first().ok_or_else(|| EthApiError::KakarotDataFilteringError("Event".into()))?; - let address: Address = try_into_via_wrapper!(*evm_contract_address); + let address = try_into_via_wrapper!(*evm_contract_address); if keys.len() % 2 != 0 { return Err(anyhow::anyhow!("Not a convertible event: Keys length is not even").into()); diff --git a/src/models/transaction/transaction.rs b/src/models/transaction/transaction.rs index 415bcfdcf..e764c5238 100644 --- a/src/models/transaction/transaction.rs +++ b/src/models/transaction/transaction.rs @@ -3,6 +3,7 @@ use reth_rpc_types::{Signature, Transaction as EthTransaction}; use starknet::core::types::{BlockId as StarknetBlockId, FieldElement, InvokeTransaction, StarknetError, Transaction}; use starknet::providers::{MaybeUnknownErrorCode, Provider, ProviderError, StarknetErrorWithMessage}; +use crate::into_via_try_wrapper; use crate::models::call::{Call, Calls}; use crate::models::errors::ConversionError; use crate::models::felt::Felt252Wrapper; @@ -64,7 +65,7 @@ impl StarknetTransaction { let hash = self.transaction_hash(); let starknet_block_id = match block_hash { - Some(block_hash) => StarknetBlockId::Hash(TryInto::::try_into(block_hash)?.into()), + Some(block_hash) => StarknetBlockId::Hash(into_via_try_wrapper!(block_hash)), None => match block_number { Some(block_number) => StarknetBlockId::Number(TryInto::::try_into(block_number)?), None => { diff --git a/src/models/transaction/transaction_signed.rs b/src/models/transaction/transaction_signed.rs index 1b94b14e1..5a983457e 100644 --- a/src/models/transaction/transaction_signed.rs +++ b/src/models/transaction/transaction_signed.rs @@ -1,6 +1,6 @@ use reth_primitives::{Bytes, TransactionSigned}; use reth_rlp::Decodable as _; -use starknet::core::types::{BlockId as StarknetBlockId, BlockTag, BroadcastedInvokeTransaction}; +use starknet::core::types::BroadcastedInvokeTransaction; use starknet::providers::Provider; use starknet_crypto::FieldElement; use tracing::debug; @@ -34,9 +34,7 @@ impl StarknetTransactionSigned { EthApiError::Other(anyhow::anyhow!("Kakarot send_transaction: signature ecrecover failed")) })?; - let starknet_block_id = StarknetBlockId::Tag(BlockTag::Latest); - - let starknet_address = client.compute_starknet_address(&evm_address, &starknet_block_id).await?; + let starknet_address = client.compute_starknet_address(&evm_address).await?; let nonce = FieldElement::from(transaction.nonce()); diff --git a/src/models/transaction_receipt.rs b/src/models/transaction_receipt.rs index 73ee74266..97180fce2 100644 --- a/src/models/transaction_receipt.rs +++ b/src/models/transaction_receipt.rs @@ -6,7 +6,7 @@ use starknet::core::types::{ ExecutionResult, InvokeTransactionReceipt, MaybePendingTransactionReceipt, TransactionReceipt, }; use starknet::providers::Provider; -use tracing::debug; +use tracing::{debug, error}; use super::event::StarknetEvent; use super::felt::Felt252Wrapper; @@ -69,7 +69,7 @@ impl StarknetTransactionReceipt { } } ExecutionResult::Reverted { ref reason } => { - tracing::error!("Transaction reverted with {reason}"); + error!("Transaction reverted with {reason}"); None } }; diff --git a/src/starknet_client/mod.rs b/src/starknet_client/mod.rs index 46f07a7d5..f17c2f7a8 100644 --- a/src/starknet_client/mod.rs +++ b/src/starknet_client/mod.rs @@ -18,7 +18,7 @@ use starknet::core::types::{ FieldElement, MaybePendingBlockWithTxHashes, MaybePendingBlockWithTxs, MaybePendingTransactionReceipt, StarknetError, Transaction as TransactionType, TransactionReceipt as StarknetTransactionReceipt, }; -use starknet::core::utils::get_storage_var_address; +use starknet::core::utils::{get_contract_address, get_storage_var_address}; use starknet::providers::sequencer::models::{FeeEstimate, FeeUnit, TransactionSimulationInfo, TransactionTrace}; use starknet::providers::{MaybeUnknownErrorCode, Provider, ProviderError, StarknetErrorWithMessage}; use starknet_abigen_parser::cairo_types::CairoArrayLegacy; @@ -213,7 +213,7 @@ impl KakarotClient

{ #[tracing::instrument(skip_all, level = "debug")] pub async fn nonce(&self, ethereum_address: Address, block_id: BlockId) -> Result { let starknet_block_id: StarknetBlockId = EthBlockId::new(block_id).try_into()?; - let starknet_address = self.compute_starknet_address(ðereum_address, &starknet_block_id).await?; + let starknet_address = self.compute_starknet_address(ðereum_address).await?; let proxy = ProxyReader::new(starknet_address, &self.starknet_provider); let class_hash = proxy.get_implementation().call().await.map_or(FieldElement::ZERO, |class_hash| class_hash); @@ -222,7 +222,7 @@ impl KakarotClient

{ debug!("contract account"); // Get the nonce of the contract account -> a storage variable let contract_account = ContractAccountReader::new(starknet_address, &self.starknet_provider); - Ok(into_via_wrapper!(contract_account.get_nonce().call().await?)) + Ok(into_via_wrapper!(contract_account.get_nonce().block_id(starknet_block_id).call().await?)) } else { debug!("eoa"); // Get the nonce of the Eoa -> the protocol level nonce @@ -247,12 +247,12 @@ impl KakarotClient

{ #[tracing::instrument(skip_all, level = "debug")] pub async fn balance(&self, ethereum_address: Address, block_id: BlockId) -> Result { let starknet_block_id: StarknetBlockId = EthBlockId::new(block_id).try_into()?; - let starknet_address = self.compute_starknet_address(ðereum_address, &starknet_block_id).await?; + let starknet_address = self.compute_starknet_address(ðereum_address).await?; let native_token_address = FieldElement::from_hex_be(STARKNET_NATIVE_TOKEN).unwrap(); let provider = self.starknet_provider(); let native_token = erc20::ERC20Reader::new(native_token_address, &provider); - let balance = native_token.balanceOf(&starknet_address).call().await?; + let balance = native_token.balanceOf(&starknet_address).block_id(starknet_block_id).call().await?; debug!("starknet address {} has balance: {:?}", starknet_address, balance); @@ -267,7 +267,7 @@ impl KakarotClient

{ pub async fn storage_at(&self, address: Address, index: U256, block_id: BlockId) -> Result { let starknet_block_id: StarknetBlockId = EthBlockId::new(block_id).try_into()?; - let starknet_contract_address = self.compute_starknet_address(&address, &starknet_block_id).await?; + let starknet_contract_address = self.compute_starknet_address(&address).await?; let provider = self.starknet_provider(); let contract_account = ContractAccountReader::new(starknet_contract_address, &provider); @@ -277,7 +277,8 @@ impl KakarotClient

{ let storage_address = get_storage_var_address("storage_", &keys).map_err(|e| EthApiError::ConversionError(e.to_string()))?; - let storage: CairoUint256 = contract_account.storage(&storage_address).call().await?; + let storage: CairoUint256 = + contract_account.storage(&storage_address).block_id(starknet_block_id).call().await?; debug!( "storage at starknet address {} key slot {} is {:?}", @@ -299,8 +300,7 @@ impl KakarotClient

{ let handles = token_addresses.into_iter().map(|token_address| { let token_addr: Felt252Wrapper = token_address.into(); - let token = - EthereumErc20::new(token_addr.into(), self.starknet_provider(), self.kakarot_contract.reader.address); + let token = EthereumErc20::new(token_addr.into(), self.starknet_provider(), self.kakarot_address()); let balance = token.balance_of(address.into(), block_id); FutureTokenBalance::new(Box::pin(balance), token_address) @@ -421,14 +421,14 @@ impl KakarotClient

{ let starknet_block_id: StarknetBlockId = EthBlockId::new(block_id).try_into()?; let block_number = self.map_block_id_to_block_number(&starknet_block_id).await?; - let sender_address = self.compute_starknet_address(&from, &starknet_block_id).await?; + let sender_address = self.compute_starknet_address(&from).await?; let mut data = vec![]; tx.encode_without_signature(&mut data); let data = data.into_iter().map(FieldElement::from).collect(); let calldata = prepare_kakarot_eth_send_transaction(self.kakarot_address(), data); - debug!("Kakarot calldata: {:?}", calldata); + debug!("starknet calldata: {:?}", calldata); let tx = BroadcastedInvokeTransaction { max_fee: FieldElement::ZERO, @@ -529,25 +529,12 @@ impl KakarotClient

{ /// Returns the EVM address associated with a given Starknet address for a given block id /// by calling the `compute_starknet_address` function on the Kakarot contract. #[tracing::instrument(skip_all, level = "debug")] - pub async fn compute_starknet_address( - &self, - ethereum_address: &Address, - starknet_block_id: &StarknetBlockId, - ) -> Result { + pub async fn compute_starknet_address(&self, ethereum_address: &Address) -> Result { let ethereum_address = into_via_wrapper!(*ethereum_address); - debug!("ethereum address: {:?}", ethereum_address); - - let starknet_address = self - .kakarot_contract - .reader - .compute_starknet_address(ðereum_address) - .block_id(*starknet_block_id) - .call() - .await?; - + let starknet_address = + get_contract_address(ethereum_address, self.proxy_account_class_hash(), &[], self.kakarot_address()); debug!("starknet address: {:?}", starknet_address); - Ok(starknet_address) } diff --git a/tests/starknet_client.rs b/tests/starknet_client.rs index 6f5d5e0ba..05d22f157 100644 --- a/tests/starknet_client.rs +++ b/tests/starknet_client.rs @@ -1,8 +1,10 @@ #[cfg(test)] mod test_utils; +use kakarot_rpc::contracts::kakarot_contract::KakarotCoreReader; use kakarot_rpc::models::felt::Felt252Wrapper; use rstest::*; use starknet::providers::Provider; +use starknet_crypto::FieldElement; use test_utils::eoa::Eoa; use test_utils::evm_contract::KakarotEvmContract; use test_utils::fixtures::{counter, katana}; @@ -61,6 +63,21 @@ async fn test_fee_history(#[future] katana: Katana) { assert_eq!(fee_history.oldest_block, U256::ZERO); } +#[rstest] +#[awt] +#[tokio::test(flavor = "multi_thread")] +async fn test_compute_starknet_address(#[future] katana: Katana) { + let client = katana.client(); + let kakarot_contract = KakarotCoreReader::new(client.kakarot_address(), client.starknet_provider()); + let address = 0x1234u64; + + let starknet_address = client.compute_starknet_address(&Address::from(address)).await.unwrap(); + let expected_address = + kakarot_contract.compute_starknet_address(&FieldElement::from(address)).call().await.unwrap(); + + assert_eq!(starknet_address, expected_address); +} + #[tokio::test] // Ignore until #649 is fixed #[ignore] diff --git a/tests/test_utils/constants.rs b/tests/test_utils/constants.rs index 47a994611..6577e49f7 100644 --- a/tests/test_utils/constants.rs +++ b/tests/test_utils/constants.rs @@ -1,12 +1,6 @@ -use std::str::FromStr; - -use lazy_static::lazy_static; -use reth_primitives::Address; use serde_json::Value; use starknet_crypto::FieldElement; -pub const ACCOUNT_ADDRESS_HEX: &str = "0x044021e020d096bd375bddc0f8d122ecae520003ca4c2691cccaa9ad5b53eed7"; - lazy_static::lazy_static! { pub static ref KAKAROT_ADDRESS: FieldElement = { let deployments = include_str!("../../lib/kakarot/deployments/katana/deployments.json"); @@ -16,13 +10,3 @@ lazy_static::lazy_static! { object.get("kakarot").unwrap().get("address").unwrap().as_str().unwrap().parse().unwrap() }; } - -// Testnet values -// TODO: Delete when simulateTransaction is merged in Madara -lazy_static! { - pub static ref ACCOUNT_ADDRESS: FieldElement = FieldElement::from_hex_be(ACCOUNT_ADDRESS_HEX).unwrap(); - pub static ref ACCOUNT_ADDRESS_EVM: Address = - Address::from_str("0x54B288676B749DEF5FC10EB17244FE2C87375dE1").unwrap(); - pub static ref COUNTER_ADDRESS_EVM: Address = - Address::from_str("0x2e11ed82f5ec165ab8ce3cc094f025fe7527f4d1").unwrap(); -} diff --git a/tests/test_utils/eoa.rs b/tests/test_utils/eoa.rs index c60282b92..eed2ac778 100644 --- a/tests/test_utils/eoa.rs +++ b/tests/test_utils/eoa.rs @@ -9,7 +9,7 @@ use reth_primitives::{ sign_message, Address, BlockId, BlockNumberOrTag, Bytes, Transaction, TransactionKind, TransactionSigned, TxEip1559, H256, U256, }; -use starknet::core::types::{BlockId as StarknetBlockId, BlockTag, MaybePendingTransactionReceipt, TransactionReceipt}; +use starknet::core::types::{MaybePendingTransactionReceipt, TransactionReceipt}; use starknet::core::utils::get_selector_from_name; use starknet::providers::Provider; use starknet_crypto::FieldElement; @@ -24,7 +24,7 @@ use crate::test_utils::tx_waiter::watch_tx; pub trait Eoa { async fn starknet_address(&self) -> Result { let client: &KakarotClient

= self.client(); - Ok(client.compute_starknet_address(&self.evm_address()?, &StarknetBlockId::Tag(BlockTag::Latest)).await?) + Ok(client.compute_starknet_address(&self.evm_address()?).await?) } fn evm_address(&self) -> Result { let wallet = LocalWallet::from_bytes(self.private_key().as_bytes())?; @@ -101,7 +101,7 @@ impl KakarotEOA

{ let maybe_receipt = self .provider() - .get_transaction_receipt(FieldElement::from(tx_hash.clone())) + .get_transaction_receipt(FieldElement::from(tx_hash)) .await .expect("Failed to get transaction receipt after retries");