From 4bbbc5d422ddaa92fdd582b7abaee5c656cf0549 Mon Sep 17 00:00:00 2001 From: Gilad Chase Date: Wed, 18 Sep 2024 14:32:37 +0300 Subject: [PATCH] feat(base_layer): add types to config - implement the TODO for adding types to the Config, rather than working with raw strings. - using `Url` for url and **re-exporting** `alloy`'s `Address` type in order to not externalize this implementation detail type unnecessarily. - Remove 2 errors that are now no longer the responsibility of this module, the callsite will have to handle the casting into the correct types. commit-id:0a043060 --- Cargo.lock | 1 + crates/papyrus_base_layer/Cargo.toml | 2 +- .../papyrus_base_layer/src/base_layer_test.rs | 15 +++++--- .../src/ethereum_base_layer_contract.rs | 34 ++++++++++--------- 4 files changed, 30 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 26ab1bdd66..6c27bd2e46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11017,6 +11017,7 @@ dependencies = [ "form_urlencoded", "idna 0.5.0", "percent-encoding", + "serde", ] [[package]] diff --git a/crates/papyrus_base_layer/Cargo.toml b/crates/papyrus_base_layer/Cargo.toml index 3fd20b7073..33cf92f1b1 100644 --- a/crates/papyrus_base_layer/Cargo.toml +++ b/crates/papyrus_base_layer/Cargo.toml @@ -22,7 +22,7 @@ serde_json.workspace = true starknet_api.workspace = true thiserror.workspace = true tokio = { workspace = true, features = ["full", "sync"] } -url.workspace = true +url = { workspace = true, features = ["serde"] } [dev-dependencies] ethers-core.workspace = true diff --git a/crates/papyrus_base_layer/src/base_layer_test.rs b/crates/papyrus_base_layer/src/base_layer_test.rs index 2388adbcbc..2159aa9107 100644 --- a/crates/papyrus_base_layer/src/base_layer_test.rs +++ b/crates/papyrus_base_layer/src/base_layer_test.rs @@ -8,10 +8,13 @@ use starknet_api::felt; use tar::Archive; use tempfile::{tempdir, TempDir}; -use crate::ethereum_base_layer_contract::{EthereumBaseLayerConfig, EthereumBaseLayerContract}; +use crate::ethereum_base_layer_contract::{ + EthereumBaseLayerConfig, + EthereumBaseLayerContract, + EthereumContractAddress, +}; use crate::BaseLayerContract; -type EthereumContractAddress = String; type TestEthereumNodeHandle = (GanacheInstance, TempDir); const MINIMAL_GANACHE_VERSION: u8 = 7; @@ -65,7 +68,7 @@ fn get_test_ethereum_node() -> (TestEthereumNodeHandle, EthereumContractAddress) let db_path = ganache_db.path().join(DB_NAME); let ganache = Ganache::new().args(["--db", db_path.to_str().unwrap()]).spawn(); - ((ganache, ganache_db), SN_CONTRACT_ADDR.to_owned()) + ((ganache, ganache_db), SN_CONTRACT_ADDR.to_string().parse().unwrap()) } #[test_with::executable(ganache)] @@ -73,8 +76,10 @@ fn get_test_ethereum_node() -> (TestEthereumNodeHandle, EthereumContractAddress) // Note: the test requires ganache-cli installed, otherwise it is ignored. async fn latest_proved_block_ethereum() { let (node_handle, starknet_contract_address) = get_test_ethereum_node(); - let config = - EthereumBaseLayerConfig { node_url: node_handle.0.endpoint(), starknet_contract_address }; + let config = EthereumBaseLayerConfig { + node_url: node_handle.0.endpoint().parse().unwrap(), + starknet_contract_address, + }; let contract = EthereumBaseLayerContract::new(config).unwrap(); let first_sn_state_update = (BlockNumber(100), BlockHash(felt!("0x100"))); diff --git a/crates/papyrus_base_layer/src/ethereum_base_layer_contract.rs b/crates/papyrus_base_layer/src/ethereum_base_layer_contract.rs index 0e119cfacf..f89bd3d263 100644 --- a/crates/papyrus_base_layer/src/ethereum_base_layer_contract.rs +++ b/crates/papyrus_base_layer/src/ethereum_base_layer_contract.rs @@ -4,8 +4,7 @@ use std::future::IntoFuture; use alloy_contract::{ContractInstance, Interface}; use alloy_dyn_abi::SolType; use alloy_json_rpc::RpcError; -use alloy_primitives::hex::FromHexError; -use alloy_primitives::Address; +pub(crate) use alloy_primitives::Address as EthereumContractAddress; use alloy_provider::network::Ethereum; use alloy_provider::{Provider, ProviderBuilder, RootProvider}; use alloy_sol_types::sol_data; @@ -17,7 +16,7 @@ use papyrus_config::{ParamPath, ParamPrivacyInput, SerializationType, Serialized use serde::{Deserialize, Serialize}; use starknet_api::block::{BlockHash, BlockNumber}; use starknet_api::hash::StarkHash; -use url::ParseError; +use url::Url; use crate::BaseLayerContract; @@ -26,22 +25,17 @@ pub enum EthereumBaseLayerError { #[error(transparent)] Contract(#[from] alloy_contract::Error), #[error(transparent)] - FromHex(#[from] FromHexError), - #[error(transparent)] RpcError(#[from] RpcError), #[error(transparent)] Serde(#[from] serde_json::Error), #[error(transparent)] TypeError(#[from] alloy_sol_types::Error), - #[error(transparent)] - Url(#[from] ParseError), } #[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] pub struct EthereumBaseLayerConfig { - // TODO(yair): consider using types. - pub node_url: String, - pub starknet_contract_address: String, + pub node_url: Url, + pub starknet_contract_address: EthereumContractAddress, } impl SerializeConfig for EthereumBaseLayerConfig { @@ -55,7 +49,7 @@ impl SerializeConfig for EthereumBaseLayerConfig { ), ser_param( "starknet_contract_address", - &self.starknet_contract_address, + &self.starknet_contract_address.to_string(), "Starknet contract address in ethereum.", ParamPrivacyInput::Public, ), @@ -65,9 +59,12 @@ impl SerializeConfig for EthereumBaseLayerConfig { impl Default for EthereumBaseLayerConfig { fn default() -> Self { + let starknet_contract_address = + "0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4".parse().unwrap(); + Self { - node_url: "https://mainnet.infura.io/v3/".to_string(), - starknet_contract_address: "0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4".to_string(), + node_url: "https://mainnet.infura.io/v3/".parse().unwrap(), + starknet_contract_address, } } } @@ -79,12 +76,17 @@ pub struct EthereumBaseLayerContract { impl EthereumBaseLayerContract { pub fn new(config: EthereumBaseLayerConfig) -> Result { - let address: Address = config.starknet_contract_address.parse()?; - let client = ProviderBuilder::new().on_http(config.node_url.parse()?); + let client = ProviderBuilder::new().on_http(config.node_url); // The solidity contract was pre-compiled, and only the relevant functions were kept. let abi = serde_json::from_str(include_str!("core_contract_latest_block.abi"))?; - Ok(Self { contract: ContractInstance::new(address, client, Interface::new(abi)) }) + Ok(Self { + contract: ContractInstance::new( + config.starknet_contract_address, + client, + Interface::new(abi), + ), + }) } }