From 819b3f83a2d8ea211d2b297e192663ef389132d5 Mon Sep 17 00:00:00 2001
From: Haider-Ali-DS <haiderali.tech_786@outlook.com>
Date: Wed, 22 Feb 2023 17:21:49 +0500
Subject: [PATCH 01/10] ethereum contract send call implementation

---
 chains/ethereum/server/src/lib.rs   | 33 +++++++++--------
 chains/ethereum/server/src/utils.rs | 21 ++++++++++-
 chains/ethereum/tx/Cargo.toml       |  2 +
 chains/ethereum/tx/src/lib.rs       | 57 ++++++++++++++++++++++++++++-
 chains/polkadot/tx/src/lib.rs       | 10 ++++-
 rosetta-client/src/wallet.rs        | 29 +++++++++++++++
 rosetta-core/src/lib.rs             |  2 +
 rosetta-wallet/src/main.rs          | 28 ++++++++++++++
 8 files changed, 163 insertions(+), 19 deletions(-)

diff --git a/chains/ethereum/server/src/lib.rs b/chains/ethereum/server/src/lib.rs
index 55b1f435..4619750b 100644
--- a/chains/ethereum/server/src/lib.rs
+++ b/chains/ethereum/server/src/lib.rs
@@ -1,8 +1,6 @@
 use crate::eth_types::GENESIS_BLOCK_INDEX;
 use crate::utils::{get_block, get_transaction, populate_transactions, EthDetokenizer};
 use anyhow::{anyhow, bail, Context, Result};
-use ethers::abi::Abi;
-use ethers::contract as ethers_contract;
 use ethers::prelude::*;
 use rosetta_config_ethereum::{EthereumMetadata, EthereumMetadataParams};
 use rosetta_server::crypto::address::Address;
@@ -14,6 +12,7 @@ use rosetta_server::types::{
 use rosetta_server::{BlockchainClient, BlockchainConfig};
 use serde_json::Value;
 use std::str::FromStr;
+use utils::parse_method;
 
 mod eth_types;
 mod utils;
@@ -201,10 +200,6 @@ impl BlockchainClient for EthereumClient {
         match call_type.to_lowercase().as_str() {
             "call" => {
                 //process constant call
-                let abi_str = params["abi"].as_str().context("ABI not found")?;
-
-                let abi: Abi = serde_json::from_str(abi_str).map_err(|err| anyhow!(err))?;
-
                 let contract_address = H160::from_str(
                     params["contract_address"]
                         .as_str()
@@ -212,23 +207,29 @@ impl BlockchainClient for EthereumClient {
                 )
                 .map_err(|err| anyhow!(err))?;
 
-                let contract =
-                    ethers_contract::Contract::new(contract_address, abi, self.client.clone());
+                let function = parse_method(&method)?;
+
+                let bytes: Vec<u8> = function.encode_input(&[])?;
+
+                let tx = Eip1559TransactionRequest {
+                    to: Some(contract_address.into()),
+                    data: Some(bytes.into()),
+                    ..Default::default()
+                };
 
-                let value: EthDetokenizer = contract
-                    .method(&method, ())
-                    .map_err(|err| anyhow!(err))?
-                    .call()
-                    .await
-                    .map_err(|err| anyhow!(err))?;
+                let tx = &tx.into();
+                let received_data = self.client.call(tx, None).await?;
+
+                let data: EthDetokenizer = decode_function_data(&function, received_data, false)?;
+
+                let result: Value = serde_json::from_str(&data.json)?;
 
-                let result: Value = serde_json::from_str(&value.json)?;
                 return Ok(result);
             }
             "storage" => {
                 //process storage call
                 let from = H160::from_str(
-                    params["address"]
+                    params["contract_address"]
                         .as_str()
                         .context("address field not found")?,
                 )
diff --git a/chains/ethereum/server/src/utils.rs b/chains/ethereum/server/src/utils.rs
index 834f32b0..706c243c 100644
--- a/chains/ethereum/server/src/utils.rs
+++ b/chains/ethereum/server/src/utils.rs
@@ -7,7 +7,7 @@ use crate::eth_types::{
 };
 use anyhow::{anyhow, bail, Context, Result};
 use ethers::{
-    abi::{Detokenize, InvalidOutputType, Token},
+    abi::{Abi, Detokenize, Function, HumanReadableParser, InvalidOutputType, Token},
     prelude::*,
 };
 use ethers::{
@@ -729,6 +729,25 @@ fn effective_gas_price(tx: &Transaction, base_fee: Option<U256>) -> Result<U256>
     Ok(base_fee + tx_max_priority_fee_per_gas)
 }
 
+pub fn parse_method(method: &str) -> Result<Function> {
+    let parse_result = HumanReadableParser::parse_function(method);
+    if parse_result.is_ok() {
+        parse_result.map_err(|e| anyhow!(e))
+    } else {
+        let json_parse: Result<Abi, serde_json::Error> =
+            if !(method.starts_with('[') && method.ends_with(']')) {
+                let abi_str = format!("[{method}]");
+                serde_json::from_str(&abi_str)
+            } else {
+                serde_json::from_str(method)
+            };
+        let abi: Abi = json_parse.unwrap();
+        let (_, functions): (&String, &Vec<Function>) = abi.functions.iter().next().unwrap();
+        let function: Function = functions.get(0).unwrap().clone();
+        Ok(function)
+    }
+}
+
 #[derive(Serialize)]
 #[doc(hidden)]
 pub(crate) struct GethLoggerConfig {
diff --git a/chains/ethereum/tx/Cargo.toml b/chains/ethereum/tx/Cargo.toml
index a3e2b1f7..463211c9 100644
--- a/chains/ethereum/tx/Cargo.toml
+++ b/chains/ethereum/tx/Cargo.toml
@@ -6,6 +6,8 @@ edition = "2021"
 [dependencies]
 anyhow = "1.0.69"
 ethers-core = "1.0.2"
+ethers = "1.0.2"
 rosetta-config-ethereum = { version = "0.1.0", path = "../config" }
 rosetta-core = { version = "0.1.0", path = "../../../rosetta-core" }
+serde_json = "1.0.70"
 sha3 = "0.10.6"
diff --git a/chains/ethereum/tx/src/lib.rs b/chains/ethereum/tx/src/lib.rs
index d43842d9..e731e615 100644
--- a/chains/ethereum/tx/src/lib.rs
+++ b/chains/ethereum/tx/src/lib.rs
@@ -1,9 +1,12 @@
-use anyhow::Result;
+use anyhow::{anyhow, Result};
+use ethers::abi::token::{LenientTokenizer, Tokenizer};
+use ethers::abi::{Abi, Function, HumanReadableParser, Param, Token};
 use ethers_core::types::{Eip1559TransactionRequest, Signature, H160, U256};
 use rosetta_config_ethereum::{EthereumMetadata, EthereumMetadataParams};
 use rosetta_core::crypto::address::Address;
 use rosetta_core::crypto::SecretKey;
 use rosetta_core::{BlockchainConfig, TransactionBuilder};
+use serde_json::Value;
 use sha3::{Digest, Keccak256};
 
 #[derive(Default)]
@@ -23,6 +26,29 @@ impl TransactionBuilder for EthereumTransactionBuilder {
         })
     }
 
+    fn method_call(&self, address: &Address, params: &Value) -> Result<Self::MetadataParams> {
+        let destination: H160 = address.address().parse()?;
+
+        let method_str = params["method_signature"]
+            .as_str()
+            .ok_or(anyhow!("Method signature not found"))?;
+        let function_params = params["params"]
+            .as_array()
+            .ok_or(anyhow!("Params not found"))?;
+
+        let function = parse_method(method_str)?;
+
+        let tokens = tokenize_params(function_params, &function.inputs);
+
+        let bytes: Vec<u8> = function.encode_input(&tokens).map(Into::into)?;
+
+        Ok(EthereumMetadataParams {
+            destination: destination.0.to_vec(),
+            amount: [0, 0, 0, 0],
+            data: bytes,
+        })
+    }
+
     fn create_and_sign(
         &self,
         config: &BlockchainConfig,
@@ -65,3 +91,32 @@ impl TransactionBuilder for EthereumTransactionBuilder {
         tx
     }
 }
+
+fn parse_method(method: &str) -> Result<Function> {
+    let parse_result = HumanReadableParser::parse_function(method);
+    if parse_result.is_ok() {
+        parse_result.map_err(|e| anyhow!(e))
+    } else {
+        let json_parse: Result<Abi, serde_json::Error> =
+            if !(method.starts_with('[') && method.ends_with(']')) {
+                let abi_str = format!("[{method}]");
+                serde_json::from_str(&abi_str)
+            } else {
+                serde_json::from_str(method)
+            };
+        let abi: Abi = json_parse.unwrap();
+        let (_, functions): (&String, &Vec<Function>) = abi.functions.iter().next().unwrap();
+        let function: Function = functions.get(0).unwrap().clone();
+        Ok(function)
+    }
+}
+
+fn tokenize_params(values: &[Value], inputs: &[Param]) -> Vec<Token> {
+    let value_strings: Vec<String> = values.iter().map(|v| v.as_str().unwrap().into()).collect();
+
+    inputs
+        .iter()
+        .zip(value_strings.iter())
+        .map(|(param, arg)| LenientTokenizer::tokenize(&param.kind, arg).unwrap())
+        .collect()
+}
diff --git a/chains/polkadot/tx/src/lib.rs b/chains/polkadot/tx/src/lib.rs
index cea1562b..67559ece 100644
--- a/chains/polkadot/tx/src/lib.rs
+++ b/chains/polkadot/tx/src/lib.rs
@@ -1,4 +1,4 @@
-use anyhow::{Context, Result};
+use anyhow::{bail, Context, Result};
 use parity_scale_codec::{Compact, Decode, Encode};
 use rosetta_config_polkadot::{PolkadotMetadata, PolkadotMetadataParams};
 use rosetta_core::crypto::address::Address;
@@ -98,6 +98,14 @@ impl TransactionBuilder for PolkadotTransactionBuilder {
         })
     }
 
+    fn method_call(
+        &self,
+        _address: &Address,
+        _params: &serde_json::Value,
+    ) -> Result<Self::MetadataParams> {
+        bail!("Not Implemented")
+    }
+
     fn create_and_sign(
         &self,
         _config: &BlockchainConfig,
diff --git a/rosetta-client/src/wallet.rs b/rosetta-client/src/wallet.rs
index 0473d735..908dc8dd 100644
--- a/rosetta-client/src/wallet.rs
+++ b/rosetta-client/src/wallet.rs
@@ -14,6 +14,7 @@ use anyhow::Result;
 use futures::{Future, Stream};
 use std::pin::Pin;
 use std::task::{Context, Poll};
+use serde_json::Value;
 
 pub enum GenericTransactionBuilder {
     Ethereum(rosetta_tx_ethereum::EthereumTransactionBuilder),
@@ -36,6 +37,17 @@ impl GenericTransactionBuilder {
         })
     }
 
+    pub fn method_call(
+        &self,
+        method: &Address,
+        params: &serde_json::Value,
+    ) -> Result<serde_json::Value> {
+        Ok(match self {
+            Self::Ethereum(tx) => serde_json::to_value(tx.method_call(method, params)?)?,
+            Self::Polkadot(tx) => serde_json::to_value(tx.method_call(method, params)?)?,
+        })
+    }
+
     pub fn create_and_sign(
         &self,
         config: &BlockchainConfig,
@@ -173,6 +185,23 @@ impl Wallet {
         self.submit(&transaction).await
     }
 
+    pub async fn method_call(
+        &self,
+        account: &AccountIdentifier,
+        params: Value,
+    ) -> Result<TransactionIdentifier> {
+        let address = Address::new(self.config.address_format, account.address.clone());
+        let metadata_params = self.tx.method_call(&address, &params)?;
+        let metadata = self.metadata(metadata_params.clone()).await?;
+        let transaction = self.tx.create_and_sign(
+            &self.config,
+            metadata_params,
+            metadata,
+            self.secret_key.secret_key(),
+        );
+        self.submit(&transaction).await
+    }
+
     pub async fn faucet(&self, faucet_parameter: u128) -> Result<TransactionIdentifier> {
         let req = AccountFaucetRequest {
             network_identifier: self.config.network(),
diff --git a/rosetta-core/src/lib.rs b/rosetta-core/src/lib.rs
index 3cbeffd7..73eb99f1 100644
--- a/rosetta-core/src/lib.rs
+++ b/rosetta-core/src/lib.rs
@@ -122,6 +122,8 @@ pub trait TransactionBuilder: Default + Sized {
 
     fn transfer(&self, address: &Address, amount: u128) -> Result<Self::MetadataParams>;
 
+    fn method_call(&self, address: &Address, values: &Value) -> Result<Self::MetadataParams>;
+
     fn create_and_sign(
         &self,
         config: &BlockchainConfig,
diff --git a/rosetta-wallet/src/main.rs b/rosetta-wallet/src/main.rs
index becded74..2e47b9a8 100644
--- a/rosetta-wallet/src/main.rs
+++ b/rosetta-wallet/src/main.rs
@@ -3,6 +3,7 @@ use clap::Parser;
 use futures::stream::StreamExt;
 use rosetta_client::types::AccountIdentifier;
 use std::path::PathBuf;
+use surf::http::convert::json;
 
 #[derive(Parser)]
 pub struct Opts {
@@ -26,6 +27,7 @@ pub enum Command {
     Faucet(FaucetOpts),
     Transfer(TransferOpts),
     Transactions,
+    MethodCall(MethodCallOpts),
 }
 
 #[derive(Parser)]
@@ -39,6 +41,14 @@ pub struct FaucetOpts {
     pub amount: u128,
 }
 
+#[derive(Parser)]
+pub struct MethodCallOpts {
+    pub address: String,
+    pub method_signature: String,
+    #[clap(value_delimiter = ' ')]
+    pub params: Vec<String>,
+}
+
 #[async_std::main]
 async fn main() -> Result<()> {
     tracing_subscriber::fmt::init();
@@ -148,6 +158,24 @@ async fn main() -> Result<()> {
                 println!("No transactions found");
             }
         }
+        Command::MethodCall(MethodCallOpts {
+            address,
+            method_signature,
+            params,
+        }) => {
+            let acc_identifier = AccountIdentifier {
+                address,
+                sub_account: None,
+                metadata: None,
+            };
+            let params = json!({
+                "method_signature": method_signature,
+                "params": params
+            });
+
+            let tx = wallet.method_call(&acc_identifier, params).await?;
+            println!("Transaction hash: {:?}", tx.hash);
+        }
     }
     Ok(())
 }

From 3ee011244ce28f424b4914059fe9a247fb65a148 Mon Sep 17 00:00:00 2001
From: Haider-Ali-DS <haiderali.tech_786@outlook.com>
Date: Wed, 22 Feb 2023 19:06:29 +0500
Subject: [PATCH 02/10] rebasinc to account

---
 rosetta-client/src/wallet.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/rosetta-client/src/wallet.rs b/rosetta-client/src/wallet.rs
index 908dc8dd..5f51d37e 100644
--- a/rosetta-client/src/wallet.rs
+++ b/rosetta-client/src/wallet.rs
@@ -12,9 +12,9 @@ use crate::types::{
 use crate::{BlockchainConfig, Client, TransactionBuilder};
 use anyhow::Result;
 use futures::{Future, Stream};
+use serde_json::Value;
 use std::pin::Pin;
 use std::task::{Context, Poll};
-use serde_json::Value;
 
 pub enum GenericTransactionBuilder {
     Ethereum(rosetta_tx_ethereum::EthereumTransactionBuilder),

From 0eab3d840d3cfd1ae4d57c4b8cb5b85e9916e844 Mon Sep 17 00:00:00 2001
From: Haider-Ali-DS <haiderali.tech_786@outlook.com>
Date: Wed, 22 Feb 2023 19:09:26 +0500
Subject: [PATCH 03/10] clippy fixed

---
 chains/polkadot/server/src/block.rs | 4 ++--
 rosetta-server/src/lib.rs           | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/chains/polkadot/server/src/block.rs b/chains/polkadot/server/src/block.rs
index e2c69fca..a38299c9 100644
--- a/chains/polkadot/server/src/block.rs
+++ b/chains/polkadot/server/src/block.rs
@@ -38,7 +38,7 @@ pub async fn get_transaction<T: Config<Hash = H256>>(
 
         let op_neg_amount: Option<Amount> =
             event_parsed_data.amount.as_ref().map(|amount| Amount {
-                value: format!("-{}", amount),
+                value: format!("-{amount}"),
                 currency: config.currency(),
                 metadata: None,
             });
@@ -99,7 +99,7 @@ fn get_operation_data(
     let pallet_name = event.pallet_name();
     let event_name = event.variant_name();
 
-    let call_type = format!("{}.{}", pallet_name, event_name);
+    let call_type = format!("{pallet_name}.{event_name}");
 
     let event_fields = event.field_values()?;
     let parsed_data = match event_fields {
diff --git a/rosetta-server/src/lib.rs b/rosetta-server/src/lib.rs
index 49900efb..ae9168be 100644
--- a/rosetta-server/src/lib.rs
+++ b/rosetta-server/src/lib.rs
@@ -113,7 +113,7 @@ fn ok<T: serde::Serialize>(t: &T) -> tide::Result {
 fn err(err: &anyhow::Error) -> tide::Result {
     let error = crate::types::Error {
         code: 500,
-        message: format!("{}", err),
+        message: format!("{err}"),
         description: None,
         retriable: false,
         details: None,

From 1360a372c452e1c9c2c3e7bcfc666206b88b011a Mon Sep 17 00:00:00 2001
From: Haider-Ali-DS <haiderali.tech_786@outlook.com>
Date: Wed, 1 Mar 2023 02:19:11 +0500
Subject: [PATCH 04/10] Features: Storage proof implementation Testcase fixed
 for ethereum Code improvement

---
 chains/ethereum/server/src/lib.rs   |  83 ++++++++++--
 chains/ethereum/server/src/proof.rs | 194 ++++++++++++++++++++++++++++
 chains/ethereum/server/src/utils.rs | 122 ++++++-----------
 rosetta-server/src/indexer.rs       |  25 ++--
 rosetta-server/src/lib.rs           |   1 +
 5 files changed, 319 insertions(+), 106 deletions(-)
 create mode 100644 chains/ethereum/server/src/proof.rs

diff --git a/chains/ethereum/server/src/lib.rs b/chains/ethereum/server/src/lib.rs
index 4619750b..36936159 100644
--- a/chains/ethereum/server/src/lib.rs
+++ b/chains/ethereum/server/src/lib.rs
@@ -1,7 +1,10 @@
 use crate::eth_types::GENESIS_BLOCK_INDEX;
 use crate::utils::{get_block, get_transaction, populate_transactions, EthDetokenizer};
-use anyhow::{anyhow, bail, Context, Result};
+use anyhow::{bail, Context, Result};
 use ethers::prelude::*;
+use ethers::utils::keccak256;
+use ethers::utils::rlp::Encodable;
+use proof::verify_proof;
 use rosetta_config_ethereum::{EthereumMetadata, EthereumMetadataParams};
 use rosetta_server::crypto::address::Address;
 use rosetta_server::crypto::PublicKey;
@@ -10,11 +13,12 @@ use rosetta_server::types::{
     TransactionIdentifier,
 };
 use rosetta_server::{BlockchainClient, BlockchainConfig};
-use serde_json::Value;
+use serde_json::{json, Value};
 use std::str::FromStr;
-use utils::parse_method;
+use utils::{hex_str_to_bytes, parse_method};
 
 mod eth_types;
+mod proof;
 mod utils;
 
 pub struct EthereumClient {
@@ -31,7 +35,10 @@ impl BlockchainClient for EthereumClient {
     async fn new(network: &str, addr: &str) -> Result<Self> {
         let config = rosetta_config_ethereum::config(network)?;
         let client = Provider::<Http>::try_from(format!("http://{addr}"))?;
-        let genesis = client.get_block(0).await?.unwrap();
+        let genesis = client
+            .get_block(0)
+            .await?
+            .context("Failed to get genesis block")?;
         let genesis_block = BlockIdentifier {
             index: 0,
             hash: hex::encode(genesis.hash.as_ref().unwrap()),
@@ -111,8 +118,7 @@ impl BlockchainClient for EthereumClient {
         let from: H160 = public_key
             .to_address(self.config().address_format)
             .address()
-            .parse()
-            .unwrap();
+            .parse()?;
         let to = H160::from_slice(&options.destination);
         let chain_id = self.client.get_chainid().await?;
         let nonce = self.client.get_transaction_count(from, None).await?;
@@ -135,12 +141,13 @@ impl BlockchainClient for EthereumClient {
 
     async fn submit(&self, transaction: &[u8]) -> Result<Vec<u8>> {
         let tx = transaction.to_vec().into();
+
         Ok(self
             .client
             .send_raw_transaction(Bytes(tx))
             .await?
             .await?
-            .unwrap()
+            .context("Failed to get transaction receipt")?
             .transaction_hash
             .0
             .to_vec())
@@ -204,8 +211,7 @@ impl BlockchainClient for EthereumClient {
                     params["contract_address"]
                         .as_str()
                         .context("contact address not found")?,
-                )
-                .map_err(|err| anyhow!(err))?;
+                )?;
 
                 let function = parse_method(&method)?;
 
@@ -232,12 +238,10 @@ impl BlockchainClient for EthereumClient {
                     params["contract_address"]
                         .as_str()
                         .context("address field not found")?,
-                )
-                .map_err(|err| anyhow!(err))?;
+                )?;
 
                 let location =
-                    H256::from_str(params["position"].as_str().context("position not found")?)
-                        .map_err(|err| anyhow!(err))?;
+                    H256::from_str(params["position"].as_str().context("position not found")?)?;
 
                 let block_num = params["block_number"]
                     .as_u64()
@@ -249,6 +253,47 @@ impl BlockchainClient for EthereumClient {
                     .await?;
                 return Ok(Value::String(format!("{storage_check:#?}",)));
             }
+            "storage_proof" => {
+                let from = H160::from_str(
+                    params["contract_address"]
+                        .as_str()
+                        .context("address field not found")?,
+                )?;
+
+                let location =
+                    H256::from_str(params["position"].as_str().context("position not found")?)?;
+
+                let block_num = params["block_number"]
+                    .as_u64()
+                    .map(|block_num| BlockId::Number(block_num.into()));
+
+                let proof_data = self
+                    .client
+                    .get_proof(from, vec![location], block_num)
+                    .await?;
+
+                //process verfiicatin of proof
+                let storage_hash = proof_data.storage_hash;
+                let storage_proof = proof_data.storage_proof.first().context("No proof found")?;
+
+                let key = hex_str_to_bytes(&hex::encode(storage_proof.key))?;
+                let key_hash = keccak256(key);
+                let encoded_val = storage_proof.value.rlp_bytes().to_vec();
+
+                let is_valid = verify_proof(
+                    &storage_proof.proof,
+                    storage_hash.as_bytes(),
+                    &key_hash.to_vec(),
+                    &encoded_val,
+                );
+
+                let result = serde_json::to_value(&proof_data)?;
+
+                return Ok(json!({
+                    "proof": result,
+                    "isValid": is_valid
+                }));
+            }
             _ => {
                 bail!("request type not supported")
             }
@@ -289,4 +334,16 @@ mod tests {
         let config = rosetta_config_ethereum::config("dev")?;
         rosetta_server::tests::construction(config).await
     }
+
+    #[tokio::test]
+    async fn test_find_transaction() -> Result<()> {
+        let config = rosetta_config_ethereum::config("dev")?;
+        rosetta_server::tests::find_transaction(config).await
+    }
+
+    #[tokio::test]
+    async fn test_list_transactions() -> Result<()> {
+        let config = rosetta_config_ethereum::config("dev")?;
+        rosetta_server::tests::list_transactions(config).await
+    }
 }
diff --git a/chains/ethereum/server/src/proof.rs b/chains/ethereum/server/src/proof.rs
new file mode 100644
index 00000000..d111a540
--- /dev/null
+++ b/chains/ethereum/server/src/proof.rs
@@ -0,0 +1,194 @@
+use ethers::types::{Bytes, EIP1186ProofResponse};
+use ethers::utils::keccak256;
+use ethers::utils::rlp::{decode_list, RlpStream};
+
+pub fn verify_proof(proof: &Vec<Bytes>, root: &[u8], path: &Vec<u8>, value: &Vec<u8>) -> bool {
+    let mut expected_hash = root.to_vec();
+    let mut path_offset = 0;
+
+    for (i, node) in proof.iter().enumerate() {
+        if expected_hash != keccak256(node).to_vec() {
+            return false;
+        }
+
+        let node_list: Vec<Vec<u8>> = decode_list(node);
+
+        if node_list.len() == 17 {
+            if i == proof.len() - 1 {
+                // exclusion proof
+                let nibble = get_nibble(path, path_offset);
+                let node = &node_list[nibble as usize];
+
+                if node.is_empty() && is_empty_value(value) {
+                    return true;
+                }
+            } else {
+                let nibble = get_nibble(path, path_offset);
+                expected_hash = node_list[nibble as usize].clone();
+
+                path_offset += 1;
+            }
+        } else if node_list.len() == 2 {
+            if i == proof.len() - 1 {
+                // exclusion proof
+                if !paths_match(&node_list[0], skip_length(&node_list[0]), path, path_offset)
+                    && is_empty_value(value)
+                {
+                    return true;
+                }
+
+                // inclusion proof
+                if &node_list[1] == value {
+                    return paths_match(
+                        &node_list[0],
+                        skip_length(&node_list[0]),
+                        path,
+                        path_offset,
+                    );
+                }
+            } else {
+                let node_path = &node_list[0];
+                let prefix_length = shared_prefix_length(path, path_offset, node_path);
+                if prefix_length < node_path.len() * 2 - skip_length(node_path) {
+                    // The proof shows a divergent path, but we're not
+                    // at the end of the proof, so something's wrong.
+                    return false;
+                }
+                path_offset += prefix_length;
+                expected_hash = node_list[1].clone();
+            }
+        } else {
+            return false;
+        }
+    }
+
+    false
+}
+
+fn paths_match(p1: &Vec<u8>, s1: usize, p2: &Vec<u8>, s2: usize) -> bool {
+    let len1 = p1.len() * 2 - s1;
+    let len2 = p2.len() * 2 - s2;
+
+    if len1 != len2 {
+        return false;
+    }
+
+    for offset in 0..len1 {
+        let n1 = get_nibble(p1, s1 + offset);
+        let n2 = get_nibble(p2, s2 + offset);
+
+        if n1 != n2 {
+            return false;
+        }
+    }
+
+    true
+}
+
+#[allow(dead_code)]
+fn get_rest_path(p: &Vec<u8>, s: usize) -> String {
+    let mut ret = String::new();
+    for i in s..p.len() * 2 {
+        let n = get_nibble(p, i);
+        ret += &format!("{n:01x}");
+    }
+    ret
+}
+
+fn is_empty_value(value: &Vec<u8>) -> bool {
+    let mut stream = RlpStream::new();
+    stream.begin_list(4);
+    stream.append_empty_data();
+    stream.append_empty_data();
+    let empty_storage_hash = "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421";
+    stream.append(&hex::decode(empty_storage_hash).unwrap());
+    let empty_code_hash = "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470";
+    stream.append(&hex::decode(empty_code_hash).unwrap());
+    let empty_account = stream.out();
+
+    let is_empty_slot = value.len() == 1 && value[0] == 0x80;
+    let is_empty_account = value == &empty_account;
+    is_empty_slot || is_empty_account
+}
+
+fn shared_prefix_length(path: &Vec<u8>, path_offset: usize, node_path: &Vec<u8>) -> usize {
+    let skip_length = skip_length(node_path);
+
+    let len = std::cmp::min(
+        node_path.len() * 2 - skip_length,
+        path.len() * 2 - path_offset,
+    );
+    let mut prefix_len = 0;
+
+    for i in 0..len {
+        let path_nibble = get_nibble(path, i + path_offset);
+        let node_path_nibble = get_nibble(node_path, i + skip_length);
+
+        if path_nibble == node_path_nibble {
+            prefix_len += 1;
+        } else {
+            break;
+        }
+    }
+
+    prefix_len
+}
+
+fn skip_length(node: &Vec<u8>) -> usize {
+    if node.is_empty() {
+        return 0;
+    }
+
+    let nibble = get_nibble(node, 0);
+    match nibble {
+        0 => 2,
+        1 => 1,
+        2 => 2,
+        3 => 1,
+        _ => 0,
+    }
+}
+
+fn get_nibble(path: &[u8], offset: usize) -> u8 {
+    let byte = path[offset / 2];
+    if offset % 2 == 0 {
+        byte >> 4
+    } else {
+        byte & 0xF
+    }
+}
+
+pub fn _encode_account(proof: &EIP1186ProofResponse) -> Vec<u8> {
+    let mut stream = RlpStream::new_list(4);
+    stream.append(&proof.nonce);
+    stream.append(&proof.balance);
+    stream.append(&proof.storage_hash);
+    stream.append(&proof.code_hash);
+    let encoded = stream.out();
+    encoded.to_vec()
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::proof::shared_prefix_length;
+
+    #[tokio::test]
+    async fn test_shared_prefix_length() {
+        // We compare the path starting from the 6th nibble i.e. the 6 in 0x6f
+        let path: Vec<u8> = vec![0x12, 0x13, 0x14, 0x6f, 0x6c, 0x64, 0x21];
+        let path_offset = 6;
+        // Our node path matches only the first 5 nibbles of the path
+        let node_path: Vec<u8> = vec![0x6f, 0x6c, 0x63, 0x21];
+        let shared_len = shared_prefix_length(&path, path_offset, &node_path);
+        assert_eq!(shared_len, 5);
+
+        // Now we compare the path starting from the 5th nibble i.e. the 4 in 0x14
+        let path: Vec<u8> = vec![0x12, 0x13, 0x14, 0x6f, 0x6c, 0x64, 0x21];
+        let path_offset = 5;
+        // Our node path matches only the first 7 nibbles of the path
+        // Note the first nibble is 1, so we skip 1 nibble
+        let node_path: Vec<u8> = vec![0x14, 0x6f, 0x6c, 0x64, 0x11];
+        let shared_len = shared_prefix_length(&path, path_offset, &node_path);
+        assert_eq!(shared_len, 7);
+    }
+}
diff --git a/chains/ethereum/server/src/utils.rs b/chains/ethereum/server/src/utils.rs
index 706c243c..1827ecbe 100644
--- a/chains/ethereum/server/src/utils.rs
+++ b/chains/ethereum/server/src/utils.rs
@@ -19,8 +19,7 @@ use rosetta_server::types::{
     AccountIdentifier, Amount, BlockIdentifier, Currency, Operation, OperationIdentifier,
     PartialBlockIdentifier, TransactionIdentifier,
 };
-use serde::{Deserialize, Serialize};
-use serde_json::{json, Value};
+use serde_json::json;
 use std::collections::HashMap;
 use std::str::FromStr;
 
@@ -33,7 +32,7 @@ pub async fn get_block(
     client: &Provider<Http>,
 ) -> Result<(Block<Transaction>, Vec<LoadedTransaction>, Vec<Block<H256>>)> {
     let bl_id = if let Some(hash) = block.hash.as_ref() {
-        let h256 = H256::from_str(hash).map_err(|err| anyhow!(err))?;
+        let h256 = H256::from_str(hash)?;
         BlockId::Hash(h256)
     } else if let Some(index) = block.index {
         let ehters_u64 = U64::from(index);
@@ -45,8 +44,7 @@ pub async fn get_block(
 
     let block_eth = client
         .get_block_with_txs(bl_id)
-        .await
-        .map_err(|err| anyhow!(err))?
+        .await?
         .context("Block not found")?;
 
     let block_number = block_eth
@@ -76,7 +74,7 @@ pub async fn get_block(
         traces.extend(block_traces.0);
     }
 
-    let mut loaded_transaction_vec = vec![];
+    let mut loaded_transactions = vec![];
     for (idx, transaction) in block_transactions.iter().enumerate() {
         let tx_receipt = &receipts[idx];
 
@@ -96,15 +94,15 @@ pub async fn get_block(
         };
 
         if !add_traces {
-            loaded_transaction_vec.push(loaded_tx);
+            loaded_transactions.push(loaded_tx);
             continue;
         }
 
         loaded_tx.trace = Some(traces[idx].result.clone());
-        loaded_transaction_vec.push(loaded_tx);
+        loaded_transactions.push(loaded_tx);
     }
 
-    Ok((block_eth, loaded_transaction_vec, uncles))
+    Ok((block_eth, loaded_transactions, uncles))
 }
 
 pub async fn get_transaction(
@@ -113,11 +111,10 @@ pub async fn get_transaction(
     client: &Provider<Http>,
     currency: &Currency,
 ) -> Result<rosetta_types::Transaction> {
-    let tx_hash = H256::from_str(hash).map_err(|err| anyhow!(err))?;
+    let tx_hash = H256::from_str(hash)?;
     let transaction = client
         .get_transaction(tx_hash)
-        .await
-        .map_err(|err| anyhow!(err))?
+        .await?
         .context("Unable to get transaction")?;
 
     let ehters_u64 = U64::from(block_identifier.index);
@@ -126,8 +123,7 @@ pub async fn get_transaction(
 
     let block = client
         .get_block(block_num)
-        .await
-        .map_err(|err| anyhow!(err))?
+        .await?
         .context("Block not found")?;
 
     let block_hash = block.hash.context("Block hash not found")?;
@@ -135,8 +131,7 @@ pub async fn get_transaction(
 
     let tx_receipt = client
         .get_transaction_receipt(tx_hash)
-        .await
-        .map_err(|err| anyhow!(err))?
+        .await?
         .context("Transaction receipt not found")?;
 
     if tx_receipt
@@ -216,7 +211,7 @@ pub async fn populate_transaction(
 
     let transaction = rosetta_types::Transaction {
         transaction_identifier: TransactionIdentifier {
-            hash: format!("{:?}", tx.transaction.hash),
+            hash: hex::encode(tx.transaction.hash),
         },
         operations,
         related_transactions: None,
@@ -235,17 +230,16 @@ pub async fn get_uncles(
     uncles: &[H256],
     client: &Provider<Http>,
 ) -> Result<Vec<Block<H256>>> {
-    let mut uncles_vec = vec![];
+    let mut uncles_data = vec![];
     for (idx, _) in uncles.iter().enumerate() {
         let index = U64::from(idx);
         let uncle_response = client
             .get_uncle(block_index, index)
-            .await
-            .map_err(|err| anyhow!("{err}"))?
+            .await?
             .context("Uncle block now found")?;
-        uncles_vec.push(uncle_response);
+        uncles_data.push(uncle_response);
     }
-    Ok(uncles_vec)
+    Ok(uncles_data)
 }
 
 pub async fn get_block_receipts(
@@ -258,8 +252,7 @@ pub async fn get_block_receipts(
         let tx_hash = tx.hash;
         let receipt = client
             .get_transaction_receipt(tx_hash)
-            .await
-            .map_err(|err| anyhow!("{err}"))?
+            .await?
             .context("Transaction receipt not found")?;
 
         if receipt
@@ -288,8 +281,7 @@ pub async fn get_block_traces(
 
     let traces: ResultGethExecTraces = client
         .request("debug_traceBlockByHash", [hash_serialize, cfg])
-        .await
-        .map_err(|err| anyhow!(err))?;
+        .await?;
 
     Ok(traces)
 }
@@ -304,8 +296,7 @@ async fn get_transaction_trace(hash: &H256, client: &Provider<Http>) -> Result<T
 
     let traces: Trace = client
         .request("debug_traceTransaction", [hash_serialize, cfg])
-        .await
-        .map_err(|err| anyhow!(err))?;
+        .await?;
 
     Ok(traces)
 }
@@ -317,7 +308,7 @@ pub fn get_fee_operations(tx: &LoadedTransaction, currency: &Currency) -> Result
         tx.fee_amount
     };
 
-    let mut operations_vec = vec![];
+    let mut operations = vec![];
 
     let first_op = Operation {
         operation_identifier: OperationIdentifier {
@@ -366,8 +357,8 @@ pub fn get_fee_operations(tx: &LoadedTransaction, currency: &Currency) -> Result
         metadata: None,
     };
 
-    operations_vec.push(first_op);
-    operations_vec.push(second_op);
+    operations.push(first_op);
+    operations.push(second_op);
 
     if let Some(fee_burned) = tx.fee_burned {
         let burned_operation = Operation {
@@ -392,11 +383,9 @@ pub fn get_fee_operations(tx: &LoadedTransaction, currency: &Currency) -> Result
             metadata: None,
         };
 
-        operations_vec.push(burned_operation);
-        Ok(operations_vec)
-    } else {
-        Ok(operations_vec)
+        operations.push(burned_operation);
     }
+    Ok(operations)
 }
 
 pub fn get_traces_operations(
@@ -718,9 +707,7 @@ fn effective_gas_price(tx: &Transaction, base_fee: Option<U256>) -> Result<U256>
         .transaction_type
         .context("transaction type is not available")?;
     let tx_gas_price = tx.gas_price.context("gas price is not available")?;
-    let tx_max_priority_fee_per_gas = tx
-        .max_priority_fee_per_gas
-        .context("max priority fee per gas is not available")?;
+    let tx_max_priority_fee_per_gas = tx.max_priority_fee_per_gas.unwrap_or(U256::from(0));
 
     if tx_transaction_type.as_u64() != 2 {
         return Ok(tx_gas_price);
@@ -741,58 +728,25 @@ pub fn parse_method(method: &str) -> Result<Function> {
             } else {
                 serde_json::from_str(method)
             };
-        let abi: Abi = json_parse.unwrap();
-        let (_, functions): (&String, &Vec<Function>) = abi.functions.iter().next().unwrap();
-        let function: Function = functions.get(0).unwrap().clone();
+        let abi: Abi = json_parse?;
+        let (_, functions): (&String, &Vec<Function>) = abi
+            .functions
+            .iter()
+            .next()
+            .context("No functions found in abi")?;
+        let function: Function = functions
+            .get(0)
+            .context("Abi function list is empty")?
+            .clone();
         Ok(function)
     }
 }
 
-#[derive(Serialize)]
-#[doc(hidden)]
-pub(crate) struct GethLoggerConfig {
-    /// enable memory capture
-    #[serde(rename = "EnableMemory")]
-    enable_memory: bool,
-    /// disable stack capture
-    #[serde(rename = "DisableStack")]
-    disable_stack: bool,
-    /// disable storage capture
-    #[serde(rename = "DisableStorage")]
-    disable_storage: bool,
-    /// enable return data capture
-    #[serde(rename = "EnableReturnData")]
-    enable_return_data: bool,
-}
-
-impl Default for GethLoggerConfig {
-    fn default() -> Self {
-        Self {
-            enable_memory: false,
-            disable_stack: false,
-            disable_storage: false,
-            enable_return_data: true,
-        }
-    }
-}
-
-#[derive(Deserialize, Serialize, Clone, Debug, Eq, PartialEq)]
-pub struct GethExecTrace {
-    /// Used gas
-    pub gas: Gas,
-    /// True when the transaction has failed.
-    pub failed: bool,
-    /// Return value of execution which is a hex encoded byte array
-    #[serde(rename = "returnValue")]
-    pub return_value: String,
-    /// Vector of geth execution steps of the trace.
-    #[serde(rename = "structLogs")]
-    pub struct_logs: Vec<Value>,
+pub fn hex_str_to_bytes(s: &str) -> Result<Vec<u8>> {
+    let stripped = s.strip_prefix("0x").unwrap_or(s);
+    Ok(hex::decode(stripped)?)
 }
 
-#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
-pub struct Gas(pub u64);
-
 pub struct LoadedTransaction {
     pub transaction: Transaction,
     pub from: H160,
diff --git a/rosetta-server/src/indexer.rs b/rosetta-server/src/indexer.rs
index 21c02b4a..3ebf50a4 100644
--- a/rosetta-server/src/indexer.rs
+++ b/rosetta-server/src/indexer.rs
@@ -105,9 +105,10 @@ impl AccountTable {
     }
 
     pub fn get(&self, account: &AccountIdentifier) -> impl Iterator<Item = Result<TransactionRef>> {
-        let address_len = account.address.as_bytes().len();
+        let address = preprocess_acc_address(&account.address);
+        let address_len = address.as_bytes().len();
         self.tree
-            .scan_prefix(account.address.as_bytes())
+            .scan_prefix(address.to_lowercase().as_bytes())
             .keys()
             .map(move |key| Ok(TransactionRef::from_bytes(&key?[address_len..])))
     }
@@ -118,10 +119,8 @@ impl AccountTable {
     }
 
     pub fn len(&self, account: &AccountIdentifier) -> usize {
-        self.tree
-            .scan_prefix(account.address.as_bytes())
-            .keys()
-            .count()
+        let address = preprocess_acc_address(&account.address);
+        self.tree.scan_prefix(address.as_bytes()).keys().count()
     }
 
     #[allow(unused)]
@@ -132,13 +131,21 @@ impl AccountTable {
 }
 
 fn account_table_key(account: &AccountIdentifier, tx: &TransactionRef) -> Vec<u8> {
-    let address_len = account.address.as_bytes().len();
+    let address = preprocess_acc_address(&account.address);
+    let address_len = address.as_bytes().len();
     let mut key = Vec::with_capacity(address_len + 12);
-    key.extend(account.address.as_bytes());
+    key.extend(address.as_bytes());
     key.extend(tx.to_bytes());
     key
 }
 
+fn preprocess_acc_address(address: &str) -> String {
+    address
+        .strip_prefix("0x")
+        .unwrap_or(&address)
+        .to_lowercase()
+}
+
 #[derive(Clone)]
 pub struct Indexer<C: BlockchainClient> {
     transaction_table: TransactionTable,
@@ -204,7 +211,7 @@ impl<C: BlockchainClient> Indexer<C> {
     pub async fn sync(&self) -> Result<()> {
         let synced_height = self.transaction_table.height()?;
         let current_height = self.client.current_block().await?.index;
-        for block_index in (synced_height + 1)..current_height {
+        for block_index in (synced_height + 1)..current_height + 1 {
             let block = self.block_by_index(block_index).await?;
             for (transaction_index, transaction) in block.transactions.iter().enumerate() {
                 let tx = TransactionRef::new(block_index, transaction_index as _);
diff --git a/rosetta-server/src/lib.rs b/rosetta-server/src/lib.rs
index ae9168be..6662efc1 100644
--- a/rosetta-server/src/lib.rs
+++ b/rosetta-server/src/lib.rs
@@ -537,6 +537,7 @@ pub mod tests {
         alice.transfer(bob.account(), value).await?;
         alice.transfer(bob.account(), value).await?;
 
+        tokio::time::sleep(Duration::from_secs(11)).await;
         let mut stream = bob.transactions(1);
         let mut count = 0;
         while let Some(res) = stream.next().await {

From 9f44eee8f14256c63fe147751e47f1a3a183781b Mon Sep 17 00:00:00 2001
From: Haider-Ali-DS <haiderali.tech_786@outlook.com>
Date: Wed, 1 Mar 2023 02:23:31 +0500
Subject: [PATCH 05/10] clippy fix

---
 rosetta-server/src/indexer.rs | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/rosetta-server/src/indexer.rs b/rosetta-server/src/indexer.rs
index 3ebf50a4..e89c40b8 100644
--- a/rosetta-server/src/indexer.rs
+++ b/rosetta-server/src/indexer.rs
@@ -140,10 +140,7 @@ fn account_table_key(account: &AccountIdentifier, tx: &TransactionRef) -> Vec<u8
 }
 
 fn preprocess_acc_address(address: &str) -> String {
-    address
-        .strip_prefix("0x")
-        .unwrap_or(&address)
-        .to_lowercase()
+    address.strip_prefix("0x").unwrap_or(address).to_lowercase()
 }
 
 #[derive(Clone)]

From 79a44ede2fb6dd677235e1ca8a3e91995614186e Mon Sep 17 00:00:00 2001
From: Haider-Ali-DS <haiderali.tech_786@outlook.com>
Date: Thu, 2 Mar 2023 01:27:13 +0500
Subject: [PATCH 06/10] reviews fixes

---
 chains/ethereum/server/src/utils.rs | 22 ++++++++++++++--------
 rosetta-server/src/indexer.rs       | 20 ++++++++------------
 2 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/chains/ethereum/server/src/utils.rs b/chains/ethereum/server/src/utils.rs
index 1827ecbe..76aa33c9 100644
--- a/chains/ethereum/server/src/utils.rs
+++ b/chains/ethereum/server/src/utils.rs
@@ -9,6 +9,7 @@ use anyhow::{anyhow, bail, Context, Result};
 use ethers::{
     abi::{Abi, Detokenize, Function, HumanReadableParser, InvalidOutputType, Token},
     prelude::*,
+    utils::to_checksum,
 };
 use ethers::{
     providers::{Http, Middleware, Provider},
@@ -319,7 +320,7 @@ pub fn get_fee_operations(tx: &LoadedTransaction, currency: &Currency) -> Result
         r#type: FEE_OP_TYPE.into(),
         status: Some(SUCCESS_STATUS.into()),
         account: Some(AccountIdentifier {
-            address: format!("{:?}", tx.from),
+            address: parse_address(format!("{:?}", tx.from))?,
             sub_account: None,
             metadata: None,
         }),
@@ -344,7 +345,7 @@ pub fn get_fee_operations(tx: &LoadedTransaction, currency: &Currency) -> Result
         r#type: FEE_OP_TYPE.into(),
         status: Some(SUCCESS_STATUS.into()),
         account: Some(AccountIdentifier {
-            address: format!("{:?}", tx.miner),
+            address: parse_address(format!("{:?}", tx.miner))?,
             sub_account: None,
             metadata: None,
         }),
@@ -370,7 +371,7 @@ pub fn get_fee_operations(tx: &LoadedTransaction, currency: &Currency) -> Result
             r#type: FEE_OP_TYPE.into(),
             status: Some(SUCCESS_STATUS.into()),
             account: Some(AccountIdentifier {
-                address: format!("{:?}", tx.from),
+                address: parse_address(format!("{:?}", tx.from))?,
                 sub_account: None,
                 metadata: None,
             }),
@@ -431,7 +432,7 @@ pub fn get_traces_operations(
                 r#type: trace.trace_type.clone(),
                 status: Some(operation_status.into()),
                 account: Some(AccountIdentifier {
-                    address: from.clone(),
+                    address: parse_address(from.clone())?,
                     sub_account: None,
                     metadata: None,
                 }),
@@ -487,7 +488,7 @@ pub fn get_traces_operations(
                 r#type: trace.trace_type,
                 status: Some(operation_status.into()),
                 account: Some(AccountIdentifier {
-                    address: to.clone(),
+                    address: parse_address(to.clone())?,
                     sub_account: None,
                     metadata: None,
                 }),
@@ -530,7 +531,7 @@ pub fn get_traces_operations(
                 r#type: DESTRUCT_OP_TYPE.into(),
                 status: Some(SUCCESS_STATUS.into()),
                 account: Some(AccountIdentifier {
-                    address: k.clone(),
+                    address: parse_address(k.clone())?,
                     sub_account: None,
                     metadata: None,
                 }),
@@ -597,7 +598,7 @@ pub fn get_mining_rewards(
         r#type: MINING_REWARD_OP_TYPE.into(),
         status: Some(SUCCESS_STATUS.into()),
         account: Some(AccountIdentifier {
-            address: format!("{miner:?}"),
+            address: parse_address(format!("{miner:?}"))?,
             sub_account: None,
             metadata: None,
         }),
@@ -627,7 +628,7 @@ pub fn get_mining_rewards(
             r#type: UNCLE_REWARD_OP_TYPE.into(),
             status: Some(SUCCESS_STATUS.into()),
             account: Some(AccountIdentifier {
-                address: format!("{uncle_miner:?}"),
+                address: parse_address(format!("{uncle_miner:?}"))?,
                 sub_account: None,
                 metadata: None,
             }),
@@ -747,6 +748,11 @@ pub fn hex_str_to_bytes(s: &str) -> Result<Vec<u8>> {
     Ok(hex::decode(stripped)?)
 }
 
+pub fn parse_address(address: String) -> Result<String> {
+    let ethereum_address = H160::from_str(&address)?;
+    Ok(to_checksum(&ethereum_address, None))
+}
+
 pub struct LoadedTransaction {
     pub transaction: Transaction,
     pub from: H160,
diff --git a/rosetta-server/src/indexer.rs b/rosetta-server/src/indexer.rs
index e89c40b8..c9ee783a 100644
--- a/rosetta-server/src/indexer.rs
+++ b/rosetta-server/src/indexer.rs
@@ -105,10 +105,9 @@ impl AccountTable {
     }
 
     pub fn get(&self, account: &AccountIdentifier) -> impl Iterator<Item = Result<TransactionRef>> {
-        let address = preprocess_acc_address(&account.address);
-        let address_len = address.as_bytes().len();
+        let address_len = account.address.as_bytes().len();
         self.tree
-            .scan_prefix(address.to_lowercase().as_bytes())
+            .scan_prefix(account.address.as_bytes())
             .keys()
             .map(move |key| Ok(TransactionRef::from_bytes(&key?[address_len..])))
     }
@@ -119,8 +118,10 @@ impl AccountTable {
     }
 
     pub fn len(&self, account: &AccountIdentifier) -> usize {
-        let address = preprocess_acc_address(&account.address);
-        self.tree.scan_prefix(address.as_bytes()).keys().count()
+        self.tree
+            .scan_prefix(account.address.as_bytes())
+            .keys()
+            .count()
     }
 
     #[allow(unused)]
@@ -131,18 +132,13 @@ impl AccountTable {
 }
 
 fn account_table_key(account: &AccountIdentifier, tx: &TransactionRef) -> Vec<u8> {
-    let address = preprocess_acc_address(&account.address);
-    let address_len = address.as_bytes().len();
+    let address_len = account.address.as_bytes().len();
     let mut key = Vec::with_capacity(address_len + 12);
-    key.extend(address.as_bytes());
+    key.extend(account.address.as_bytes());
     key.extend(tx.to_bytes());
     key
 }
 
-fn preprocess_acc_address(address: &str) -> String {
-    address.strip_prefix("0x").unwrap_or(address).to_lowercase()
-}
-
 #[derive(Clone)]
 pub struct Indexer<C: BlockchainClient> {
     transaction_table: TransactionTable,

From 56de95be744e4f799d1113b84b146cae5549af4c Mon Sep 17 00:00:00 2001
From: Haider-Ali-DS <haiderali.tech_786@outlook.com>
Date: Thu, 2 Mar 2023 16:41:43 +0500
Subject: [PATCH 07/10] fixing checksum junk code

---
 chains/ethereum/server/src/lib.rs   |  6 ++++--
 chains/ethereum/server/src/utils.rs | 30 ++++++++++-------------------
 2 files changed, 14 insertions(+), 22 deletions(-)

diff --git a/chains/ethereum/server/src/lib.rs b/chains/ethereum/server/src/lib.rs
index 36936159..5f531f11 100644
--- a/chains/ethereum/server/src/lib.rs
+++ b/chains/ethereum/server/src/lib.rs
@@ -15,7 +15,7 @@ use rosetta_server::types::{
 use rosetta_server::{BlockchainClient, BlockchainConfig};
 use serde_json::{json, Value};
 use std::str::FromStr;
-use utils::{hex_str_to_bytes, parse_method};
+use utils::parse_method;
 
 mod eth_types;
 mod proof;
@@ -276,7 +276,9 @@ impl BlockchainClient for EthereumClient {
                 let storage_hash = proof_data.storage_hash;
                 let storage_proof = proof_data.storage_proof.first().context("No proof found")?;
 
-                let key = hex_str_to_bytes(&hex::encode(storage_proof.key))?;
+                let encoded_key = hex::encode(storage_proof.key);
+                let stripped_key = encoded_key.strip_prefix("0x").unwrap_or(&encoded_key);
+                let key = hex::decode(stripped_key)?;
                 let key_hash = keccak256(key);
                 let encoded_val = storage_proof.value.rlp_bytes().to_vec();
 
diff --git a/chains/ethereum/server/src/utils.rs b/chains/ethereum/server/src/utils.rs
index 76aa33c9..a6e50235 100644
--- a/chains/ethereum/server/src/utils.rs
+++ b/chains/ethereum/server/src/utils.rs
@@ -320,7 +320,7 @@ pub fn get_fee_operations(tx: &LoadedTransaction, currency: &Currency) -> Result
         r#type: FEE_OP_TYPE.into(),
         status: Some(SUCCESS_STATUS.into()),
         account: Some(AccountIdentifier {
-            address: parse_address(format!("{:?}", tx.from))?,
+            address: to_checksum(&tx.from, None),
             sub_account: None,
             metadata: None,
         }),
@@ -345,7 +345,7 @@ pub fn get_fee_operations(tx: &LoadedTransaction, currency: &Currency) -> Result
         r#type: FEE_OP_TYPE.into(),
         status: Some(SUCCESS_STATUS.into()),
         account: Some(AccountIdentifier {
-            address: parse_address(format!("{:?}", tx.miner))?,
+            address: to_checksum(&tx.miner, None),
             sub_account: None,
             metadata: None,
         }),
@@ -371,7 +371,7 @@ pub fn get_fee_operations(tx: &LoadedTransaction, currency: &Currency) -> Result
             r#type: FEE_OP_TYPE.into(),
             status: Some(SUCCESS_STATUS.into()),
             account: Some(AccountIdentifier {
-                address: parse_address(format!("{:?}", tx.from))?,
+                address: to_checksum(&tx.from, None),
                 sub_account: None,
                 metadata: None,
             }),
@@ -419,8 +419,8 @@ pub fn get_traces_operations(
             should_add = false;
         }
 
-        let from = format!("{:?}", trace.from);
-        let to = format!("{:?}", trace.to);
+        let from = to_checksum(&trace.from, None);
+        let to = to_checksum(&trace.to, None);
 
         if should_add {
             let mut from_operation = Operation {
@@ -432,7 +432,7 @@ pub fn get_traces_operations(
                 r#type: trace.trace_type.clone(),
                 status: Some(operation_status.into()),
                 account: Some(AccountIdentifier {
-                    address: parse_address(from.clone())?,
+                    address: from.clone(),
                     sub_account: None,
                     metadata: None,
                 }),
@@ -488,7 +488,7 @@ pub fn get_traces_operations(
                 r#type: trace.trace_type,
                 status: Some(operation_status.into()),
                 account: Some(AccountIdentifier {
-                    address: parse_address(to.clone())?,
+                    address: to.clone(),
                     sub_account: None,
                     metadata: None,
                 }),
@@ -531,7 +531,7 @@ pub fn get_traces_operations(
                 r#type: DESTRUCT_OP_TYPE.into(),
                 status: Some(SUCCESS_STATUS.into()),
                 account: Some(AccountIdentifier {
-                    address: parse_address(k.clone())?,
+                    address: to_checksum(&H160::from_str(k)?, None),
                     sub_account: None,
                     metadata: None,
                 }),
@@ -598,7 +598,7 @@ pub fn get_mining_rewards(
         r#type: MINING_REWARD_OP_TYPE.into(),
         status: Some(SUCCESS_STATUS.into()),
         account: Some(AccountIdentifier {
-            address: parse_address(format!("{miner:?}"))?,
+            address: to_checksum(miner, None),
             sub_account: None,
             metadata: None,
         }),
@@ -628,7 +628,7 @@ pub fn get_mining_rewards(
             r#type: UNCLE_REWARD_OP_TYPE.into(),
             status: Some(SUCCESS_STATUS.into()),
             account: Some(AccountIdentifier {
-                address: parse_address(format!("{uncle_miner:?}"))?,
+                address: to_checksum(&uncle_miner, None),
                 sub_account: None,
                 metadata: None,
             }),
@@ -743,16 +743,6 @@ pub fn parse_method(method: &str) -> Result<Function> {
     }
 }
 
-pub fn hex_str_to_bytes(s: &str) -> Result<Vec<u8>> {
-    let stripped = s.strip_prefix("0x").unwrap_or(s);
-    Ok(hex::decode(stripped)?)
-}
-
-pub fn parse_address(address: String) -> Result<String> {
-    let ethereum_address = H160::from_str(&address)?;
-    Ok(to_checksum(&ethereum_address, None))
-}
-
 pub struct LoadedTransaction {
     pub transaction: Transaction,
     pub from: H160,

From 948f82d97bdf276043edab13d8ece3644eea1b94 Mon Sep 17 00:00:00 2001
From: David Craven <david@craven.ch>
Date: Thu, 2 Mar 2023 14:53:29 +0100
Subject: [PATCH 08/10] Update chains/ethereum/server/src/lib.rs

---
 chains/ethereum/server/src/lib.rs | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/chains/ethereum/server/src/lib.rs b/chains/ethereum/server/src/lib.rs
index 5f531f11..e439d41c 100644
--- a/chains/ethereum/server/src/lib.rs
+++ b/chains/ethereum/server/src/lib.rs
@@ -276,9 +276,7 @@ impl BlockchainClient for EthereumClient {
                 let storage_hash = proof_data.storage_hash;
                 let storage_proof = proof_data.storage_proof.first().context("No proof found")?;
 
-                let encoded_key = hex::encode(storage_proof.key);
-                let stripped_key = encoded_key.strip_prefix("0x").unwrap_or(&encoded_key);
-                let key = hex::decode(stripped_key)?;
+                let key = &storage_proof.key;
                 let key_hash = keccak256(key);
                 let encoded_val = storage_proof.value.rlp_bytes().to_vec();
 

From 886d481b1ed58c1c936427e5246aa91a2b370019 Mon Sep 17 00:00:00 2001
From: Haider-Ali-DS <haiderali.tech_786@outlook.com>
Date: Thu, 2 Mar 2023 19:08:37 +0500
Subject: [PATCH 09/10] fmt fix

---
 chains/ethereum/server/src/lib.rs | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/chains/ethereum/server/src/lib.rs b/chains/ethereum/server/src/lib.rs
index 5854b432..8d2b546c 100644
--- a/chains/ethereum/server/src/lib.rs
+++ b/chains/ethereum/server/src/lib.rs
@@ -1,5 +1,7 @@
 use crate::eth_types::GENESIS_BLOCK_INDEX;
-use crate::utils::{get_block, get_transaction, parse_method, populate_transactions, EthDetokenizer};
+use crate::utils::{
+    get_block, get_transaction, parse_method, populate_transactions, EthDetokenizer,
+};
 use anyhow::{bail, Context, Result};
 use ethers::prelude::*;
 use ethers::utils::keccak256;

From 340b4779472b36671aa7d27fafcf3436644802b1 Mon Sep 17 00:00:00 2001
From: David Craven <david@craven.ch>
Date: Thu, 2 Mar 2023 17:18:44 +0100
Subject: [PATCH 10/10] Fix clippy warnings.

---
 chains/ethereum/server/src/utils.rs | 2 +-
 chains/ethereum/tx/src/lib.rs       | 8 +++-----
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/chains/ethereum/server/src/utils.rs b/chains/ethereum/server/src/utils.rs
index a6e50235..8f3555e1 100644
--- a/chains/ethereum/server/src/utils.rs
+++ b/chains/ethereum/server/src/utils.rs
@@ -708,7 +708,7 @@ fn effective_gas_price(tx: &Transaction, base_fee: Option<U256>) -> Result<U256>
         .transaction_type
         .context("transaction type is not available")?;
     let tx_gas_price = tx.gas_price.context("gas price is not available")?;
-    let tx_max_priority_fee_per_gas = tx.max_priority_fee_per_gas.unwrap_or(U256::from(0));
+    let tx_max_priority_fee_per_gas = tx.max_priority_fee_per_gas.unwrap_or_default();
 
     if tx_transaction_type.as_u64() != 2 {
         return Ok(tx_gas_price);
diff --git a/chains/ethereum/tx/src/lib.rs b/chains/ethereum/tx/src/lib.rs
index e731e615..3a86d466 100644
--- a/chains/ethereum/tx/src/lib.rs
+++ b/chains/ethereum/tx/src/lib.rs
@@ -1,4 +1,4 @@
-use anyhow::{anyhow, Result};
+use anyhow::{anyhow, Context, Result};
 use ethers::abi::token::{LenientTokenizer, Tokenizer};
 use ethers::abi::{Abi, Function, HumanReadableParser, Param, Token};
 use ethers_core::types::{Eip1559TransactionRequest, Signature, H160, U256};
@@ -31,10 +31,8 @@ impl TransactionBuilder for EthereumTransactionBuilder {
 
         let method_str = params["method_signature"]
             .as_str()
-            .ok_or(anyhow!("Method signature not found"))?;
-        let function_params = params["params"]
-            .as_array()
-            .ok_or(anyhow!("Params not found"))?;
+            .context("Method signature not found")?;
+        let function_params = params["params"].as_array().context("Params not found")?;
 
         let function = parse_method(method_str)?;