From c9d769e9511716a637238d027939de1e48d6e8bb Mon Sep 17 00:00:00 2001 From: mcaseaux Date: Thu, 6 Jun 2024 18:20:29 +0200 Subject: [PATCH 01/16] gogo --- crates/client/l1-gas-price/src/worker.rs | 35 +++++++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/crates/client/l1-gas-price/src/worker.rs b/crates/client/l1-gas-price/src/worker.rs index c90a91f71e..43b458cf14 100644 --- a/crates/client/l1-gas-price/src/worker.rs +++ b/crates/client/l1-gas-price/src/worker.rs @@ -3,16 +3,24 @@ use std::sync::Arc; use std::time::Duration; use anyhow::{format_err, Result}; +use ethers::types::U256; use ethers::utils::__serde_json::json; use futures::lock::Mutex; use mc_eth_client::config::EthereumClientConfig; use mp_starknet_inherent::L1GasPrices; +use serde::Deserialize; use tokio::time::sleep; use crate::types::{EthRpcResponse, FeeHistory}; const DEFAULT_GAS_PRICE_POLL_MS: u64 = 10_000; +#[derive(Deserialize, Debug)] +struct ApiResponse { + price: String, + decimals: u32, +} + pub async fn run_worker(config: Arc, gas_price: Arc>, infinite_loop: bool) { let rpc_endpoint = config.provider.rpc_endpoint().clone(); let client = reqwest::Client::new(); @@ -89,16 +97,35 @@ async fn update_gas_price( )?; // TODO: fetch this from the oracle - let eth_strk_price = 2425; + let url = "https://api.dev.pragma.build/node/v1/data/eth/strk?interval=1min&aggregation=median"; + let api_key = ""; + + let response = reqwest::Client::new().get(url).header("x-api-key", api_key).send().await?; + + let (price, decimal) = match response.json::().await { + Ok(api_response) => { + log::trace!("Retrieved ETH/STRK price from Pragma API"); + (api_response.price, api_response.decimals) + } + Err(e) => { + log::error!("Failed to retrieve ETH/STRK price: {:?}", e); + (String::from(""), 0) + } + }; + + let eth_strk_price = u128::from_str_radix(price.trim_start_matches("0x"), 16).expect("Invalid hex string"); + + let stark_gas = ((U256::from(eth_gas_price) * U256::from(eth_strk_price)) / 10u64.pow(decimal)).as_u128(); + let stark_data_gas = ((U256::from(avg_blob_base_fee) * U256::from(eth_strk_price)) / 10u64.pow(decimal)).as_u128(); let mut gas_price = gas_price.lock().await; gas_price.eth_l1_gas_price = NonZeroU128::new(eth_gas_price).ok_or(format_err!("Failed to convert `eth_gas_price` to NonZeroU128"))?; gas_price.eth_l1_data_gas_price = NonZeroU128::new(avg_blob_base_fee) .ok_or(format_err!("Failed to convert `eth_l1_data_gas_price` to NonZeroU128"))?; - gas_price.strk_l1_gas_price = NonZeroU128::new(eth_gas_price.saturating_mul(eth_strk_price)) - .ok_or(format_err!("Failed to convert `strk_l1_gas_price` to NonZeroU128"))?; - gas_price.strk_l1_data_gas_price = NonZeroU128::new(avg_blob_base_fee.saturating_mul(eth_strk_price)) + gas_price.strk_l1_gas_price = + NonZeroU128::new(stark_gas).ok_or(format_err!("Failed to convert `strk_l1_gas_price` to NonZeroU128"))?; + gas_price.strk_l1_data_gas_price = NonZeroU128::new(stark_data_gas) .ok_or(format_err!("Failed to convert `strk_l1_data_gas_price` to NonZeroU128"))?; gas_price.last_update_timestamp = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)?.as_millis(); // explicitly dropping gas price here to avoid long waits when fetching the value From 081939ba91c1b007fcbe73d0fc464618b24b2ac3 Mon Sep 17 00:00:00 2001 From: mcaseaux Date: Wed, 19 Jun 2024 19:10:47 +0200 Subject: [PATCH 02/16] Added oracle config --- crates/client/eth-client/src/config.rs | 101 +++++++++++++++++++++++ crates/client/l1-gas-price/src/worker.rs | 44 +++++----- examples/messaging/eth-config.json | 8 +- 3 files changed, 132 insertions(+), 21 deletions(-) diff --git a/crates/client/eth-client/src/config.rs b/crates/client/eth-client/src/config.rs index 3b2aabb1ef..f52c4cad74 100644 --- a/crates/client/eth-client/src/config.rs +++ b/crates/client/eth-client/src/config.rs @@ -29,6 +29,8 @@ pub const DEFAULT_CHAIN_ID: u64 = 31337; /// PRE_PRIVATE=$(jq -r '.private_keys[0]' $BUILD_DIR/anvil.json) pub const DEFAULT_PRIVATE_KEY: &str = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; +pub const DEFAULT_API_URL: &str = "https://api.dev.pragma.build/node/v1/data/"; + #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct EthereumClientConfig { #[serde(default)] @@ -37,6 +39,8 @@ pub struct EthereumClientConfig { pub wallet: Option, #[serde(default)] pub contracts: StarknetContracts, + #[serde(default)] + pub oracle: OracleConfig, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -70,6 +74,82 @@ pub struct HttpProviderConfig { pub gas_price_poll_ms: Option, } +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum OracleConfig { + Pragma(PragmaOracle), +} + +impl OracleConfig { + pub fn get_fetch_url(&self, base: String, quote: String) -> String { + match self { + OracleConfig::Pragma(pragma_oracle) => pragma_oracle.get_fetch_url(base, quote), + } + } + + pub fn get_api_key(&self) -> &String { + match self { + OracleConfig::Pragma(oracle) => &oracle.api_key, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct PragmaOracle { + #[serde(default = "default_api_url")] + pub api_url: String, + #[serde(default)] + pub api_key: String, + #[serde(default)] + pub aggregation_method: AggregationMethod, + #[serde(default)] + pub interval: Interval, +} + +impl PragmaOracle { + fn get_fetch_url(&self, base: String, quote: String) -> String { + format!( + "{}{}/{}?interval={:?}&aggregation={:?}", + self.api_url, base, quote, self.interval, self.aggregation_method + ) + } +} + +#[derive(Default, Debug, Serialize, Deserialize, Clone, Copy)] +pub enum AggregationMethod { + #[serde(rename = "median")] + #[default] + Median, + #[serde(rename = "mean")] + Mean, + #[serde(rename = "twap")] + Twap, +} + +// impl fmt::Display for AggregationMethod { +// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +// match self { +// AggregationMethod::Median => write!(f, "median"), +// AggregationMethod::Mean => write!(f, "mean"), +// AggregationMethod::Twap => write!(f, "twap"), +// } +// } +// } + +// Supported Aggregation Intervals +#[derive(Default, Debug, Serialize, Deserialize, Clone, Copy)] +pub enum Interval { + #[serde(rename = "1min")] + #[default] + OneMinute, + #[serde(rename = "15min")] + FifteenMinutes, + #[serde(rename = "1h")] + OneHour, + #[serde(rename = "2h")] + TwoHours, +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct LocalWalletConfig { #[serde(default = "default_chain_id")] @@ -82,6 +162,10 @@ fn default_rpc_endpoint() -> String { DEFAULT_RPC_ENDPOINT.into() } +fn default_api_url() -> String { + DEFAULT_API_URL.into() +} + fn default_chain_id() -> u64 { DEFAULT_CHAIN_ID } @@ -90,6 +174,23 @@ fn default_private_key() -> String { DEFAULT_PRIVATE_KEY.to_string() } +impl Default for PragmaOracle { + fn default() -> Self { + Self { + api_url: default_api_url(), + api_key: String::from(""), + aggregation_method: AggregationMethod::Median, + interval: Interval::OneMinute, + } + } +} + +impl Default for OracleConfig { + fn default() -> Self { + Self::Pragma(PragmaOracle::default()) + } +} + impl Default for HttpProviderConfig { fn default() -> Self { Self { rpc_endpoint: default_rpc_endpoint(), tx_poll_interval_ms: None, gas_price_poll_ms: None } diff --git a/crates/client/l1-gas-price/src/worker.rs b/crates/client/l1-gas-price/src/worker.rs index 43b458cf14..8589e5e621 100644 --- a/crates/client/l1-gas-price/src/worker.rs +++ b/crates/client/l1-gas-price/src/worker.rs @@ -6,7 +6,7 @@ use anyhow::{format_err, Result}; use ethers::types::U256; use ethers::utils::__serde_json::json; use futures::lock::Mutex; -use mc_eth_client::config::EthereumClientConfig; +use mc_eth_client::config::{EthereumClientConfig, OracleConfig}; use mp_starknet_inherent::L1GasPrices; use serde::Deserialize; use tokio::time::sleep; @@ -27,7 +27,7 @@ pub async fn run_worker(config: Arc, gas_price: Arc log::trace!("Updated gas prices"), Err(e) => log::error!("Failed to update gas prices: {:?}", e), } @@ -60,6 +60,7 @@ async fn update_gas_price( rpc_endpoint: String, client: &reqwest::Client, gas_price: Arc>, + oracle: OracleConfig, ) -> Result<()> { let fee_history: EthRpcResponse = client .post(rpc_endpoint.clone()) @@ -96,37 +97,40 @@ async fn update_gas_price( 16, )?; - // TODO: fetch this from the oracle - let url = "https://api.dev.pragma.build/node/v1/data/eth/strk?interval=1min&aggregation=median"; - let api_key = ""; + let response = reqwest::Client::new() + .get(oracle.get_fetch_url(String::from("eth"), String::from("strk"))) + .header("x-api-key", oracle.get_api_key()) + .send() + .await?; - let response = reqwest::Client::new().get(url).header("x-api-key", api_key).send().await?; + let res_json = response.json::().await; + + let mut gas_price = gas_price.lock().await; - let (price, decimal) = match response.json::().await { + match res_json { Ok(api_response) => { - log::trace!("Retrieved ETH/STRK price from Pragma API"); - (api_response.price, api_response.decimals) + log::trace!("Retrieved ETH/STRK price from Oracle"); + let eth_strk_price = u128::from_str_radix(api_response.price.trim_start_matches("0x"), 16)?; + let stark_gas = + ((U256::from(eth_gas_price) * U256::from(eth_strk_price)) / 10u64.pow(api_response.decimals)).as_u128(); + let stark_data_gas = ((U256::from(avg_blob_base_fee) * U256::from(eth_strk_price)) + / 10u64.pow(api_response.decimals)) + .as_u128(); + gas_price.strk_l1_gas_price = NonZeroU128::new(stark_gas) + .ok_or(format_err!("Failed to convert `strk_l1_gas_price` to NonZeroU128"))?; + gas_price.strk_l1_data_gas_price = NonZeroU128::new(stark_data_gas) + .ok_or(format_err!("Failed to convert `strk_l1_data_gas_price` to NonZeroU128"))?; } Err(e) => { log::error!("Failed to retrieve ETH/STRK price: {:?}", e); - (String::from(""), 0) } }; - let eth_strk_price = u128::from_str_radix(price.trim_start_matches("0x"), 16).expect("Invalid hex string"); - - let stark_gas = ((U256::from(eth_gas_price) * U256::from(eth_strk_price)) / 10u64.pow(decimal)).as_u128(); - let stark_data_gas = ((U256::from(avg_blob_base_fee) * U256::from(eth_strk_price)) / 10u64.pow(decimal)).as_u128(); - - let mut gas_price = gas_price.lock().await; gas_price.eth_l1_gas_price = NonZeroU128::new(eth_gas_price).ok_or(format_err!("Failed to convert `eth_gas_price` to NonZeroU128"))?; gas_price.eth_l1_data_gas_price = NonZeroU128::new(avg_blob_base_fee) .ok_or(format_err!("Failed to convert `eth_l1_data_gas_price` to NonZeroU128"))?; - gas_price.strk_l1_gas_price = - NonZeroU128::new(stark_gas).ok_or(format_err!("Failed to convert `strk_l1_gas_price` to NonZeroU128"))?; - gas_price.strk_l1_data_gas_price = NonZeroU128::new(stark_data_gas) - .ok_or(format_err!("Failed to convert `strk_l1_data_gas_price` to NonZeroU128"))?; + gas_price.last_update_timestamp = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)?.as_millis(); // explicitly dropping gas price here to avoid long waits when fetching the value // on the inherent side which would increase block time diff --git a/examples/messaging/eth-config.json b/examples/messaging/eth-config.json index b1b997e40f..56b56fd80d 100644 --- a/examples/messaging/eth-config.json +++ b/examples/messaging/eth-config.json @@ -5,5 +5,11 @@ }, "contracts": { "core_contract": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512" + }, + "oracle": { + "api_url": "https://api.dev.pragma.build/node/v1/data/eth/strk?interval=1min&aggregation=median", + "api_key": "", + "aggregation_method": "median", + "interval": "1min" } -} +} \ No newline at end of file From 12add8ae40eae666b99d8b8649ee41e54c7688e8 Mon Sep 17 00:00:00 2001 From: mcaseaux Date: Thu, 20 Jun 2024 10:16:44 +0200 Subject: [PATCH 03/16] added bounds parameter --- crates/client/eth-client/src/config.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/client/eth-client/src/config.rs b/crates/client/eth-client/src/config.rs index f52c4cad74..d33e7e6d3a 100644 --- a/crates/client/eth-client/src/config.rs +++ b/crates/client/eth-client/src/config.rs @@ -104,6 +104,8 @@ pub struct PragmaOracle { pub aggregation_method: AggregationMethod, #[serde(default)] pub interval: Interval, + #[serde(default)] + pub bounds: (u128, u128), } impl PragmaOracle { @@ -181,6 +183,7 @@ impl Default for PragmaOracle { api_key: String::from(""), aggregation_method: AggregationMethod::Median, interval: Interval::OneMinute, + bounds: (0, u128::MAX), } } } From fc7d5f103a70f05aa93b9a1661f374afd8a1c4fc Mon Sep 17 00:00:00 2001 From: mcaseaux Date: Thu, 20 Jun 2024 10:17:31 +0200 Subject: [PATCH 04/16] update changelogs --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22f97f514b..b504d893ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -347,3 +347,4 @@ - dev : clean contracts and compiled files - fix: add from_address in calldata of l1 message - test: add starkgate related testcase +- feat: add pragam api to compute fees From ccaab57d3b7cf72fe799fe14460510f628e32f34 Mon Sep 17 00:00:00 2001 From: mcaseaux Date: Thu, 20 Jun 2024 10:44:30 +0200 Subject: [PATCH 05/16] fix some things --- crates/client/eth-client/src/config.rs | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/crates/client/eth-client/src/config.rs b/crates/client/eth-client/src/config.rs index d33e7e6d3a..66e59a5fd1 100644 --- a/crates/client/eth-client/src/config.rs +++ b/crates/client/eth-client/src/config.rs @@ -117,38 +117,28 @@ impl PragmaOracle { } } -#[derive(Default, Debug, Serialize, Deserialize, Clone, Copy)] +#[derive(Default, Debug, Serialize, Deserialize, Clone)] pub enum AggregationMethod { #[serde(rename = "median")] - #[default] Median, #[serde(rename = "mean")] Mean, #[serde(rename = "twap")] + #[default] Twap, } -// impl fmt::Display for AggregationMethod { -// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -// match self { -// AggregationMethod::Median => write!(f, "median"), -// AggregationMethod::Mean => write!(f, "mean"), -// AggregationMethod::Twap => write!(f, "twap"), -// } -// } -// } - // Supported Aggregation Intervals -#[derive(Default, Debug, Serialize, Deserialize, Clone, Copy)] +#[derive(Default, Debug, Serialize, Deserialize, Clone)] pub enum Interval { #[serde(rename = "1min")] - #[default] OneMinute, #[serde(rename = "15min")] FifteenMinutes, #[serde(rename = "1h")] OneHour, #[serde(rename = "2h")] + #[default] TwoHours, } @@ -180,7 +170,7 @@ impl Default for PragmaOracle { fn default() -> Self { Self { api_url: default_api_url(), - api_key: String::from(""), + api_key: String::default(), aggregation_method: AggregationMethod::Median, interval: Interval::OneMinute, bounds: (0, u128::MAX), From 76bde870a409ca069148d030029fbb2db508d1f1 Mon Sep 17 00:00:00 2001 From: mcaseaux Date: Thu, 20 Jun 2024 10:45:55 +0200 Subject: [PATCH 06/16] update default config --- examples/messaging/eth-config.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/messaging/eth-config.json b/examples/messaging/eth-config.json index 56b56fd80d..d1ee2fec53 100644 --- a/examples/messaging/eth-config.json +++ b/examples/messaging/eth-config.json @@ -9,7 +9,11 @@ "oracle": { "api_url": "https://api.dev.pragma.build/node/v1/data/eth/strk?interval=1min&aggregation=median", "api_key": "", - "aggregation_method": "median", - "interval": "1min" + "aggregation_method": "twap", + "interval": "2h", + "bounds": [ + 0.5, + 1 + ] } } \ No newline at end of file From 63c59e8c3ed4405e6035675ec65d7efad9d9fd8a Mon Sep 17 00:00:00 2001 From: mcaseaux Date: Thu, 20 Jun 2024 13:15:55 +0200 Subject: [PATCH 07/16] added price security bounds handling --- crates/client/eth-client/src/config.rs | 47 +++++++++++++++++++++--- crates/client/l1-gas-price/src/worker.rs | 25 ++++++++----- examples/messaging/eth-config.json | 21 ++++++----- 3 files changed, 70 insertions(+), 23 deletions(-) diff --git a/crates/client/eth-client/src/config.rs b/crates/client/eth-client/src/config.rs index 66e59a5fd1..e932169b0c 100644 --- a/crates/client/eth-client/src/config.rs +++ b/crates/client/eth-client/src/config.rs @@ -75,7 +75,7 @@ pub struct HttpProviderConfig { } #[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(untagged)] +#[serde(tag = "oracle_name", content = "config")] pub enum OracleConfig { Pragma(PragmaOracle), } @@ -92,6 +92,18 @@ impl OracleConfig { OracleConfig::Pragma(oracle) => &oracle.api_key, } } + + pub fn is_in_bounds(&self, price: u128) -> bool { + match self { + OracleConfig::Pragma(oracle) => oracle.price_bounds.low <= price && price <= oracle.price_bounds.high, + } + } +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct PriceBounds { + pub low: u128, + pub high: u128, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -105,14 +117,18 @@ pub struct PragmaOracle { #[serde(default)] pub interval: Interval, #[serde(default)] - pub bounds: (u128, u128), + pub price_bounds: PriceBounds, } impl PragmaOracle { fn get_fetch_url(&self, base: String, quote: String) -> String { format!( - "{}{}/{}?interval={:?}&aggregation={:?}", - self.api_url, base, quote, self.interval, self.aggregation_method + "{}{}/{}?interval={}&aggregation={}", + self.api_url, + base, + quote, + self.interval.as_str(), + self.aggregation_method.as_str() ) } } @@ -128,6 +144,16 @@ pub enum AggregationMethod { Twap, } +impl AggregationMethod { + pub fn as_str(&self) -> &str { + match self { + AggregationMethod::Median => "median", + AggregationMethod::Mean => "mean", + AggregationMethod::Twap => "twap", + } + } +} + // Supported Aggregation Intervals #[derive(Default, Debug, Serialize, Deserialize, Clone)] pub enum Interval { @@ -142,6 +168,17 @@ pub enum Interval { TwoHours, } +impl Interval { + pub fn as_str(&self) -> &str { + match self { + Interval::OneMinute => "1min", + Interval::FifteenMinutes => "15min", + Interval::OneHour => "1h", + Interval::TwoHours => "2h", + } + } +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct LocalWalletConfig { #[serde(default = "default_chain_id")] @@ -173,7 +210,7 @@ impl Default for PragmaOracle { api_key: String::default(), aggregation_method: AggregationMethod::Median, interval: Interval::OneMinute, - bounds: (0, u128::MAX), + price_bounds: Default::default(), } } } diff --git a/crates/client/l1-gas-price/src/worker.rs b/crates/client/l1-gas-price/src/worker.rs index 8589e5e621..1f9a3a6fe1 100644 --- a/crates/client/l1-gas-price/src/worker.rs +++ b/crates/client/l1-gas-price/src/worker.rs @@ -111,17 +111,23 @@ async fn update_gas_price( Ok(api_response) => { log::trace!("Retrieved ETH/STRK price from Oracle"); let eth_strk_price = u128::from_str_radix(api_response.price.trim_start_matches("0x"), 16)?; - let stark_gas = - ((U256::from(eth_gas_price) * U256::from(eth_strk_price)) / 10u64.pow(api_response.decimals)).as_u128(); - let stark_data_gas = ((U256::from(avg_blob_base_fee) * U256::from(eth_strk_price)) - / 10u64.pow(api_response.decimals)) - .as_u128(); - gas_price.strk_l1_gas_price = NonZeroU128::new(stark_gas) - .ok_or(format_err!("Failed to convert `strk_l1_gas_price` to NonZeroU128"))?; - gas_price.strk_l1_data_gas_price = NonZeroU128::new(stark_data_gas) - .ok_or(format_err!("Failed to convert `strk_l1_data_gas_price` to NonZeroU128"))?; + if oracle.is_in_bounds(eth_strk_price) { + let stark_gas = ((U256::from(eth_gas_price) * U256::from(eth_strk_price)) + / 10u64.pow(api_response.decimals)) + .as_u128(); + let stark_data_gas = ((U256::from(avg_blob_base_fee) * U256::from(eth_strk_price)) + / 10u64.pow(api_response.decimals)) + .as_u128(); + gas_price.strk_l1_gas_price = NonZeroU128::new(stark_gas) + .ok_or(format_err!("Failed to convert `strk_l1_gas_price` to NonZeroU128"))?; + gas_price.strk_l1_data_gas_price = NonZeroU128::new(stark_data_gas) + .ok_or(format_err!("Failed to convert `strk_l1_data_gas_price` to NonZeroU128"))?; + } else { + log::error!("⚠️ Retrieved price is outside of bounds"); + } } Err(e) => { + println!("ERROR : {:?}", e); log::error!("Failed to retrieve ETH/STRK price: {:?}", e); } }; @@ -134,6 +140,7 @@ async fn update_gas_price( gas_price.last_update_timestamp = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)?.as_millis(); // explicitly dropping gas price here to avoid long waits when fetching the value // on the inherent side which would increase block time + println!("gas_price : {:#?}", gas_price); drop(gas_price); Ok(()) diff --git a/examples/messaging/eth-config.json b/examples/messaging/eth-config.json index d1ee2fec53..60a8e7a8ca 100644 --- a/examples/messaging/eth-config.json +++ b/examples/messaging/eth-config.json @@ -1,19 +1,22 @@ { "provider": { - "rpc_endpoint": "http://127.0.0.1:8545", + "rpc_endpoint": "https://ethereum-rpc.publicnode.com", "gas_price_poll_ms": 10000 }, "contracts": { "core_contract": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512" }, "oracle": { - "api_url": "https://api.dev.pragma.build/node/v1/data/eth/strk?interval=1min&aggregation=median", - "api_key": "", - "aggregation_method": "twap", - "interval": "2h", - "bounds": [ - 0.5, - 1 - ] + "oracle_name": "Pragma", + "config": { + "api_url": "https://api.dev.pragma.build/node/v1/data/", + "api_key": "", + "aggregation_method": "twap", + "interval": "2h", + "price_bounds": { + "low": 5000000000000000000000, + "high": 6000000000000000000000 + } + } } } \ No newline at end of file From 773e9f8bf856f2b3b2e92c2a277bf6dba674b55b Mon Sep 17 00:00:00 2001 From: mcaseaux Date: Thu, 20 Jun 2024 13:16:54 +0200 Subject: [PATCH 08/16] removed useless print --- crates/client/l1-gas-price/src/worker.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/client/l1-gas-price/src/worker.rs b/crates/client/l1-gas-price/src/worker.rs index 1f9a3a6fe1..115773e914 100644 --- a/crates/client/l1-gas-price/src/worker.rs +++ b/crates/client/l1-gas-price/src/worker.rs @@ -127,7 +127,6 @@ async fn update_gas_price( } } Err(e) => { - println!("ERROR : {:?}", e); log::error!("Failed to retrieve ETH/STRK price: {:?}", e); } }; @@ -140,7 +139,6 @@ async fn update_gas_price( gas_price.last_update_timestamp = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)?.as_millis(); // explicitly dropping gas price here to avoid long waits when fetching the value // on the inherent side which would increase block time - println!("gas_price : {:#?}", gas_price); drop(gas_price); Ok(()) From 57c7fa8a9a9fca9ff679ac63e1ffb447f3a64c78 Mon Sep 17 00:00:00 2001 From: mcaseaux Date: Thu, 20 Jun 2024 13:22:48 +0200 Subject: [PATCH 09/16] fix linter --- .../articles/cn/madara-beast-article.md | 71 +++++++++---------- docs/contributor-starter-pack.md | 53 +++++++------- examples/messaging/eth-config.json | 2 +- 3 files changed, 57 insertions(+), 69 deletions(-) diff --git a/docs/content/articles/cn/madara-beast-article.md b/docs/content/articles/cn/madara-beast-article.md index 8586137585..83ce33eca6 100644 --- a/docs/content/articles/cn/madara-beast-article.md +++ b/docs/content/articles/cn/madara-beast-article.md @@ -30,32 +30,30 @@ 试想一下,为你的应用程序的特殊需求来量身定制一条区块链——这正是应用链可以提供的 功能。应用链是面向特定应用程序的区块链,开发人员可以灵活调整链的各个方面,从而 -满足能。应用链是面向特定应用程序的区块链,开发人员可以灵活调整链的各个方面,从而满 +足其应用的需求,例如选择不同的哈希函数或自定义共识算法。最棒的是,由于应用链建 立在L1 或 L2 区块链之上,可以继承其强大的安全性,为开发人员提供了两全其美的解决方 -案。 +-->L1 或 L2 区块链之上,可以继承其强大的安全性,为开发人员提供了两全其美的解决方案。 介绍下 Madara,这是一个将灵活性和极速性能相结合的划时代的排序器。排序器这一组件 负责执行交易并将它们分组到批次中。作为通往属于你的 Starknet 应用链的入 -口,Madara 为在责执行交易并将它们分组到批次中。作为通往属于你的 Starknet 应用链的入口,Madara +为在Starknet 生态系统中进行前所未有的实验开辟了广阔的可能性。 在我们深入探讨 Madara 如何为 Starknet 应用链带来强大的能力前,有必要解决一个问 题:为什么开发人员会选择在 Starknet 上构建应用链,而不是直接使用[Starknet 有效性 Rollups](https://starkware.co/resource/scaling-ethereum-navigating-the-blockchain-trilemma/#:~:text=top%20of%20them.-,Validity%20Rollups,-Validity%20rollups%2C%20also)。有 -人可能会想,Starknet 是否已经足以应对大多数情况。 +-->用[Starknet 有效性 Rollups](https://starkware.co/resource/scaling-ethereum-navigating-the-blockchain-trilemma/#:~:text=top%20of%20them.-,Validity%20Rollups,-Validity%20rollups%2C%20also)。 +有人可能会想,Starknet 是否已经足以应对大多数情况。 首先让我们了解下为什么应用链是 Starknet 生态系统中引人注目的扩展方式。 ## 为什么选择应用链 Madara 是由 StarkWare 探索团队,也称为[Keep Starknet Strange](https://github.com/keep-starknet-strange)开发的,专 -门为[Keep Starknet Strange](https://github.com/keep-starknet-strange)开发的,专门设计用于实现 StarkWare的[分形缩放](https://medium.com/starkware/fractal-scaling-from-l2-to-l3-7fe238ecfb4f)愿景。有许多令人信服的原因让开发人员选择创建一个 Starknet 应用链或 L3,而不是直 @@ -70,23 +68,22 @@ Madara 是由 StarkWare 探索团队,也称的整体成本,最高可达一百万倍。由于应用程序建立在其专用区块链上,从而无需与其 他应用竞争链上资源,吞吐量不受第三方应用活动的影响,这确保了持续平稳的流畅体 -验。 +-->应用竞争链上资源,吞吐量不受第三方应用活动的影响,这确保了持续平稳的流畅体验。 ### 定制化 像 Starknet 和 Ethereum 等通用链采取了多项措施来确保网络对所有人可用,但这导致了 一种受限的环境。通过应用链,开发人员可以微调其应用和基础设施的各个方面,创建量身 -定制受限的环境。通过应用链,开发人员可以微调其应用和基础设施的各个方面,创建量身定 +制的解决方案。不喜欢 Cairo VM 的某个特性?可以在你的应用链中将其排除掉。 ### 创新 应用链的可定制性还允许开发人员可以使用目前在 Starknet 中不可用或存在风险的功能。 应用链赋予每个团队自主权,允许他们编写和授权任何所需的代码 hints。这使得应用链 -能够用链赋予每个团队自主权,允许他们编写和授权任何所需的代码 hints。这使得应用链能 +够解锁许多用例,譬如可以在不泄露个人隐私的情况下执行链上 KYC。 ## Madara 对应用链堆栈的影响 @@ -95,33 +92,31 @@ Madara 是由 StarkWare 探索团队,也称包(StarkWare 的 - [blockifier](https://github.com/starkware-libs/blockifier)包(StarkWare 的 [blockifier](https://github.com/starkware-libs/blockifier)和 LambdaClass 的[starknet_in_rust](https://github.com/lambdaclass/starknet_in_rust))之间 - 切换的灵活性。无论选择了哪个执行工具包,底层框架都使用 Cairo VM。Cairo 语言有 - 助于创建可证明的程序,这样就能证明计算被正确执行。 + -->[starknet_in_rust](https://github.com/lambdaclass/starknet_in_rust))之间切 + 换的灵活性。无论选择了哪个执行工具包,底层框架都使用 Cairo VM。Cairo 语言有助于 + 创建可证明的程序,这样就能证明计算被正确执行。 2. **结算:** 作为有效性 Rollup,Madara 应用链的状态可以仅通过检查其结算层来重 建。通过在 Starknet L2 上更频繁的结算,L3 应用链可以实现更快的硬最终性,而去 中心化的排序层实现更强大的软最终性,因此,在这两方面(硬和软终结性),结算都得到了 - 增排序层实现更强大的软最终性,因此,在这两方面(硬和软终结性),结算都得到了增强。 3. **排序:** Madara 负责排序过程,可以根据应用的需求进行调整,无论是简单的 FCFS 或PGA,还是像 Narwhall 和 Bullshark 这类更复杂的方案。一些应用链可以选择部署 - 加密内PGA,还是像 Narwhall 和 Bullshark 这类更复杂的方案。一些应用链可以选择部署加 + 密内存池,以确保公平排序并减轻 MEV 的影响。 4. **数据可用性:** 数据可用性保证始终可访问完整的状态树,借此向用户提供信心, 即使 Madara 发生故障的情况下,他们也能证明自己拥有资产的所有权。Madara 将为 - 开发者使 Madara 发生故障的情况下,他们也能证明自己拥有资产的所有权。Madara 将为开 + 发者提供多种可供选择的数据可用性方案。 5. **治理:** 每个 Madara 应用链可以选择其治理模 型。[Snapshot X](https://twitter.com/SnapshotLabs)提供了一个依赖于存储证明 并完全基于链上的治理系统。其他治理机制也在探索中,譬如原生的 Substrate 治理 - 面板。链上治理是 Madara 的核心价值所在。 + -->完全基于链上的治理系统。其他治理机制也在探索中,譬如原生的 Substrate 治理面 + 板。链上治理是 Madara 的核心价值所在。 ![come come](https://lh4.googleusercontent.com/i7bXi2IPV-LTLzEgueA2SPHGULUFDj1OX4IznOQr5BeZe0hcey-VXA5TOV6q9XaVqBGAcYiie7u7uxw7q1ByZxjkPQKHERqKJTxhdDdTSgBQy8smyNO3jEHiNJv7Eqh8BMxjj4fFlQAW6gm-hQMzyIU) @@ -129,27 +124,25 @@ Madara 是由 StarkWare 探索团队,也称约,从而增强了 Cairo VM。Substrate 是一个开源 Rust 框架,以其灵活性而闻名,并 -用于构约,从而增强了 Cairo VM。Substrate 是一个开源 Rust 框架,以其灵活性而闻名,并用 +于构建可定制的区块链。与此同时,Cairo VM 专门设计用于高效生成程序执行的有效性证 明。通过在 L2 上使用状态跟踪和智能合约来验证这些证明,应用链确保集成了 Starknet 的 -安全性。这样,Madara 利用 Cairo 的强大功能实现了程序执行的可证明性。 +-->过在 L2 上使用状态跟踪和智能合约来验证这些证明,应用链确保集成了 Starknet 的安 +全性。这样,Madara 利用 Cairo 的强大功能实现了程序执行的可证明性。 Substrate 框架固有的模块化特性使开发者可以轻松地定制应用链。没有任何强加的假设, 允许你自行整合共识协议、哈希函数、签名方案、存储布局 - 无论你的应用需要什么, 都可以利用 Cairo 来生成证明。无论是 Starknet 还是 Ethereum 上,开发者都可以在继 -承底层链可以利用 Cairo 来生成证明。无论是 Starknet 还是 Ethereum 上,开发者都可以在继承 +底层链安全性的同时,不受限制的操作,并可被证明。 起初,Madara 将与 Starknet 非常相似,使智能合约可以在 Starknet 生态系统内进行组 合。未来将有更宏伟的计划,因为 Starknet 将 -与[Herodotus](https://www.herodotus.dev/)集来将有更宏伟的计划,因为 Starknet 将与[Herodotus](https://www.herodotus.dev/)集成,利用 [存储证明](https://book.starknet.io/chapter_8/storage_proofs.html)实 现互操作性。存储证明的整合还将使 Madara 应用链能够考虑来自其他链的状态和流动 -性。 +-->互操作性。存储证明的整合还将使 Madara 应用链能够考虑来自其他链的状态和流动性。 准备好见证由 Madara 开启的 Starknet 新纪元吧。 diff --git a/docs/contributor-starter-pack.md b/docs/contributor-starter-pack.md index ff233d3d3a..83f54eb29c 100644 --- a/docs/contributor-starter-pack.md +++ b/docs/contributor-starter-pack.md @@ -41,26 +41,25 @@ are some key aspects of the mindset that can help you navigate your contribution journey: - _Openness to Learning_\ - Embrace a mindset of continuous learning and be open to acquiring new - knowledge and skills. Starknet is a recent ecosystem and does have its own - unique concepts and principles. Stay curious, ask questions (there are no dumb - questions), and be willing to explore and understand new concepts. + Embrace a mindset of continuous learning and be open to acquiring new knowledge + and skills. Starknet is a recent ecosystem and does have its own unique concepts + and principles. Stay curious, ask questions (there are no dumb questions), and + be willing to explore and understand new concepts. - _Patience and Perseverance_\ - Contributing to a complex or quickly evolving project takes time and effort. - Be patient with yourself and the learning process. Expect challenges along the - way, but persevere through them. Building expertise and making meaningful - contributions often requires persistence and determination. + Contributing to a complex or quickly evolving project takes time and effort. Be + patient with yourself and the learning process. Expect challenges along the way, + but persevere through them. Building expertise and making meaningful contributions + often requires persistence and determination. - _Collaboration and Communication_\ - Engage with the community, ask for guidance when needed, and seek feedback on - your contributions. Actively participate in GitHub discussions, issues or chat - channels. Be respectful and constructive with other builders. + Engage with the community, ask for guidance when needed, and seek feedback on your + contributions. Actively participate in GitHub discussions, issues or chat channels. + Be respectful and constructive with other builders. - _Respect for Existing Contributors_\ - Recognize and respect the work of existing contributors and maintainers. - Appreciate the efforts of others and collaborate with them in a respectful and - inclusive manner. + Recognize and respect the work of existing contributors and maintainers. Appreciate + the efforts of others and collaborate with them in a respectful and inclusive manner. With this mindset, you'll participate to Madara and Starknet projects in a collaborative and productive atmosphere. It's not everything about code but also @@ -83,8 +82,7 @@ some valuable and helpful resources. [The Rust Programming Language Book](https://doc.rust-lang.org/book/): read this first\ -[Rust by Example](https://doc.rust-lang.org/rust-by-example/): practical -approach\ +[Rust by Example](https://doc.rust-lang.org/rust-by-example/): practical approach\ [Rustlings](https://github.com/rust-lang/rustlings): Educative and interactive learning @@ -148,19 +146,17 @@ build. Some key features of Substrate are: - _Modular Framework_\ - Substrate provides a modular framework that allows developers to easily - customize and configure various components of a blockchain network. + Substrate provides a modular framework that allows developers to easily customize + and configure various components of a blockchain network. - _Efficiency and Scalability_\ - Substrate leverages advanced techniques such as in its transaction queue - management to ensure high performance and the ability to handle a large number - of transactions. + Substrate leverages advanced techniques such as in its transaction queue management + to ensure high performance and the ability to handle a large number of transactions. - _Runtime Upgradability_\ - Substrate allows for seamless runtime upgrades, enabling the introduction of - new features or bug fixes in a live blockchain network without requiring a - hard fork. This feature enhances the upgradability and maintainability of the - blockchain system. + Substrate allows for seamless runtime upgrades, enabling the introduction of new + features or bug fixes in a live blockchain network without requiring a hard fork. + This feature enhances the upgradability and maintainability of the blockchain system. Substrate achieves its modularity through three key components: the **client**, the **runtime**, and the **primitives**. Those are key concepts of Substrate @@ -287,8 +283,7 @@ organized and executed in a secure and deterministic manner. You can find Madara documentation (work in progress) [here](https://docs.madara.wtf/).\ -You can contribute to this documentation -[here](https://github.com/keep-starknet-strange/madara-docs). +You can contribute to this documentation [here](https://github.com/keep-starknet-strange/madara-docs). How to contribute? @@ -315,8 +310,8 @@ future of Ethereum scaling! guide](https://docs.github.com/en/get-started/quickstart/hello-world)\ [Madara GitHub repository](https://github.com/keep-starknet-strange/madara)\ [Madara Telegram](https://t.me/MadaraStarknet)\ -[Starknet Discord](https://discord.gg/qypnmzkhbc) (Or search for Starknet in -discord's servers browser) +[Starknet Discord](https://discord.gg/qypnmzkhbc) (Or search for Starknet in discord's +servers browser) ## Contribution rewards on OnlyDust diff --git a/examples/messaging/eth-config.json b/examples/messaging/eth-config.json index 60a8e7a8ca..7936ee942d 100644 --- a/examples/messaging/eth-config.json +++ b/examples/messaging/eth-config.json @@ -19,4 +19,4 @@ } } } -} \ No newline at end of file +} From 4f15b6a118a449971493cc9df5659ce06634520f Mon Sep 17 00:00:00 2001 From: mcaseaux Date: Thu, 20 Jun 2024 13:31:31 +0200 Subject: [PATCH 10/16] fix lint --- .../articles/cn/madara-beast-article.md | 71 ++++++++++--------- docs/contributor-starter-pack.md | 53 +++++++------- 2 files changed, 68 insertions(+), 56 deletions(-) diff --git a/docs/content/articles/cn/madara-beast-article.md b/docs/content/articles/cn/madara-beast-article.md index 83ce33eca6..8586137585 100644 --- a/docs/content/articles/cn/madara-beast-article.md +++ b/docs/content/articles/cn/madara-beast-article.md @@ -30,30 +30,32 @@ 试想一下,为你的应用程序的特殊需求来量身定制一条区块链——这正是应用链可以提供的 功能。应用链是面向特定应用程序的区块链,开发人员可以灵活调整链的各个方面,从而满 -足能。应用链是面向特定应用程序的区块链,开发人员可以灵活调整链的各个方面,从而 +满足其应用的需求,例如选择不同的哈希函数或自定义共识算法。最棒的是,由于应用链建 立在L1 或 L2 区块链之上,可以继承其强大的安全性,为开发人员提供了两全其美的解决方案。 +-->L1 或 L2 区块链之上,可以继承其强大的安全性,为开发人员提供了两全其美的解决方 +案。 介绍下 Madara,这是一个将灵活性和极速性能相结合的划时代的排序器。排序器这一组件 负责执行交易并将它们分组到批次中。作为通往属于你的 Starknet 应用链的入口,Madara -为在责执行交易并将它们分组到批次中。作为通往属于你的 Starknet 应用链的入 +口,Madara 为在Starknet 生态系统中进行前所未有的实验开辟了广阔的可能性。 在我们深入探讨 Madara 如何为 Starknet 应用链带来强大的能力前,有必要解决一个问 题:为什么开发人员会选择在 Starknet 上构建应用链,而不是直接使用[Starknet 有效性 Rollups](https://starkware.co/resource/scaling-ethereum-navigating-the-blockchain-trilemma/#:~:text=top%20of%20them.-,Validity%20Rollups,-Validity%20rollups%2C%20also)。 -有人可能会想,Starknet 是否已经足以应对大多数情况。 +-->用[Starknet 有效性 Rollups](https://starkware.co/resource/scaling-ethereum-navigating-the-blockchain-trilemma/#:~:text=top%20of%20them.-,Validity%20Rollups,-Validity%20rollups%2C%20also)。有 +人可能会想,Starknet 是否已经足以应对大多数情况。 首先让我们了解下为什么应用链是 Starknet 生态系统中引人注目的扩展方式。 ## 为什么选择应用链 Madara 是由 StarkWare 探索团队,也称为[Keep Starknet Strange](https://github.com/keep-starknet-strange)开发的,专门为[Keep Starknet Strange](https://github.com/keep-starknet-strange)开发的,专 +门设计用于实现 StarkWare的[分形缩放](https://medium.com/starkware/fractal-scaling-from-l2-to-l3-7fe238ecfb4f)愿景。有许多令人信服的原因让开发人员选择创建一个 Starknet 应用链或 L3,而不是直 @@ -68,22 +70,23 @@ Madara 是由 StarkWare 探索团队,也称的整体成本,最高可达一百万倍。由于应用程序建立在其专用区块链上,从而无需与其 他应用竞争链上资源,吞吐量不受第三方应用活动的影响,这确保了持续平稳的流畅体验。 +-->应用竞争链上资源,吞吐量不受第三方应用活动的影响,这确保了持续平稳的流畅体 +验。 ### 定制化 像 Starknet 和 Ethereum 等通用链采取了多项措施来确保网络对所有人可用,但这导致了 一种受限的环境。通过应用链,开发人员可以微调其应用和基础设施的各个方面,创建量身定 -制受限的环境。通过应用链,开发人员可以微调其应用和基础设施的各个方面,创建量身 +定制的解决方案。不喜欢 Cairo VM 的某个特性?可以在你的应用链中将其排除掉。 ### 创新 应用链的可定制性还允许开发人员可以使用目前在 Starknet 中不可用或存在风险的功能。 应用链赋予每个团队自主权,允许他们编写和授权任何所需的代码 hints。这使得应用链能 -够用链赋予每个团队自主权,允许他们编写和授权任何所需的代码 hints。这使得应用链 +能够解锁许多用例,譬如可以在不泄露个人隐私的情况下执行链上 KYC。 ## Madara 对应用链堆栈的影响 @@ -92,31 +95,33 @@ Madara 是由 StarkWare 探索团队,也称包(StarkWare 的 [blockifier](https://github.com/starkware-libs/blockifier)包(StarkWare 的 + [blockifier](https://github.com/starkware-libs/blockifier)和 LambdaClass 的[starknet_in_rust](https://github.com/lambdaclass/starknet_in_rust))之间切 - 换的灵活性。无论选择了哪个执行工具包,底层框架都使用 Cairo VM。Cairo 语言有助于 - 创建可证明的程序,这样就能证明计算被正确执行。 + -->[starknet_in_rust](https://github.com/lambdaclass/starknet_in_rust))之间 + 切换的灵活性。无论选择了哪个执行工具包,底层框架都使用 Cairo VM。Cairo 语言有 + 助于创建可证明的程序,这样就能证明计算被正确执行。 2. **结算:** 作为有效性 Rollup,Madara 应用链的状态可以仅通过检查其结算层来重 建。通过在 Starknet L2 上更频繁的结算,L3 应用链可以实现更快的硬最终性,而去 中心化的排序层实现更强大的软最终性,因此,在这两方面(硬和软终结性),结算都得到了增排序层实现更强大的软最终性,因此,在这两方面(硬和软终结性),结算都得到了 + 增强。 3. **排序:** Madara 负责排序过程,可以根据应用的需求进行调整,无论是简单的 FCFS 或PGA,还是像 Narwhall 和 Bullshark 这类更复杂的方案。一些应用链可以选择部署加 - 密内PGA,还是像 Narwhall 和 Bullshark 这类更复杂的方案。一些应用链可以选择部署 + 加密内存池,以确保公平排序并减轻 MEV 的影响。 4. **数据可用性:** 数据可用性保证始终可访问完整的状态树,借此向用户提供信心, 即使 Madara 发生故障的情况下,他们也能证明自己拥有资产的所有权。Madara 将为开 - 发者使 Madara 发生故障的情况下,他们也能证明自己拥有资产的所有权。Madara 将为 + 开发者提供多种可供选择的数据可用性方案。 5. **治理:** 每个 Madara 应用链可以选择其治理模 型。[Snapshot X](https://twitter.com/SnapshotLabs)提供了一个依赖于存储证明 并完全基于链上的治理系统。其他治理机制也在探索中,譬如原生的 Substrate 治理面 - 板。链上治理是 Madara 的核心价值所在。 + -->完全基于链上的治理系统。其他治理机制也在探索中,譬如原生的 Substrate 治理 + 面板。链上治理是 Madara 的核心价值所在。 ![come come](https://lh4.googleusercontent.com/i7bXi2IPV-LTLzEgueA2SPHGULUFDj1OX4IznOQr5BeZe0hcey-VXA5TOV6q9XaVqBGAcYiie7u7uxw7q1ByZxjkPQKHERqKJTxhdDdTSgBQy8smyNO3jEHiNJv7Eqh8BMxjj4fFlQAW6gm-hQMzyIU) @@ -124,25 +129,27 @@ Madara 是由 StarkWare 探索团队,也称约,从而增强了 Cairo VM。Substrate 是一个开源 Rust 框架,以其灵活性而闻名,并用 -于构约,从而增强了 Cairo VM。Substrate 是一个开源 Rust 框架,以其灵活性而闻名,并 +用于构建可定制的区块链。与此同时,Cairo VM 专门设计用于高效生成程序执行的有效性证 明。通过在 L2 上使用状态跟踪和智能合约来验证这些证明,应用链确保集成了 Starknet 的安 -全性。这样,Madara 利用 Cairo 的强大功能实现了程序执行的可证明性。 +-->过在 L2 上使用状态跟踪和智能合约来验证这些证明,应用链确保集成了 Starknet 的 +安全性。这样,Madara 利用 Cairo 的强大功能实现了程序执行的可证明性。 Substrate 框架固有的模块化特性使开发者可以轻松地定制应用链。没有任何强加的假设, 允许你自行整合共识协议、哈希函数、签名方案、存储布局 - 无论你的应用需要什么, 都可以利用 Cairo 来生成证明。无论是 Starknet 还是 Ethereum 上,开发者都可以在继承 -底层链可以利用 Cairo 来生成证明。无论是 Starknet 还是 Ethereum 上,开发者都可以在继 +承底层链安全性的同时,不受限制的操作,并可被证明。 起初,Madara 将与 Starknet 非常相似,使智能合约可以在 Starknet 生态系统内进行组 合。未来将有更宏伟的计划,因为 Starknet 将与[Herodotus](https://www.herodotus.dev/)集来将有更宏伟的计划,因为 Starknet 将 +与[Herodotus](https://www.herodotus.dev/)集成,利用 [存储证明](https://book.starknet.io/chapter_8/storage_proofs.html)实 现互操作性。存储证明的整合还将使 Madara 应用链能够考虑来自其他链的状态和流动性。 +-->互操作性。存储证明的整合还将使 Madara 应用链能够考虑来自其他链的状态和流动 +性。 准备好见证由 Madara 开启的 Starknet 新纪元吧。 diff --git a/docs/contributor-starter-pack.md b/docs/contributor-starter-pack.md index 83f54eb29c..ff233d3d3a 100644 --- a/docs/contributor-starter-pack.md +++ b/docs/contributor-starter-pack.md @@ -41,25 +41,26 @@ are some key aspects of the mindset that can help you navigate your contribution journey: - _Openness to Learning_\ - Embrace a mindset of continuous learning and be open to acquiring new knowledge - and skills. Starknet is a recent ecosystem and does have its own unique concepts - and principles. Stay curious, ask questions (there are no dumb questions), and - be willing to explore and understand new concepts. + Embrace a mindset of continuous learning and be open to acquiring new + knowledge and skills. Starknet is a recent ecosystem and does have its own + unique concepts and principles. Stay curious, ask questions (there are no dumb + questions), and be willing to explore and understand new concepts. - _Patience and Perseverance_\ - Contributing to a complex or quickly evolving project takes time and effort. Be - patient with yourself and the learning process. Expect challenges along the way, - but persevere through them. Building expertise and making meaningful contributions - often requires persistence and determination. + Contributing to a complex or quickly evolving project takes time and effort. + Be patient with yourself and the learning process. Expect challenges along the + way, but persevere through them. Building expertise and making meaningful + contributions often requires persistence and determination. - _Collaboration and Communication_\ - Engage with the community, ask for guidance when needed, and seek feedback on your - contributions. Actively participate in GitHub discussions, issues or chat channels. - Be respectful and constructive with other builders. + Engage with the community, ask for guidance when needed, and seek feedback on + your contributions. Actively participate in GitHub discussions, issues or chat + channels. Be respectful and constructive with other builders. - _Respect for Existing Contributors_\ - Recognize and respect the work of existing contributors and maintainers. Appreciate - the efforts of others and collaborate with them in a respectful and inclusive manner. + Recognize and respect the work of existing contributors and maintainers. + Appreciate the efforts of others and collaborate with them in a respectful and + inclusive manner. With this mindset, you'll participate to Madara and Starknet projects in a collaborative and productive atmosphere. It's not everything about code but also @@ -82,7 +83,8 @@ some valuable and helpful resources. [The Rust Programming Language Book](https://doc.rust-lang.org/book/): read this first\ -[Rust by Example](https://doc.rust-lang.org/rust-by-example/): practical approach\ +[Rust by Example](https://doc.rust-lang.org/rust-by-example/): practical +approach\ [Rustlings](https://github.com/rust-lang/rustlings): Educative and interactive learning @@ -146,17 +148,19 @@ build. Some key features of Substrate are: - _Modular Framework_\ - Substrate provides a modular framework that allows developers to easily customize - and configure various components of a blockchain network. + Substrate provides a modular framework that allows developers to easily + customize and configure various components of a blockchain network. - _Efficiency and Scalability_\ - Substrate leverages advanced techniques such as in its transaction queue management - to ensure high performance and the ability to handle a large number of transactions. + Substrate leverages advanced techniques such as in its transaction queue + management to ensure high performance and the ability to handle a large number + of transactions. - _Runtime Upgradability_\ - Substrate allows for seamless runtime upgrades, enabling the introduction of new - features or bug fixes in a live blockchain network without requiring a hard fork. - This feature enhances the upgradability and maintainability of the blockchain system. + Substrate allows for seamless runtime upgrades, enabling the introduction of + new features or bug fixes in a live blockchain network without requiring a + hard fork. This feature enhances the upgradability and maintainability of the + blockchain system. Substrate achieves its modularity through three key components: the **client**, the **runtime**, and the **primitives**. Those are key concepts of Substrate @@ -283,7 +287,8 @@ organized and executed in a secure and deterministic manner. You can find Madara documentation (work in progress) [here](https://docs.madara.wtf/).\ -You can contribute to this documentation [here](https://github.com/keep-starknet-strange/madara-docs). +You can contribute to this documentation +[here](https://github.com/keep-starknet-strange/madara-docs). How to contribute? @@ -310,8 +315,8 @@ future of Ethereum scaling! guide](https://docs.github.com/en/get-started/quickstart/hello-world)\ [Madara GitHub repository](https://github.com/keep-starknet-strange/madara)\ [Madara Telegram](https://t.me/MadaraStarknet)\ -[Starknet Discord](https://discord.gg/qypnmzkhbc) (Or search for Starknet in discord's -servers browser) +[Starknet Discord](https://discord.gg/qypnmzkhbc) (Or search for Starknet in +discord's servers browser) ## Contribution rewards on OnlyDust From 413595b356a58fa373f3bbd24539d9efdc67292e Mon Sep 17 00:00:00 2001 From: mcaseaux Date: Thu, 20 Jun 2024 13:33:05 +0200 Subject: [PATCH 11/16] modified bounds to some correct ones --- examples/messaging/eth-config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/messaging/eth-config.json b/examples/messaging/eth-config.json index 7936ee942d..5d5a6f5bf8 100644 --- a/examples/messaging/eth-config.json +++ b/examples/messaging/eth-config.json @@ -14,9 +14,9 @@ "aggregation_method": "twap", "interval": "2h", "price_bounds": { - "low": 5000000000000000000000, + "low": 3000000000000000000000, "high": 6000000000000000000000 } } } -} +} \ No newline at end of file From b7d7955fa759335e9706532f36bdc5c38575c02b Mon Sep 17 00:00:00 2001 From: mcaseaux Date: Thu, 20 Jun 2024 13:44:44 +0200 Subject: [PATCH 12/16] fix lint --- examples/messaging/eth-config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/messaging/eth-config.json b/examples/messaging/eth-config.json index 5d5a6f5bf8..46bb180b47 100644 --- a/examples/messaging/eth-config.json +++ b/examples/messaging/eth-config.json @@ -19,4 +19,4 @@ } } } -} \ No newline at end of file +} From f76dea180052e31d50d06a050888a3cdd475d279 Mon Sep 17 00:00:00 2001 From: 0xevolve Date: Thu, 20 Jun 2024 12:54:38 +0100 Subject: [PATCH 13/16] fix: smol fixes --- crates/client/eth-client/src/config.rs | 35 +++++------------------- crates/client/l1-gas-price/src/worker.rs | 8 ++++-- 2 files changed, 13 insertions(+), 30 deletions(-) diff --git a/crates/client/eth-client/src/config.rs b/crates/client/eth-client/src/config.rs index e932169b0c..395f6e69fc 100644 --- a/crates/client/eth-client/src/config.rs +++ b/crates/client/eth-client/src/config.rs @@ -100,6 +100,9 @@ impl OracleConfig { } } +/// Price bounds for the oracle +/// If the price is outside of these bounds, it will not be used +/// The bounds are denominated in the quote currency so in FRI here. #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct PriceBounds { pub low: u128, @@ -123,16 +126,13 @@ pub struct PragmaOracle { impl PragmaOracle { fn get_fetch_url(&self, base: String, quote: String) -> String { format!( - "{}{}/{}?interval={}&aggregation={}", - self.api_url, - base, - quote, - self.interval.as_str(), - self.aggregation_method.as_str() + "{}{}/{}?interval={:?}&aggregation={:?}", + self.api_url, base, quote, self.interval, self.aggregation_method ) } } +/// Supported Aggregation Methods #[derive(Default, Debug, Serialize, Deserialize, Clone)] pub enum AggregationMethod { #[serde(rename = "median")] @@ -144,17 +144,7 @@ pub enum AggregationMethod { Twap, } -impl AggregationMethod { - pub fn as_str(&self) -> &str { - match self { - AggregationMethod::Median => "median", - AggregationMethod::Mean => "mean", - AggregationMethod::Twap => "twap", - } - } -} - -// Supported Aggregation Intervals +/// Supported Aggregation Intervals #[derive(Default, Debug, Serialize, Deserialize, Clone)] pub enum Interval { #[serde(rename = "1min")] @@ -168,17 +158,6 @@ pub enum Interval { TwoHours, } -impl Interval { - pub fn as_str(&self) -> &str { - match self { - Interval::OneMinute => "1min", - Interval::FifteenMinutes => "15min", - Interval::OneHour => "1h", - Interval::TwoHours => "2h", - } - } -} - #[derive(Debug, Clone, Serialize, Deserialize)] pub struct LocalWalletConfig { #[serde(default = "default_chain_id")] diff --git a/crates/client/l1-gas-price/src/worker.rs b/crates/client/l1-gas-price/src/worker.rs index 115773e914..c9d4057989 100644 --- a/crates/client/l1-gas-price/src/worker.rs +++ b/crates/client/l1-gas-price/src/worker.rs @@ -16,7 +16,7 @@ use crate::types::{EthRpcResponse, FeeHistory}; const DEFAULT_GAS_PRICE_POLL_MS: u64 = 10_000; #[derive(Deserialize, Debug)] -struct ApiResponse { +struct OracleApiResponse { price: String, decimals: u32, } @@ -103,10 +103,14 @@ async fn update_gas_price( .send() .await?; - let res_json = response.json::().await; + let res_json = response.json::().await; let mut gas_price = gas_price.lock().await; + // We query the Oracle API for the ETH/STRK price feed + // If the api response is successful AND the price is within the bounds + // Then we update the strk_l1_gas_price and strk_l1_data_gas_price fields + // Otherwise we log an error and we keep the previous values match res_json { Ok(api_response) => { log::trace!("Retrieved ETH/STRK price from Oracle"); From 52029a1679ad0128e9fcde6600ce3882f0689c72 Mon Sep 17 00:00:00 2001 From: mcaseaux Date: Thu, 20 Jun 2024 18:36:20 +0200 Subject: [PATCH 14/16] moved everything to a mod and renamed some variable --- crates/client/eth-client/src/config.rs | 130 +--------------------- crates/client/eth-client/src/lib.rs | 1 + crates/client/eth-client/src/oracle.rs | 136 +++++++++++++++++++++++ crates/client/l1-gas-price/src/worker.rs | 9 +- 4 files changed, 143 insertions(+), 133 deletions(-) create mode 100644 crates/client/eth-client/src/oracle.rs diff --git a/crates/client/eth-client/src/config.rs b/crates/client/eth-client/src/config.rs index e932169b0c..4d0d0072d2 100644 --- a/crates/client/eth-client/src/config.rs +++ b/crates/client/eth-client/src/config.rs @@ -19,6 +19,7 @@ use ethers::types::{Address, H160}; use serde::{Deserialize, Serialize}; use crate::error::Error; +use crate::oracle::OracleConfig; /// Default Anvil local endpoint pub const DEFAULT_RPC_ENDPOINT: &str = "http://127.0.0.1:8545"; @@ -29,8 +30,6 @@ pub const DEFAULT_CHAIN_ID: u64 = 31337; /// PRE_PRIVATE=$(jq -r '.private_keys[0]' $BUILD_DIR/anvil.json) pub const DEFAULT_PRIVATE_KEY: &str = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; -pub const DEFAULT_API_URL: &str = "https://api.dev.pragma.build/node/v1/data/"; - #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct EthereumClientConfig { #[serde(default)] @@ -74,111 +73,6 @@ pub struct HttpProviderConfig { pub gas_price_poll_ms: Option, } -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(tag = "oracle_name", content = "config")] -pub enum OracleConfig { - Pragma(PragmaOracle), -} - -impl OracleConfig { - pub fn get_fetch_url(&self, base: String, quote: String) -> String { - match self { - OracleConfig::Pragma(pragma_oracle) => pragma_oracle.get_fetch_url(base, quote), - } - } - - pub fn get_api_key(&self) -> &String { - match self { - OracleConfig::Pragma(oracle) => &oracle.api_key, - } - } - - pub fn is_in_bounds(&self, price: u128) -> bool { - match self { - OracleConfig::Pragma(oracle) => oracle.price_bounds.low <= price && price <= oracle.price_bounds.high, - } - } -} - -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -pub struct PriceBounds { - pub low: u128, - pub high: u128, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct PragmaOracle { - #[serde(default = "default_api_url")] - pub api_url: String, - #[serde(default)] - pub api_key: String, - #[serde(default)] - pub aggregation_method: AggregationMethod, - #[serde(default)] - pub interval: Interval, - #[serde(default)] - pub price_bounds: PriceBounds, -} - -impl PragmaOracle { - fn get_fetch_url(&self, base: String, quote: String) -> String { - format!( - "{}{}/{}?interval={}&aggregation={}", - self.api_url, - base, - quote, - self.interval.as_str(), - self.aggregation_method.as_str() - ) - } -} - -#[derive(Default, Debug, Serialize, Deserialize, Clone)] -pub enum AggregationMethod { - #[serde(rename = "median")] - Median, - #[serde(rename = "mean")] - Mean, - #[serde(rename = "twap")] - #[default] - Twap, -} - -impl AggregationMethod { - pub fn as_str(&self) -> &str { - match self { - AggregationMethod::Median => "median", - AggregationMethod::Mean => "mean", - AggregationMethod::Twap => "twap", - } - } -} - -// Supported Aggregation Intervals -#[derive(Default, Debug, Serialize, Deserialize, Clone)] -pub enum Interval { - #[serde(rename = "1min")] - OneMinute, - #[serde(rename = "15min")] - FifteenMinutes, - #[serde(rename = "1h")] - OneHour, - #[serde(rename = "2h")] - #[default] - TwoHours, -} - -impl Interval { - pub fn as_str(&self) -> &str { - match self { - Interval::OneMinute => "1min", - Interval::FifteenMinutes => "15min", - Interval::OneHour => "1h", - Interval::TwoHours => "2h", - } - } -} - #[derive(Debug, Clone, Serialize, Deserialize)] pub struct LocalWalletConfig { #[serde(default = "default_chain_id")] @@ -191,10 +85,6 @@ fn default_rpc_endpoint() -> String { DEFAULT_RPC_ENDPOINT.into() } -fn default_api_url() -> String { - DEFAULT_API_URL.into() -} - fn default_chain_id() -> u64 { DEFAULT_CHAIN_ID } @@ -203,24 +93,6 @@ fn default_private_key() -> String { DEFAULT_PRIVATE_KEY.to_string() } -impl Default for PragmaOracle { - fn default() -> Self { - Self { - api_url: default_api_url(), - api_key: String::default(), - aggregation_method: AggregationMethod::Median, - interval: Interval::OneMinute, - price_bounds: Default::default(), - } - } -} - -impl Default for OracleConfig { - fn default() -> Self { - Self::Pragma(PragmaOracle::default()) - } -} - impl Default for HttpProviderConfig { fn default() -> Self { Self { rpc_endpoint: default_rpc_endpoint(), tx_poll_interval_ms: None, gas_price_poll_ms: None } diff --git a/crates/client/eth-client/src/lib.rs b/crates/client/eth-client/src/lib.rs index 2b1a25ad86..3711ea6cf0 100644 --- a/crates/client/eth-client/src/lib.rs +++ b/crates/client/eth-client/src/lib.rs @@ -9,6 +9,7 @@ pub mod config; pub mod error; +pub mod oracle; use std::time::Duration; diff --git a/crates/client/eth-client/src/oracle.rs b/crates/client/eth-client/src/oracle.rs new file mode 100644 index 0000000000..46915f23e0 --- /dev/null +++ b/crates/client/eth-client/src/oracle.rs @@ -0,0 +1,136 @@ +use serde::{Deserialize, Serialize}; + +pub const DEFAULT_API_URL: &str = "https://api.dev.pragma.build/node/v1/data/"; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "oracle_name", content = "config")] +pub enum OracleConfig { + Pragma(PragmaOracle), +} + +impl OracleConfig { + pub fn get_fetch_url(&self, base: String, quote: String) -> String { + match self { + OracleConfig::Pragma(pragma_oracle) => pragma_oracle.get_fetch_url(base, quote), + } + } + + pub fn get_api_key(&self) -> &String { + match self { + OracleConfig::Pragma(oracle) => &oracle.api_key, + } + } + + pub fn is_in_bounds(&self, price: u128) -> bool { + match self { + OracleConfig::Pragma(oracle) => oracle.price_bounds.low <= price && price <= oracle.price_bounds.high, + } + } +} + +impl Default for OracleConfig { + fn default() -> Self { + Self::Pragma(PragmaOracle::default()) + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct PragmaOracle { + #[serde(default = "default_oracle_api_url")] + pub api_url: String, + #[serde(default)] + pub api_key: String, + #[serde(default)] + pub aggregation_method: AggregationMethod, + #[serde(default)] + pub interval: Interval, + #[serde(default)] + pub price_bounds: PriceBounds, +} + +impl Default for PragmaOracle { + fn default() -> Self { + Self { + api_url: default_oracle_api_url(), + api_key: String::default(), + aggregation_method: AggregationMethod::Median, + interval: Interval::OneMinute, + price_bounds: Default::default(), + } + } +} + +impl PragmaOracle { + fn get_fetch_url(&self, base: String, quote: String) -> String { + format!( + "{}{}/{}?interval={}&aggregation={}", + self.api_url, + base, + quote, + self.interval.as_str(), + self.aggregation_method.as_str() + ) + } +} + +#[derive(Default, Debug, Serialize, Deserialize, Clone)] +pub enum AggregationMethod { + #[serde(rename = "median")] + Median, + #[serde(rename = "mean")] + Mean, + #[serde(rename = "twap")] + #[default] + Twap, +} + +impl AggregationMethod { + pub fn as_str(&self) -> &str { + match self { + AggregationMethod::Median => "median", + AggregationMethod::Mean => "mean", + AggregationMethod::Twap => "twap", + } + } +} + +// Supported Aggregation Intervals +#[derive(Default, Debug, Serialize, Deserialize, Clone)] +pub enum Interval { + #[serde(rename = "1min")] + OneMinute, + #[serde(rename = "15min")] + FifteenMinutes, + #[serde(rename = "1h")] + OneHour, + #[serde(rename = "2h")] + #[default] + TwoHours, +} + +impl Interval { + pub fn as_str(&self) -> &str { + match self { + Interval::OneMinute => "1min", + Interval::FifteenMinutes => "15min", + Interval::OneHour => "1h", + Interval::TwoHours => "2h", + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct PriceBounds { + pub low: u128, + pub high: u128, +} + +impl Default for PriceBounds { + fn default() -> Self { + Self { low: 0, high: u128::MAX } + } +} + +fn default_oracle_api_url() -> String { + DEFAULT_API_URL.into() +} diff --git a/crates/client/l1-gas-price/src/worker.rs b/crates/client/l1-gas-price/src/worker.rs index 115773e914..f03bd70fb9 100644 --- a/crates/client/l1-gas-price/src/worker.rs +++ b/crates/client/l1-gas-price/src/worker.rs @@ -6,7 +6,8 @@ use anyhow::{format_err, Result}; use ethers::types::U256; use ethers::utils::__serde_json::json; use futures::lock::Mutex; -use mc_eth_client::config::{EthereumClientConfig, OracleConfig}; +use mc_eth_client::config::EthereumClientConfig; +use mc_eth_client::oracle::OracleConfig; use mp_starknet_inherent::L1GasPrices; use serde::Deserialize; use tokio::time::sleep; @@ -16,7 +17,7 @@ use crate::types::{EthRpcResponse, FeeHistory}; const DEFAULT_GAS_PRICE_POLL_MS: u64 = 10_000; #[derive(Deserialize, Debug)] -struct ApiResponse { +struct OracleApiResponse { price: String, decimals: u32, } @@ -103,11 +104,11 @@ async fn update_gas_price( .send() .await?; - let res_json = response.json::().await; + let oracle_api_response = response.json::().await; let mut gas_price = gas_price.lock().await; - match res_json { + match oracle_api_response { Ok(api_response) => { log::trace!("Retrieved ETH/STRK price from Oracle"); let eth_strk_price = u128::from_str_radix(api_response.price.trim_start_matches("0x"), 16)?; From ad5345c7402906f1d99e1f0d106ce101c05464b0 Mon Sep 17 00:00:00 2001 From: mcaseaux Date: Thu, 20 Jun 2024 19:59:28 +0200 Subject: [PATCH 15/16] changed as_str to display impl --- crates/client/eth-client/src/oracle.rs | 29 ++++++++++++-------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/crates/client/eth-client/src/oracle.rs b/crates/client/eth-client/src/oracle.rs index f522d8ba10..50ca24b894 100644 --- a/crates/client/eth-client/src/oracle.rs +++ b/crates/client/eth-client/src/oracle.rs @@ -1,3 +1,5 @@ +use std::fmt; + use serde::{Deserialize, Serialize}; pub const DEFAULT_API_URL: &str = "https://api.dev.pragma.build/node/v1/data/"; @@ -62,14 +64,7 @@ impl Default for PragmaOracle { impl PragmaOracle { fn get_fetch_url(&self, base: String, quote: String) -> String { - format!( - "{}{}/{}?interval={}&aggregation={}", - self.api_url, - base, - quote, - self.interval.as_str(), - self.aggregation_method.as_str() - ) + format!("{}{}/{}?interval={}&aggregation={}", self.api_url, base, quote, self.interval, self.aggregation_method) } } @@ -85,13 +80,14 @@ pub enum AggregationMethod { Twap, } -impl AggregationMethod { - pub fn as_str(&self) -> &str { - match self { +impl fmt::Display for AggregationMethod { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let name = match self { AggregationMethod::Median => "median", AggregationMethod::Mean => "mean", AggregationMethod::Twap => "twap", - } + }; + write!(f, "{}", name) } } @@ -109,14 +105,15 @@ pub enum Interval { TwoHours, } -impl Interval { - pub fn as_str(&self) -> &str { - match self { +impl fmt::Display for Interval { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let name = match self { Interval::OneMinute => "1min", Interval::FifteenMinutes => "15min", Interval::OneHour => "1h", Interval::TwoHours => "2h", - } + }; + write!(f, "{}", name) } } From 5bd01a3e675a72fa4258489268fde441a26f06de Mon Sep 17 00:00:00 2001 From: mcaseaux Date: Thu, 20 Jun 2024 20:01:07 +0200 Subject: [PATCH 16/16] fix typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 069aa4b4a6..354a65c71b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -348,4 +348,4 @@ - dev : clean contracts and compiled files - fix: add from_address in calldata of l1 message - test: add starkgate related testcase -- feat: add pragam api to compute fees +- feat: add pragma api to compute fees