From 65a9618b266da2551b02334cc62f633cc5cefd8a Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Tue, 22 Oct 2024 11:03:48 +0100 Subject: [PATCH 1/3] chore: Clean up protosim Remove optimize and starknet_simulation Rename evm_simulation to evm --- don't change below this line --- ENG-3782 Took 5 minutes --- protosim_py/src/simulation_py.rs | 4 +- protosim_py/src/structs_py.rs | 8 +- src/{evm_simulation => evm}/Readme.md | 0 .../account_storage.rs | 2 +- src/{evm_simulation => evm}/database.rs | 0 src/{evm_simulation => evm}/mod.rs | 0 src/{evm_simulation => evm}/simulation.rs | 4 +- src/{evm_simulation => evm}/traces.rs | 0 src/{evm_simulation => evm}/tycho_client.rs | 6 +- src/{evm_simulation => evm}/tycho_db.rs | 6 +- src/{evm_simulation => evm}/tycho_models.rs | 0 src/lib.rs | 3 +- src/optimize/gss.rs | 431 ------- src/optimize/mod.rs | 2 - src/protocol/dodo/state.rs | 2 +- src/starknet_simulation/mod.rs | 22 - src/starknet_simulation/rpc_reader.rs | 242 ---- src/starknet_simulation/simulation.rs | 1107 ----------------- 18 files changed, 16 insertions(+), 1823 deletions(-) rename src/{evm_simulation => evm}/Readme.md (100%) rename src/{evm_simulation => evm}/account_storage.rs (99%) rename src/{evm_simulation => evm}/database.rs (100%) rename src/{evm_simulation => evm}/mod.rs (100%) rename src/{evm_simulation => evm}/simulation.rs (99%) rename src/{evm_simulation => evm}/traces.rs (100%) rename src/{evm_simulation => evm}/tycho_client.rs (98%) rename src/{evm_simulation => evm}/tycho_db.rs (99%) rename src/{evm_simulation => evm}/tycho_models.rs (100%) delete mode 100644 src/optimize/gss.rs delete mode 100644 src/optimize/mod.rs delete mode 100644 src/starknet_simulation/mod.rs delete mode 100644 src/starknet_simulation/rpc_reader.rs delete mode 100644 src/starknet_simulation/simulation.rs diff --git a/protosim_py/src/simulation_py.rs b/protosim_py/src/simulation_py.rs index 35f63bd6..220e7c61 100644 --- a/protosim_py/src/simulation_py.rs +++ b/protosim_py/src/simulation_py.rs @@ -9,7 +9,7 @@ use crate::structs_py::{ use pyo3::{prelude::*, types::PyType}; use std::{collections::HashMap, str::FromStr}; -use protosim::evm_simulation::{account_storage, database, simulation, tycho_db}; +use protosim::evm::{account_storage, database, simulation, tycho_db}; #[derive(Clone, Copy)] enum DatabaseType { @@ -201,7 +201,7 @@ impl SimulationEngine { updates: HashMap, block: BlockHeader, ) -> PyResult> { - let block = protosim::evm_simulation::database::BlockHeader::from(block); + let block = protosim::evm::database::BlockHeader::from(block); let mut rust_updates: HashMap = HashMap::new(); for (key, value) in updates { rust_updates.insert( diff --git a/protosim_py/src/structs_py.rs b/protosim_py/src/structs_py.rs index 60b24adb..6416d0e7 100644 --- a/protosim_py/src/structs_py.rs +++ b/protosim_py/src/structs_py.rs @@ -10,7 +10,7 @@ use tracing::info; use std::{collections::HashMap, str::FromStr, sync::Arc}; -use protosim::evm_simulation::{account_storage, database, simulation, tycho_db, tycho_models}; +use protosim::evm::{account_storage, database, simulation, tycho_db, tycho_models}; use std::fmt::Debug; /// Data needed to invoke a transaction simulation @@ -402,9 +402,9 @@ impl BlockHeader { } } -impl From for protosim::evm_simulation::database::BlockHeader { +impl From for protosim::evm::database::BlockHeader { fn from(py_header: BlockHeader) -> Self { - protosim::evm_simulation::database::BlockHeader { + protosim::evm::database::BlockHeader { number: py_header.number, hash: H256::from_str(&py_header.hash).unwrap(), timestamp: py_header.timestamp, @@ -530,7 +530,7 @@ impl TychoDB { .map(Into::into) .collect(); - let block = block.map(protosim::evm_simulation::database::BlockHeader::from); + let block = block.map(protosim::evm::database::BlockHeader::from); let runtime = tokio::runtime::Runtime::new().unwrap(); // Create a new Tokio runtime runtime.block_on(async { diff --git a/src/evm_simulation/Readme.md b/src/evm/Readme.md similarity index 100% rename from src/evm_simulation/Readme.md rename to src/evm/Readme.md diff --git a/src/evm_simulation/account_storage.rs b/src/evm/account_storage.rs similarity index 99% rename from src/evm_simulation/account_storage.rs rename to src/evm/account_storage.rs index 18e79082..06687fa4 100644 --- a/src/evm_simulation/account_storage.rs +++ b/src/evm/account_storage.rs @@ -232,7 +232,7 @@ impl AccountStorage { #[cfg(test)] mod tests { use super::StateUpdate; - use crate::evm_simulation::account_storage::{Account, AccountStorage}; + use crate::evm::account_storage::{Account, AccountStorage}; use revm::primitives::{AccountInfo, Address, KECCAK_EMPTY, U256 as rU256}; use std::{collections::HashMap, error::Error, str::FromStr}; diff --git a/src/evm_simulation/database.rs b/src/evm/database.rs similarity index 100% rename from src/evm_simulation/database.rs rename to src/evm/database.rs diff --git a/src/evm_simulation/mod.rs b/src/evm/mod.rs similarity index 100% rename from src/evm_simulation/mod.rs rename to src/evm/mod.rs diff --git a/src/evm_simulation/simulation.rs b/src/evm/simulation.rs similarity index 99% rename from src/evm_simulation/simulation.rs rename to src/evm/simulation.rs index 071e143c..4e7d0d4f 100644 --- a/src/evm_simulation/simulation.rs +++ b/src/evm/simulation.rs @@ -17,7 +17,7 @@ use revm_inspectors::tracing::{TracingInspector, TracingInspectorConfig}; use tokio::runtime::Runtime; use tracing::debug; -use crate::evm_simulation::database::OverriddenSimulationDB; +use crate::evm::database::OverriddenSimulationDB; use super::{ account_storage::StateUpdate, @@ -369,7 +369,7 @@ mod tests { OutOfGasError, Output, ResultAndState, SuccessReason, B256, }; - use crate::evm_simulation::database; + use crate::evm::database; use super::*; diff --git a/src/evm_simulation/traces.rs b/src/evm/traces.rs similarity index 100% rename from src/evm_simulation/traces.rs rename to src/evm/traces.rs diff --git a/src/evm_simulation/tycho_client.rs b/src/evm/tycho_client.rs similarity index 98% rename from src/evm_simulation/tycho_client.rs rename to src/evm/tycho_client.rs index 524c75a4..e9ec9dba 100644 --- a/src/evm_simulation/tycho_client.rs +++ b/src/evm/tycho_client.rs @@ -8,9 +8,7 @@ use uuid::Uuid; use super::tycho_models::{ BlockAccountChanges, Chain, Command, ExtractorIdentity, Response, WebSocketMessage, }; -use crate::evm_simulation::tycho_models::{ - StateRequestBody, StateRequestParameters, StateRequestResponse, -}; +use crate::evm::tycho_models::{StateRequestBody, StateRequestParameters, StateRequestResponse}; use async_trait::async_trait; use futures::SinkExt; use tokio::sync::mpsc::{self, Receiver}; @@ -258,7 +256,7 @@ impl TychoWsClient for TychoWsClientImpl { #[cfg(test)] mod tests { - use crate::evm_simulation::tycho_models::{AccountUpdate, Block, ChangeType}; + use crate::evm::tycho_models::{AccountUpdate, Block, ChangeType}; use chrono::NaiveDateTime; use super::*; diff --git a/src/evm_simulation/tycho_db.rs b/src/evm/tycho_db.rs similarity index 99% rename from src/evm_simulation/tycho_db.rs rename to src/evm/tycho_db.rs index 23b8b10d..cdaf1ff6 100644 --- a/src/evm_simulation/tycho_db.rs +++ b/src/evm/tycho_db.rs @@ -8,7 +8,7 @@ use revm::{ primitives::{AccountInfo, Address, Bytecode, Bytes, B256, U256 as rU256}, }; -use crate::evm_simulation::{ +use crate::evm::{ account_storage::{AccountStorage, StateUpdate}, database::BlockHeader, tycho_client::{TychoClientError, TychoHttpClient, AMBIENT_ACCOUNT_ADDRESS}, @@ -380,7 +380,7 @@ mod tests { use rstest::{fixture, rstest}; use std::{error::Error, str::FromStr}; - use crate::evm_simulation::{ + use crate::evm::{ tycho_client::TychoClientError, tycho_models::{ AccountUpdate, Block, Chain, ChangeType, ResponseAccount, StateRequestParameters, @@ -660,7 +660,7 @@ mod tests { /// Then run the test with: /// ```bash /// cargo test --package src --lib -- --ignored --exact --nocapture - /// evm_simulation::tycho_db::tests::test_tycho_db_connection + /// evm::tycho_db::tests::test_tycho_db_connection /// ``` #[ignore] #[rstest] diff --git a/src/evm_simulation/tycho_models.rs b/src/evm/tycho_models.rs similarity index 100% rename from src/evm_simulation/tycho_models.rs rename to src/evm/tycho_models.rs diff --git a/src/lib.rs b/src/lib.rs index d9538343..3b2da18b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,9 +18,8 @@ // Reexports pub use num_traits; -pub mod evm_simulation; +pub mod evm; pub mod models; -pub mod optimize; pub mod protocol; pub mod safe_math; pub mod serde_helpers; diff --git a/src/optimize/gss.rs b/src/optimize/gss.rs deleted file mode 100644 index c15c1686..00000000 --- a/src/optimize/gss.rs +++ /dev/null @@ -1,431 +0,0 @@ -//! Golden Section Search -use crate::{ - protocol::errors::TradeSimulationError, - safe_math::{ - safe_add_i256, safe_div_i256, safe_div_u512, safe_mul_i256, safe_mul_u512, safe_sub_i256, - }, -}; -use ethers::types::{Sign, I256, U256, U512}; -use std::mem::swap; - -const INVPHI: i64 = 2654435769; // (math.sqrt(5) - 1) / 2 * 2 ** 32 -const INVPHI2: i64 = 1640531526; // (3 - math.sqrt(5)) * 2 ** 32 -const DENOM: U512 = U512([4294967296, 0, 0, 0, 0, 0, 0, 0]); // 2 ** 32 - -/// Golden Section Search -/// -/// This function maximizes the function `f` using the Golden Section Search algorithm. -/// -/// ## Parameters -/// -/// - `f`: A function that takes a `I256` value as input and returns a `I256` value. The function to -/// be maximized. -/// - `min_bound`: The lower bound of the search interval, represented as a `U256` value. -/// - `max_bound`: The upper bound of the search interval, represented as a `U256` value. -/// - `tol`: The tolerance level, represented as a `I256` value. The search will stop when the -/// difference between the two brackets is less than this tolerance. -/// - `max_iter`: The maximum number of iterations to perform before stopping the search, -/// represented as a `u64` value. -/// - `honour_bounds`: A `bool` value indicating whether the algorithm should honour the bounds or -/// not. If true, the algorithm will not search for solutions outside of the `min_bound` and -/// `max_bound` values. -/// -/// ## Returns -/// -/// A tuple of `U256` values representing the left and right brackets of the maximum value of the -/// function. -pub fn golden_section_search I256>( - f: F, - mut min_bound: U256, - mut max_bound: U256, - tol: I256, - max_iter: u64, - honour_bounds: bool, -) -> Result<(U256, U256), TradeSimulationError> { - let invphi_i256 = I256::from(INVPHI); - let invphi2_i256 = I256::from(INVPHI2); - - if min_bound > max_bound { - swap(&mut min_bound, &mut max_bound); - } - - let mut min_bound = I256::checked_from_sign_and_abs(Sign::Positive, min_bound).unwrap(); - let mut max_bound = I256::checked_from_sign_and_abs(Sign::Positive, max_bound).unwrap(); - - let mut h = max_bound - min_bound; - if h <= tol { - return Ok((i256_to_u256(min_bound), i256_to_u256(max_bound))); - } - - let mut yc; - let mut xc; - - if honour_bounds { - xc = safe_add_i256(min_bound, mul_div(invphi2_i256, h, DENOM)?)?; - yc = f(xc); - } else { - let brackets = bracket(&f, min_bound, max_bound)?; - min_bound = brackets.0; - max_bound = brackets.1; - xc = brackets.2; - yc = brackets.3; - } - - let mut xd = safe_add_i256(min_bound, mul_div(invphi_i256, h, DENOM)?)?; - let mut yd = f(xd); - - for _ in 0..max_iter { - if yc > yd { - max_bound = xd; - xd = xc; - yd = yc; - h = mul_div(invphi_i256, h, DENOM)?; - xc = safe_add_i256(min_bound, mul_div(invphi2_i256, h, DENOM)?)?; - yc = f(xc); - } else { - min_bound = xc; - xc = xd; - yc = yd; - h = mul_div(invphi_i256, h, DENOM)?; - xd = safe_add_i256(min_bound, mul_div(invphi_i256, h, DENOM)?)?; - yd = f(xd); - } - } - - if yc < yd { - Ok((i256_to_u256(min_bound), i256_to_u256(xd))) - } else { - Ok((i256_to_u256(xc), i256_to_u256(max_bound))) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_gss() { - let func = |x| ((x - I256::from(2)) * (I256::from(-1) * x + I256::from(10))); - let min_bound = U256::from(0); - let max_bound = U256::from(10); - let tol = I256::from(0); - let max_iter = 100; - let honour_bounds = true; - - let res = golden_section_search(func, min_bound, max_bound, tol, max_iter, honour_bounds) - .unwrap(); - - assert!(res.0 >= U256::from(3) && res.0 <= U256::from(7)); - assert!(res.1 >= U256::from(3) && res.1 <= U256::from(7)); - assert!(res.0 <= res.1); - } - - #[test] - fn test_gss_multiple_minima() { - let tol = I256::from(1u128); - let max_iter = 500; - let honour_bounds = false; - - let func = |x: I256| { - ((x - I256::from(2)).pow(6) - (x - I256::from(2)).pow(4) - (x - I256::from(2)).pow(2)) + - I256::from(1) - }; - - let res = golden_section_search( - func, - U256::from(2u128), - U256::from(2u128), - tol, - max_iter, - honour_bounds, - ) - .unwrap(); - - assert!(res.0 >= U256::from(0) && res.0 <= U256::from(5)); - assert!(res.1 >= U256::from(0) && res.1 <= U256::from(5)); - assert!(res.0 <= res.1); - } - - #[test] - fn test_gss_large_interval() { - let f = |x: I256| I256::minus_one() * I256::pow(I256::from(50) - x, 2); - - let res = golden_section_search( - f, - U256::from(0), - U256::from(10000), - I256::from(1u128), - 10000, - true, - ) - .unwrap(); - - assert!(res.0 >= U256::from(45) && res.0 <= U256::from(55)); - assert!(res.1 >= U256::from(45) && res.1 <= U256::from(55)); - assert!(res.0 <= res.1) - } - - #[test] - fn test_gss_bracket() { - let func = |x| (x - I256::from(2)) * (I256::from(-1) * x + I256::from(10)); - let res = golden_section_search( - func, - U256::from(0u128), - U256::from(2u128), - I256::from(1u128), - 100, - false, - ) - .unwrap(); - assert!(res.0 >= U256::from(0) && res.0 <= U256::from(10)); - assert!(res.1 >= U256::from(0) && res.1 <= U256::from(10)); - } -} - -fn i256_to_u256(to_convert: I256) -> U256 { - if to_convert <= I256::zero() { - return U256::zero(); - } - - U256::from_dec_str(&to_convert.to_string()).unwrap() -} - -pub fn bracket I256>( - f: F, - mut xa: I256, - mut xb: I256, -) -> Result<(I256, I256, I256, I256), TradeSimulationError> { - let _maxiter = 50; - let _grow_limit = I256::from(110); - let _golden_ratio: I256 = I256::from(6949403065_i64); // golden ratio: (1.0+sqrt(5.0))/2.0 * 2 ** 32 - let _w_max = I256::pow(I256::from(2), 96); - - let mut ya = f(xa); - let mut yb = f(xb); - - if ya > yb { - swap(&mut xa, &mut xb); - swap(&mut ya, &mut yb) - } - - let mut xc = safe_add_i256(xb, mul_div(_golden_ratio, safe_sub_i256(xb, xa)?, DENOM)?)?; - let mut yc = f(xc); - let mut yw; - let mut iter = 0; - let mut w; - - while yb < yc { - let tmp1 = safe_mul_i256(safe_sub_i256(xb, xa)?, safe_sub_i256(yb, yc)?)?; - let tmp2 = safe_mul_i256(safe_sub_i256(xb, xc)?, safe_sub_i256(yb, ya)?)?; - let val = safe_sub_i256(tmp2, tmp1)?; - - if val.abs() <= I256::zero() { - w = safe_sub_i256( - safe_mul_i256(safe_sub_i256(xb, xc)?, tmp2)?, - safe_mul_i256(safe_sub_i256(xb, xa)?, tmp1)?, - )?; - w = safe_sub_i256(xb, w.saturating_mul(I256::from(5000)))?; - } else { - w = safe_sub_i256( - xb, - safe_div_i256( - safe_sub_i256( - safe_mul_i256(safe_sub_i256(xb, xc)?, tmp2)?, - safe_mul_i256(safe_sub_i256(xb, xa)?, tmp1)?, - )?, - safe_mul_i256(I256::from(2), val)?, - )?, - )?; - }; - - if w.abs() > _w_max { - let w_sign = w.sign(); - w = _w_max; - if w_sign == Sign::Negative { - w = I256::from(-1) * w - } - } - - let wlim = safe_add_i256(xb, safe_mul_i256(_grow_limit, safe_sub_i256(xc, xb)?)?)?; - - if iter > _maxiter { - panic!("Too many iterations!"); - } - - iter += 1; - if safe_mul_i256(safe_sub_i256(w, xc)?, safe_sub_i256(xb, w)?)? > I256::zero() { - yw = f(w); - if yw > yc { - let min_bound = xb; - let max_bound = w; - return Ok((max_bound, min_bound, xc, yc)); - } else if yw < yb { - let xc = w; - let yc = yw; - return Ok((xa, xb, xc, yc)); - } - w = safe_add_i256(xc, mul_div(_golden_ratio, safe_sub_i256(xc, xb)?, DENOM)?)?; - yw = f(w); - } else if safe_mul_i256(safe_sub_i256(w, wlim)?, safe_sub_i256(wlim, xc)?)? >= I256::zero() - { - w = wlim; - yw = f(w); - } else if safe_mul_i256(safe_sub_i256(w, wlim)?, safe_sub_i256(xc, w)?)? > I256::zero() { - yw = f(w); - if yw > yc { - xb = xc; - xc = w; - w = safe_add_i256(xc, mul_div(_golden_ratio, xc - xb, DENOM)?)?; - yb = yc; - yc = yw; - yw = f(w); - } - } else { - w = safe_add_i256(xc, mul_div(_golden_ratio, xc - xb, DENOM)?)?; - yw = f(w); - } - xa = xb; - xb = xc; - xc = w; - ya = yb; - yb = yc; - yc = yw; - } - - Ok((xa, xb, xc, yc)) -} - -#[cfg(test)] -mod bracket_tests { - use super::*; - - #[test] - fn test_bracket() { - let func = |x| (x - I256::from(2)) * (I256::from(-1) * x + I256::from(10)); - let min_bound = I256::from(2); - let max_bound = I256::from(5); - let res = bracket(func, min_bound, max_bound).unwrap(); - - assert!(res.0 < res.1 && res.1 < res.2); - // xa - assert_eq!(res.0, I256::from(2)); - // xb - assert_eq!(res.1, I256::from(5)); - // xc - assert_eq!(res.2, I256::from(9)); - // yc - assert_eq!(res.3, I256::from(7)); - } - - #[test] - fn test_bracket_negative_bound() { - let func = |x| (x - I256::from(2)) * (I256::from(-1) * x + I256::from(10)); - let min_bound = I256::from(-10); - let max_bound = I256::from(-5); - let res = bracket(func, min_bound, max_bound).unwrap(); - - assert!(res.0 < res.1 && res.1 < res.2); - // xa - assert_eq!(res.0, I256::from(3)); - // xb - assert_eq!(res.1, I256::from(6)); - // xc - assert_eq!(res.2, I256::from(10)); - // yc - assert_eq!(res.3, I256::from(0)); - } - - #[test] - fn test_bracket_big_distance() { - let func = |x| { - I256::minus_one() * ((I256::pow(I256::from(100) - x, 2)) / I256::from(100)) + - I256::from(100) - }; - - let min_bound = I256::from(0); - let max_bound = I256::from(-30); - let res = bracket(func, min_bound, max_bound).unwrap(); - - assert!(res.0 < res.1 && res.1 < res.2); - // xa - assert_eq!(res.0, I256::from(48)); - // xb - assert_eq!(res.1, I256::from(100)); - // xc - assert_eq!(res.2, I256::from(184)); - // yc - assert_eq!(res.3, I256::from(30)); - } - - #[test] - #[should_panic] - fn test_bracket_max_iteration() { - let func = |x: I256| x; - let min_bound = I256::from(0); - let max_bound = I256::from(50); - bracket(func, min_bound, max_bound).unwrap(); - } -} - -pub fn mul_div(a: I256, b: I256, denom: U512) -> Result { - let a_sign = a.sign(); - let b_sign = b.sign(); - - let a_u512 = if a_sign == Sign::Negative { - U512::from_dec_str(&(I256::from(-1) * a).to_string()).unwrap() - } else { - U512::from_dec_str(&a.to_string()).unwrap() - }; - - let b_u512 = if b_sign == Sign::Negative { - U512::from_dec_str(&(I256::from(-1) * b).to_string()).unwrap() - } else { - U512::from_dec_str(&b.to_string()).unwrap() - }; - - let product = safe_mul_u512(a_u512, b_u512)?; - - let result: U256 = safe_div_u512(product, denom)? - .try_into() - .expect("Integer Overflow when casting from U512 to U256"); - let mut new_sign = Sign::Positive; - if a_sign != b_sign { - new_sign = Sign::Negative; - } - Ok(I256::checked_from_sign_and_abs(new_sign, result) - .expect("Integer Overflow when casting from U256 to I256")) -} - -#[cfg(test)] -mod mul_div_tests { - use super::*; - - #[test] - fn test_mul_div() { - let a = I256::from(2147483648_i64); // 0.5 * 2 **32 - let b = I256::from(50); - let res = mul_div(a, b, DENOM).unwrap(); - - assert!(res == I256::from(25)); - assert!(res.sign() == Sign::Positive); - } - #[test] - fn test_mul_div_negativ_mul() { - let a = I256::from(-2147483648_i64); // 0.5 * 2 **32 - let b = I256::from(50); - let res = mul_div(a, b, DENOM).unwrap(); - - assert!(res == I256::from(-25)); - assert!(res.sign() == Sign::Negative); - } - - #[test] - fn test_mul_div_both_negativ_mul() { - let a = I256::from(-2147483648_i64); // 0.5 * 2 **32 - let b = I256::from(-50); - let res = mul_div(a, b, DENOM).unwrap(); - - assert!(res == I256::from(25)); - assert!(res.sign() == Sign::Positive); - } -} diff --git a/src/optimize/mod.rs b/src/optimize/mod.rs deleted file mode 100644 index 044d4f64..00000000 --- a/src/optimize/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -//! Optimization methods for the Solidity type system -pub mod gss; diff --git a/src/protocol/dodo/state.rs b/src/protocol/dodo/state.rs index b7aecf36..7cf588aa 100644 --- a/src/protocol/dodo/state.rs +++ b/src/protocol/dodo/state.rs @@ -14,7 +14,7 @@ use revm::{ use tycho_core::dto::ProtocolStateDelta; use crate::{ - evm_simulation::simulation::{SimulationEngine, SimulationParameters}, + evm::simulation::{SimulationEngine, SimulationParameters}, protocol::{ errors::TransitionError, events::{EVMLogMeta, LogIndex}, diff --git a/src/starknet_simulation/mod.rs b/src/starknet_simulation/mod.rs deleted file mode 100644 index d6042907..00000000 --- a/src/starknet_simulation/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -use cairo_vm::felt::{Felt252, ParseFeltError}; -use num_traits::Num; -use starknet_in_rust::utils::{Address, ClassHash}; - -pub mod rpc_reader; -pub mod simulation; - -pub fn felt_str(val: &str) -> Result { - let base = if val.starts_with("0x") { 16 } else { 10 }; - let stripped_val = val.trim_start_matches("0x"); - - Felt252::from_str_radix(stripped_val, base) -} - -pub fn address_str(val: &str) -> Result { - felt_str(val).map(Address) -} - -pub fn class_hash_str(val: &str) -> Result { - let felt = felt_str(val)?; - Ok(felt.to_be_bytes()) -} diff --git a/src/starknet_simulation/rpc_reader.rs b/src/starknet_simulation/rpc_reader.rs deleted file mode 100644 index 78f170e3..00000000 --- a/src/starknet_simulation/rpc_reader.rs +++ /dev/null @@ -1,242 +0,0 @@ -use cairo_vm::felt::Felt252; -use rpc_state_reader::rpc_state::{BlockValue, RpcState}; -use starknet_api::{ - core::{ClassHash as SNClassHash, ContractAddress, PatriciaKey}, - hash::StarkHash, - state::StorageKey, -}; -use starknet_in_rust::{ - core::errors::state_errors::StateError, - services::api::contract_classes::compiled_class::CompiledClass, - state::{state_api::StateReader, state_cache::StorageEntry}, - utils::{Address, ClassHash, CompiledClassHash}, -}; - -trait ToContractAddress { - fn to_contract_address(&self) -> ContractAddress; -} - -impl ToContractAddress for Address { - fn to_contract_address(&self) -> ContractAddress { - ContractAddress( - PatriciaKey::try_from(StarkHash::new(self.0.to_be_bytes()).unwrap()).unwrap(), - ) - } -} - -#[derive(Debug, Clone)] -pub struct RpcStateReader(pub RpcState); - -impl RpcStateReader { - pub fn new(state: RpcState) -> Self { - Self(state) - } - - pub fn with_updated_block(&self, new_block: BlockValue) -> Self { - let mut cloned_state = self.0.clone(); - cloned_state.block = new_block; - RpcStateReader(cloned_state) - } - - pub fn block(&self) -> &BlockValue { - &self.0.block - } -} - -impl StateReader for RpcStateReader { - fn get_contract_class(&self, class_hash: &ClassHash) -> Result { - let hash = match StarkHash::new(*class_hash) { - Ok(val) => SNClassHash(val), - Err(err) => return Err(StateError::CustomError(err.to_string())), - }; - Ok(CompiledClass::from(self.0.get_contract_class(&hash))) - } - - fn get_class_hash_at(&self, contract_address: &Address) -> Result { - let address = contract_address.to_contract_address(); - let mut bytes = [0u8; 32]; - bytes.copy_from_slice( - self.0 - .get_class_hash_at(&address) - .0 - .bytes(), - ); - Ok(bytes) - } - - fn get_nonce_at(&self, contract_address: &Address) -> Result { - let address = contract_address.to_contract_address(); - let nonce = self.0.get_nonce_at(&address); - Ok(Felt252::from_bytes_be(nonce.bytes())) - } - - fn get_storage_at(&self, storage_entry: &StorageEntry) -> Result { - let (contract_address, key) = storage_entry; - let address = contract_address.to_contract_address(); - let key_hash = - StarkHash::new(*key).map_err(|err| StateError::CustomError(err.to_string()))?; - let key = match PatriciaKey::try_from(key_hash) { - Ok(val) => StorageKey(val), - Err(err) => return Err(StateError::CustomError(err.to_string())), - }; - let value = self.0.get_storage_at(&address, &key); - Ok(Felt252::from_bytes_be(value.bytes())) - } - - fn get_compiled_class_hash( - &self, - class_hash: &ClassHash, - ) -> Result { - Ok(*class_hash) - } -} - -#[cfg(test)] -pub(crate) mod tests { - use dotenv::dotenv; - use std::env; - - use rpc_state_reader::rpc_state::{RpcBlockInfo, RpcChain, RpcState}; - use starknet_api::{block::BlockNumber, core::ChainId}; - - use super::*; - - pub fn setup_reader(block_number: u64) -> RpcStateReader { - let rpc_url = env::var("ETH_RPC_URL").unwrap_or_else(|_| { - dotenv().expect("Missing .env file"); - env::var("ETH_RPC_URL").expect("Missing ETH_RPC_URL in .env file") - }); - let rpc_chain_id: ChainId = rpc_chain.into(); - let feeder_url = format!("https://{}.starknet.io/feeder_gateway", rpc_chain_id); - RpcStateReader::new(RpcState::new( - rpc_chain, - BlockNumber(block_number).into(), - &rpc_url, - &feeder_url, - )) - } - - #[test] - #[cfg_attr(not(feature = "network_tests"), ignore)] - fn test_get_class_hash_at() { - let reader = setup_reader(333333); - - // Jedi Swap ETH/USDC pool address - let address_bytes = - hex::decode("04d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a") - .unwrap(); - let contract_address: Address = Address(Felt252::from_bytes_be(&address_bytes)); - - // expected class hash - let hash_bytes = - hex::decode("07b5cd6a6949cc1730f89d795f2442f6ab431ea6c9a5be00685d50f97433c5eb") - .unwrap(); - let expected_result: ClassHash = hash_bytes - .as_slice() - .try_into() - .unwrap(); - - let result = reader - .get_class_hash_at(&contract_address) - .unwrap(); - - assert_eq!(result, expected_result); - } - - #[test] - #[cfg_attr(not(feature = "network_tests"), ignore)] - fn test_get_contract_class() { - let reader = setup_reader(333333); - - // Jedi Swap ETH/USDC pool class hash - let class_hash: ClassHash = - hex::decode("07b5cd6a6949cc1730f89d795f2442f6ab431ea6c9a5be00685d50f97433c5eb") - .unwrap() - .as_slice() - .try_into() - .unwrap(); - - let result = reader.get_contract_class(&class_hash); - - // the CompiledClass object is huge, so we just check it is returned and skip the details - // here - assert!(result.is_ok()) - } - - #[test] - #[cfg_attr(not(feature = "network_tests"), ignore)] - fn test_get_nonce_at() { - let reader = setup_reader(333333); - - // a test wallet address - let address_bytes = - hex::decode("03e9dB89D1c040968Cd82c07356E8e93B51825ab3CdAbA3d6dBA7a856729ef71") - .unwrap(); - let contract_address: Address = Address(Felt252::from_bytes_be(&address_bytes)); - - let result = reader - .get_nonce_at(&contract_address) - .unwrap(); - - assert_eq!(result.to_string(), "22") - } - - #[test] - #[cfg_attr(not(feature = "network_tests"), ignore)] - fn test_get_storage_at() { - let reader = setup_reader(333333); - - let address_bytes = - hex::decode("04d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a") - .unwrap(); - let address: Address = Address(Felt252::from_bytes_be(&address_bytes)); - let entry = [0; 32]; - let storage_entry: StorageEntry = (address, entry); - - let result = reader - .get_storage_at(&storage_entry) - .unwrap(); - - let zero_as_bytes: ClassHash = [0; 32]; - assert_eq!(result, Felt252::from_bytes_be(&zero_as_bytes)) - } - - #[test] - #[cfg_attr(not(feature = "network_tests"), ignore)] - fn test_get_compiled_class_hash() { - let reader = setup_reader(333333); - - // Jedi Swap ETH/USDC pool class hash - let class_hash: &ClassHash = &[ - 7, 181, 205, 106, 105, 73, 204, 23, 48, 248, 157, 121, 95, 36, 66, 246, 171, 67, 30, - 166, 201, 165, 190, 0, 104, 93, 80, 249, 116, 51, 197, 235, - ]; - - //expected compiled class hash - let expected_hash: CompiledClassHash = [ - 7, 181, 205, 106, 105, 73, 204, 23, 48, 248, 157, 121, 95, 36, 66, 246, 171, 67, 30, - 166, 201, 165, 190, 0, 104, 93, 80, 249, 116, 51, 197, 235, - ]; - - let result = reader - .get_compiled_class_hash(class_hash) - .unwrap(); - - assert_eq!(result, expected_hash) - } - - #[test] - #[cfg_attr(not(feature = "network_tests"), ignore)] - fn test_with_updated_block() { - let reader = setup_reader(333333); - let RpcBlockInfo { block_number: initial_block_number, .. } = reader.0.get_block_info(); - let new_block = BlockNumber(333334).into(); - - let updated_reader = reader.with_updated_block(new_block); - let RpcBlockInfo { block_number: updated_block_number, .. } = - updated_reader.0.get_block_info(); - assert_eq!(initial_block_number, BlockNumber(333333)); - assert_eq!(updated_block_number, BlockNumber(333334)); - assert_ne!(initial_block_number, updated_block_number); - } -} diff --git a/src/starknet_simulation/simulation.rs b/src/starknet_simulation/simulation.rs deleted file mode 100644 index 2d27d2e1..00000000 --- a/src/starknet_simulation/simulation.rs +++ /dev/null @@ -1,1107 +0,0 @@ -use rpc_state_reader::rpc_state::BlockValue; -use starknet_api::block::BlockNumber; -use std::{collections::HashMap, path::Path, sync::Arc}; - -use cairo_vm::felt::Felt252; -use starknet_in_rust::{ - core::contract_address::{compute_casm_class_hash, compute_deprecated_class_hash}, - definitions::block_context::BlockContext, - execution::{ - execution_entry_point::{ExecutionEntryPoint, ExecutionResult}, - TransactionExecutionContext, - }, - services::api::contract_classes::{ - compiled_class::CompiledClass, deprecated_contract_class::ContractClass, - }, - state::{ - cached_state::CachedState, - state_api::{State, StateReader}, - state_cache::{StateCache, StorageEntry}, - ExecutionResourcesManager, - }, - utils::{calculate_sn_keccak, felt_to_hash, Address, ClassHash, CompiledClassHash}, - CasmContractClass, EntryPointType, -}; -use thiserror::Error; -use tracing::{debug, info}; - -use super::rpc_reader::RpcStateReader; - -#[derive(Error, Debug, PartialEq)] -pub enum SimulationError { - #[error("Failed to initialise contracts: {0}")] - InitError(String), - #[error("ContractState is already initialized: {0}")] - AlreadyInitialized(String), - #[error("Override Starknet state failed: {0}")] - OverrideError(String), - /// Simulation didn't succeed; likely not related to network, so retrying won't help - #[error("Simulated transaction failed: {0}")] - TransactionError(String), - #[error("Failed to decode result: {0}")] - ResultError(String), - /// Error reading state - #[error("Accessing contract state failed: {0}")] - StateError(String), -} - -pub type StorageHash = [u8; 32]; -pub type Overrides = HashMap; - -#[derive(Debug, Clone)] -pub struct SimulationParameters { - /// Address of the sending account - pub caller: Address, - /// Address of the receiving account/contract - pub to: Address, - /// Calldata - pub data: Vec, - /// The contract function/entry point to call e.g. "transfer" - pub entry_point: String, - /// Starknet state overrides. - /// Will be merged with the existing state. Will take effect only for current simulation. - /// Must be given as a contract address to its variable override map. - pub overrides: Option>, - /// Limit of gas to be used by the transaction - pub gas_limit: Option, - /// The block number to be used by the transaction. This is independent of the states block. - pub block_number: u64, -} - -impl SimulationParameters { - pub fn new( - caller: Address, - to: Address, - data: Vec, - entry_point: String, - overrides: Option>, - gas_limit: Option, - block_number: u64, - ) -> Self { - Self { caller, to, data, entry_point, overrides, gas_limit, block_number } - } -} - -#[derive(Debug, Clone, Default, PartialEq)] -pub struct SimulationResult { - /// Output of transaction execution - pub result: Vec, - /// State changes caused by the transaction - pub state_updates: HashMap, - /// Gas used by the transaction (already reduced by the refunded gas) - pub gas_used: u128, -} - -impl SimulationResult { - pub fn new( - result: Vec, - state_updates: HashMap, - gas_used: u128, - ) -> Self { - Self { result, state_updates, gas_used } - } -} - -/** - * Loads a Starknet contract from a given file path and returns it as a `CompiledClass` enum. - * - * # Arguments - * - * * `path: impl AsRef` - A path to the contract file. - * - * # Returns - * - * * `Ok(CompiledClass)` - The loaded contract as a `CompiledClass` enum. - * * `Err(Box)` - An error indicating the reason for the failure. - * - * # Contract Formats - * - * Starknet contracts can be represented in two main formats: `.casm` and `.json`. - * You can read more about these formats in the [Starknet documentation](https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/cairo-and-sierra/). - * - * ## .json Format (Cairo 0) - * - * * This format is older and represents Cairo 0 contracts. It is in JSON format, but sometimes - * for clarity it is given the `.sierra` extension. - * - * ## .casm Format (Cairo 1 / Cairo 2) - * - * * This format is newer and is used for Cairo 1 and Cairo 2 contracts. - * - * If the file extension is neither `.casm` nor `.json`, the function will return an `Err` - * indicating an unsupported file type. - */ -fn load_compiled_class_from_path( - path: impl AsRef, -) -> Result> { - let contents = std::fs::read_to_string(&path)?; - - match path - .as_ref() - .extension() - .and_then(std::ffi::OsStr::to_str) - { - Some("casm") => { - // Parse and load .casm file - let casm_contract_class: CasmContractClass = serde_json::from_str(&contents)?; - Ok(CompiledClass::Casm(Arc::new(casm_contract_class))) - } - Some("json") => { - // Deserialize the .json file - let contract_class: ContractClass = ContractClass::from_path(&path)?; - Ok(CompiledClass::Deprecated(Arc::new(contract_class))) - } - _ => Err(Box::new(std::io::Error::new( - std::io::ErrorKind::InvalidData, - "Unsupported file type", - ))), - } -} - -/// Computes the class hash of a given contract. -/// -/// # Arguments -/// -/// * `compiled_class: &CompiledClass` - The contract to compute the class hash of. -/// -/// # Returns -/// -/// * `Result>` - The computed class hash. -fn compute_class_hash( - compiled_class: &CompiledClass, -) -> Result> { - match compiled_class { - CompiledClass::Casm(casm_contract_class) => { - let class_hash = compute_casm_class_hash(casm_contract_class)?; - Ok(class_hash) - } - CompiledClass::Deprecated(contract_class) => { - let class_hash = compute_deprecated_class_hash(contract_class)?; - Ok(class_hash) - } - } -} - -/// A struct with metadata about a contract to be initialized. -/// These overrides are permanent and will not be reset on a new block. -/// -/// # Fields -/// -/// * `contract_address: Address` - The address of the contract. -/// * `class_hash: ClassHash` - The class hash of the contract (can differ from that of the contract -/// onchain if you wish to mock the contract) -/// * `path: Option` - The path to the contract file. WARNING: if `None`, the contract will -/// be fetched from the state reader, adding rpc overhead. This should be avoided if possible! -#[derive(Debug, Clone)] -pub struct ContractOverride { - pub contract_address: Address, - pub class_hash: ClassHash, - pub path: Option, -} - -impl ContractOverride { - pub fn new(contract_address: Address, class_hash: ClassHash, path: Option) -> Self { - Self { contract_address, class_hash, path } - } -} - -/// Simulation engine for Starknet transactions. -/// -/// Warning: Given that the used libraries are in development, -/// this code is also considered to not be very stable and production ready. -/// -/// One of the issues in current state is that the trait [StateReader] does not operate in a context -/// of a given block and the simulation engine expects the data to be correct for the given block. -/// This is unforunately not enforcable by the trait and thus the simulation `simulate()` function -/// is implemented over a concrete type (more info on [SimulationEngine]). -/// -/// # Fields -/// -/// * `state: CachedState` - The state of the simulation engine. -/// * `contract_overrides: Vec` - A permanent list of contract overrides persisted -/// across simulations, does not reset on a new block. -#[derive(Debug)] -#[allow(dead_code)] -pub struct SimulationEngine { - state: CachedState, - contract_overrides: Vec, -} - -#[allow(unused_variables)] -#[allow(dead_code)] -impl SimulationEngine { - pub fn new( - rpc_state_reader: Arc, - contract_overrides: Option>, - ) -> Result { - // Prepare initial values - let mut address_to_class_hash: HashMap = HashMap::new(); - let mut class_hash_to_compiled_class: HashMap = HashMap::new(); - let mut address_to_nonce: HashMap = HashMap::new(); - let storage_updates: HashMap = HashMap::new(); - - let mut class_hash_to_compiled_class_hash: HashMap = - HashMap::new(); - - // Load contracts - for input_contract in contract_overrides - .clone() - .unwrap_or_default() - .iter() - { - let class_hash = input_contract.class_hash; - let compiled_class_hash; - let compiled_class; - if let Some(path) = input_contract.path.clone() { - // Load contract from path - compiled_class = load_compiled_class_from_path(&path).map_err(|e| { - SimulationError::InitError(format!( - "Failed to load contract from path: {:?} with error: {:?}", - path, e - )) - })?; - // Compute compiled class hash - compiled_class_hash = - felt_to_hash(&compute_class_hash(&compiled_class).map_err(|e| { - SimulationError::InitError(format!( - "Failed to compute class hash for contract: {:?} with error: {:?}", - path, e - )) - })?); - } else { - // Load contract from rpc - compiled_class = rpc_state_reader - .get_contract_class(&class_hash) - .map_err(|err| { - SimulationError::InitError(format!( - "Could not fetch compiled class: {}", - err - )) - })?; - compiled_class_hash = rpc_state_reader - .get_compiled_class_hash(&class_hash) - .map_err(|err| { - SimulationError::InitError(format!( - "Could not fetch compiled class hash: {}", - err - )) - })?; - } - // Update caches - address_to_class_hash.insert(input_contract.contract_address.clone(), class_hash); - class_hash_to_compiled_class.insert(compiled_class_hash, compiled_class.clone()); - address_to_nonce.insert(input_contract.contract_address.clone(), Felt252::from(0u8)); - - class_hash_to_compiled_class_hash.insert(class_hash, compiled_class_hash); - } - - info!( - "Initialising SimulationEngine with {} contracts", - class_hash_to_compiled_class_hash.len() - ); - - // Set StateCache initial values - let cache: StateCache = StateCache::new( - address_to_class_hash, - class_hash_to_compiled_class.clone(), - address_to_nonce, - storage_updates, - HashMap::new(), - HashMap::new(), - HashMap::new(), - HashMap::new(), - class_hash_to_compiled_class_hash, - ); - - // Initialize CachedState contract classes - let state: CachedState = - CachedState::new_for_testing(rpc_state_reader, cache, class_hash_to_compiled_class); - - Ok(Self { state, contract_overrides: contract_overrides.unwrap_or_default() }) - } - - fn set_state(&mut self, state: HashMap) { - for (address, slot_update) in state { - for (slot, value) in slot_update { - let storage_entry = (address.clone(), slot); - self.state - .set_storage_at(&storage_entry, value); - } - } - } - - /// Interpret the result of a simulated execution. - /// - /// Transforms the raw outcome of a simulated execution into a `SimulationResult`. - /// - /// # Arguments - /// - /// * `result` - An instance of the `ExecutionResult` struct, containing the result data from a - /// simulated execution. - /// * `state_cache` - A `StateCache` giving the state's cache after simulation. - /// - /// # Return Value - /// - /// On successful simulation, this function returns `SimulationResult` containing the return - /// data, state updates, and gas consumed. If an error occurs during the simulation, it - /// returns a `SimulationError`. - /// - /// # Errors - /// - /// This function will return an error in the following situations: - /// - /// * If the execution reverts with an error (there exists a `revert_error` in the - /// `ExecutionResult`) - /// * If the `call_info` field of the `ExecutionResult` is empty (None) - /// * If the simulated execution fails (as indicated by the `failure_flag` in `call_info`) - fn interpret_result( - &self, - result: ExecutionResult, - ) -> Result { - // Check if revertError is not None - if let Some(revert_error) = result.revert_error { - return Err(SimulationError::TransactionError(format!( - "Execution reverted with error: {}", - revert_error - ))); - } - - // Extract call info - let call_info = result - .call_info - .ok_or(SimulationError::ResultError("Call info is empty".to_owned()))?; - // Check if call failed - if call_info.failure_flag { - return Err(SimulationError::ResultError("Execution failed".to_owned())); - } - let gas_used = call_info.gas_consumed; - let result = call_info.retdata.clone(); - - debug!("Simulation successful: {:#?} {:#?}", result, gas_used); - - // Collect state changes - let all_writes = self.state.cache().storage_writes(); - let simultation_write_keys = call_info.get_visited_storage_entries(); - let state_updates: HashMap> = all_writes - .iter() - .filter(|(key, _)| simultation_write_keys.contains(key)) // filter for those applied during simulation - .map(|((addr, hash), value)| (addr.clone(), (*hash, value.clone()))) // map to our Override struct format - .fold(HashMap::new(), |mut acc, (addr, (hash, value))| { - acc.entry(addr) - .or_default() - .insert(hash, value); - acc - }); - - Ok(SimulationResult { result, state_updates, gas_used }) - } - - /// Clear the cache of the simulation engine. - /// - /// This is useful when the state of the RPC reader has changed and the cache is no longer - /// valid. For example if the StateReader was set to a concrete block and a new block was - /// added to the chain. - /// - /// Note: This function does not clean up the contract cache. This is not necessary as it - /// contains immutable contract code. - pub fn clear_cache(&mut self, rpc_state_reader: Arc) { - // We keep contracts code in the cache. - let contract_cache: HashMap = - self.state.contract_classes().clone(); - // We initiate the class_hash_initial_values from permanent contract overrides - // Also we persist compiled_class_hash_initial_values because they can't change. - let cache = StateCache::new( - self.contract_overrides - .iter() - .map(|contract_override| { - ( - contract_override - .contract_address - .clone(), - contract_override.class_hash, - ) - }) - .collect(), - self.state - .cache_mut() - .compiled_class_hash_initial_values_mut() - .clone(), - HashMap::new(), - HashMap::new(), - HashMap::new(), - HashMap::new(), - HashMap::new(), - HashMap::new(), - self.state - .cache_mut() - .class_hash_to_compiled_class_hash_mut() - .clone(), - ); - self.state = CachedState::new_for_testing(rpc_state_reader, cache, contract_cache); - } - - /// Clears storage and nonce writes from the cache of the simulation engine. - /// - /// This should be called after every simulation to reset the contract writes applied during - /// simulation. This will not reset the entirety of the contract's cache, so all data retrieved - /// from the rpc persists. - pub fn clear_cache_writes(&mut self) { - let cache = self.state.cache_mut(); - cache.storage_writes_mut().clear(); - cache.nonce_writes_mut().clear(); - } -} - -/// The rest of the functions are implemented over the concrete [RpcStateReader], -/// because we need to have info about the block the StateReader is reading, which means what block -/// the data in the CachedState is valid for. -impl SimulationEngine { - /// Clear the cache and create a new RpcStateReader with the given block if and only if the - /// given block is different from the block in the RpcStateReader. - fn set_block_and_reset_cache(&mut self, new_block: BlockValue) { - if self.state.state_reader.block() != &new_block { - let new_state_reader = self - .state - .state_reader - .with_updated_block(new_block); - self.clear_cache(new_state_reader.into()); - } - } - - /// Simulate a transaction - /// - /// Simulates a V1 Invoke transaction [https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/transactions/#invoke_v1]. - /// This may be either an external call i.e. a multicall to a smart contract wallet or an - /// internal call between smart contracts. State's block will be modified to be the last - /// block before the simulation's block. - pub fn simulate( - &mut self, - params: &SimulationParameters, - ) -> Result { - // Reset cache if the internal block is different from the block in params - let block_value = BlockValue::Number(BlockNumber(params.block_number)); - self.set_block_and_reset_cache(block_value); - - // Apply overrides - if let Some(overrides) = ¶ms.overrides { - for (address, storage_update) in overrides { - for (slot, value) in storage_update { - let storage_entry = ((*address).clone(), *slot); - self.state - .set_storage_at(&storage_entry, (*value).clone()); - } - } - } - - // Create the simulated call - let entry_point = params.entry_point.as_bytes(); - let entry_point_selector = Felt252::from_bytes_be(&calculate_sn_keccak(entry_point)); - - let call = ExecutionEntryPoint::new( - params.to.clone(), - params.data.clone(), - entry_point_selector, - params.caller.clone(), - EntryPointType::External, - None, - None, - params.gas_limit.unwrap_or(u128::MAX), - ); - - debug!("Starting simulation with tx parameters: {:#?} {:#?}", call, block_value); - - // Set up the call context - let block_context = BlockContext::default(); - let mut resources_manager = ExecutionResourcesManager::default(); - let mut tx_execution_context = TransactionExecutionContext::create_for_testing( - params.caller.clone(), - u128::MAX, - Default::default(), - block_context.invoke_tx_max_n_steps(), - 1.into(), // Set this to 0 to simulate a V0 type invoke transaction - ); - - // Execute the simulated call - let execution_result = call - .execute( - &mut self.state, - &block_context, - &mut resources_manager, - &mut tx_execution_context, - false, - block_context.invoke_tx_max_n_steps(), - ) - .map_err(|err| SimulationError::TransactionError(err.to_string()))?; - - // Interpret and return the results - let simulation_result = self.interpret_result(execution_result); - - // Clear simulation writes from cache - self.clear_cache_writes(); - - simulation_result - } -} - -#[cfg(test)] -pub mod tests { - use std::{collections::HashSet, env}; - - use crate::starknet_simulation::rpc_reader::tests::setup_reader; - - use super::*; - use rpc_state_reader::rpc_state::RpcChain; - use rstest::rstest; - use starknet_in_rust::{ - core::errors::state_errors::StateError, execution::CallInfo, - state::cached_state::ContractClassCache, - }; - - pub fn felt_str(val: &str) -> Felt252 { - let base = if val.starts_with("0x") { 16_u32 } else { 10_u32 }; - let stripped_val = val.strip_prefix("0x").unwrap_or(val); - - Felt252::parse_bytes(stripped_val.as_bytes(), base).expect("Failed to parse input") - } - - pub fn address_str(val: &str) -> Address { - Address(felt_str(val)) - } - - pub fn class_hash_str(val: &str) -> ClassHash { - felt_str(val).to_be_bytes() - } - - #[test] - fn test_address_str_with_prefix() { - let input = "3658190653781265738165783961758321"; - - let expected_felt = Felt252::from(3658190653781265738165783961758321u128); - let expected = Address(expected_felt); - let result = address_str(input); - - assert_eq!(result, expected); - } - - fn setup_engine( - block_number: u64, - contract_overrides: Option>, - ) -> SimulationEngine { - let rpc_state_reader = Arc::new(setup_reader(block_number)); - - // Initialize the engine - SimulationEngine::new(rpc_state_reader, contract_overrides) - .expect("should initialize engine") - } - - // Mock empty StateReader - struct StateReaderMock {} - - impl StateReaderMock { - fn new() -> Self { - Self {} - } - } - - #[allow(unused_variables)] - #[allow(dead_code)] - impl StateReader for StateReaderMock { - fn get_contract_class(&self, class_hash: &ClassHash) -> Result { - todo!() - } - - fn get_class_hash_at(&self, contract_address: &Address) -> Result { - todo!() - } - - fn get_nonce_at(&self, contract_address: &Address) -> Result { - Ok(Felt252::from(1)) - } - - fn get_storage_at(&self, storage_entry: &StorageEntry) -> Result { - todo!() - } - - fn get_compiled_class_hash( - &self, - class_hash: &ClassHash, - ) -> Result { - todo!() - } - } - - #[rstest] - #[case::cairo_0("tests/resources/fibonacci.json")] - #[case::cairo_1("tests/resources/fibonacci.casm")] - fn test_create_engine_with_contract_from_path(#[case] path: &str) { - let cargo_manifest_path = Path::new(env!("CARGO_MANIFEST_DIR")); - dbg!("Cargo manifest path is: {:?}", cargo_manifest_path); - - let path = cargo_manifest_path.join(path); - dbg!("Contract path is: {:?}", &path); - let path_str: String = path.to_str().unwrap().to_owned(); - - let address: Address = Address(Felt252::from(0u8)); - let input_contract = ContractOverride::new(address, [0u8; 32], Some(path_str)); - let rpc_state_reader = Arc::new(StateReaderMock::new()); - let engine_result = SimulationEngine::new(rpc_state_reader, vec![input_contract].into()); - if let Err(err) = engine_result { - panic!("Failed to create engine with error: {:?}", err); - } - assert!(engine_result.is_ok()); - } - - #[rstest] - #[cfg_attr(not(feature = "network_tests"), ignore)] - fn test_create_engine_with_contract_without_path() { - // USDC token contract - let address = - address_str("0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8"); - let class_hash: ClassHash = - hex::decode("052c7ba99c77fc38dd3346beea6c0753c3471f2e3135af5bb837d6c9523fff62") - .unwrap() - .as_slice() - .try_into() - .unwrap(); - let input_contract = ContractOverride::new(address, class_hash, None); - - // Create engine - let rpc_state_reader = setup_reader(333333); - let engine_result = - SimulationEngine::new(Arc::new(rpc_state_reader), vec![input_contract].into()); - if let Err(err) = engine_result { - panic!("Failed to create engine with error: {:?}", err); - } - - assert!(engine_result.is_ok()); - } - - #[test] - fn test_set_state() { - let mut engine = SimulationEngine { - state: CachedState::new( - Arc::new(StateReaderMock::new()), - ContractClassCache::default(), - ), - contract_overrides: vec![], - }; - - let mut state = HashMap::new(); - let mut overrides = HashMap::new(); - - let address = Address(123.into()); - let slot = [0; 32]; - let value = Felt252::from(1); - - overrides.insert(slot, value.clone()); - state.insert(address.clone(), overrides); - - engine.set_state(state.clone()); - - let storage_entry = (address, slot); - let retrieved_value = engine - .state - .get_storage_at(&storage_entry) - .unwrap(); - assert_eq!(retrieved_value, value, "State was not set correctly"); - } - - #[rstest] - fn test_clear_cache_writes() { - let rpc_state_reader = Arc::new(StateReaderMock::new()); - let mut engine = SimulationEngine::new(rpc_state_reader.clone(), None).unwrap(); - let address = Address(Felt252::from(0u8)); - let write_hash = [0u8; 32]; - let value: Felt252 = 0.into(); - - // Add a cache write - engine - .state - .set_storage_at(&(address.clone(), write_hash), value); - // Add a nonce write - engine - .state - .increment_nonce(&address) - .ok(); - - // Check writes exist - let cache = engine.state.cache_mut(); - assert!(!cache.storage_writes().is_empty()); - assert!(!cache.nonce_writes_mut().is_empty()); - - // Clear writes - engine.clear_cache_writes(); - - // Check writes are empty - let final_cache = engine.state.cache_mut(); - assert!(final_cache.storage_writes().is_empty()); - assert!(final_cache - .nonce_writes_mut() - .is_empty()) - } - - #[rstest] - fn test_interpret_results() { - let address = Address(Felt252::from(0u8)); - let rpc_state_reader = Arc::new(StateReaderMock::new()); - let mut engine = SimulationEngine::new(rpc_state_reader.clone(), None).unwrap(); - - // Construct expected values - let gas_consumed = 10; - let retdata: Vec = vec![1, 2, 3] - .into_iter() - .map(Felt252::from) - .collect(); - let mut state_updates = HashMap::new(); - let mut storage_write: HashMap<[u8; 32], Felt252> = HashMap::new(); - let write_hash = [0u8; 32]; - let value: Felt252 = 0.into(); - storage_write.insert(write_hash, value.clone()); - state_updates.insert(address.clone(), storage_write); - - // Apply overrides (state changes that mustn't appear in the result) - let override_hash = [1u8; 32]; - engine - .state - .set_storage_at(&(address.clone(), override_hash), value.clone()); - // Apply mock simulation write (state change that must appear in the result) - engine - .state - .set_storage_at(&(address.clone(), write_hash), value); - - // Construct execution result - let mut call_info = - CallInfo::empty_constructor_call(address.clone(), address.clone(), None); - call_info.gas_consumed = gas_consumed; - call_info.retdata.clone_from(&retdata); - // Flag relevant storage slots as updated during simulation - call_info.accessed_storage_keys = HashSet::new(); - call_info - .accessed_storage_keys - .insert(write_hash); - let execution_result = - ExecutionResult { call_info: Some(call_info), revert_error: None, n_reverted_steps: 0 }; - - // Call interpret_result - let result = engine - .interpret_result(execution_result) - .unwrap(); - - assert_eq!(result.gas_used, gas_consumed); - assert_eq!(result.result, retdata); - assert_eq!(result.state_updates, state_updates); - } - - #[rstest] - fn test_interpret_results_with_revert_error() { - // Construct state and engine - let rpc_state_reader = Arc::new(StateReaderMock::new()); - let engine = SimulationEngine::new(rpc_state_reader.clone(), None).unwrap(); - - // Construct reverted execution result - let execution_result_with_revert = ExecutionResult { - call_info: None, - revert_error: Some("Test Revert".to_string()), - n_reverted_steps: 0, - }; - - match engine.interpret_result(execution_result_with_revert) { - Err(SimulationError::TransactionError(message)) => { - assert!(message.contains("Execution reverted with error: Test Revert")); - } - _ => panic!("Expected TransactionError for revert"), - } - } - - #[rstest] - fn test_interpret_results_with_empty_call_info() { - // Construct state and engine - let rpc_state_reader = Arc::new(StateReaderMock::new()); - let engine = SimulationEngine::new(rpc_state_reader.clone(), None).unwrap(); - - // Construct execution result with no call info - let execution_result_no_call_info = - ExecutionResult { call_info: None, revert_error: None, n_reverted_steps: 0 }; - - match engine.interpret_result(execution_result_no_call_info) { - Err(SimulationError::ResultError(message)) => { - assert_eq!(message, "Call info is empty"); - } - _ => panic!("Expected ResultError for empty call_info"), - } - } - - #[rstest] - fn test_interpret_results_with_failure_flag() { - // Construct state and engine - let address = Address(Felt252::from(0u8)); - let rpc_state_reader = Arc::new(StateReaderMock::new()); - let engine = SimulationEngine::new(rpc_state_reader.clone(), None).unwrap(); - - // Construct execution result with failed call - let mut call_info = - CallInfo::empty_constructor_call(address.clone(), address.clone(), None); - call_info.failure_flag = true; - let execution_result_fail_flag = - ExecutionResult { call_info: Some(call_info), revert_error: None, n_reverted_steps: 0 }; - - match engine.interpret_result(execution_result_fail_flag) { - Err(SimulationError::ResultError(message)) => { - assert_eq!(message, "Execution failed"); - } - _ => panic!("Expected ResultError for failed call"), - } - } - - // Simulation of an inner call to a Cairo 0 contract. - #[rstest] - #[cfg_attr(not(feature = "network_tests"), ignore)] - fn test_simulate_cairo0_call() { - // https://starkscan.co/tx/0x046e50c398bf08a69c7bbf1dedc35760556ba7c426a704d1ecb67378f01ffe59 - - // Set up the engine - let block_number = 366118; // actual block is 366119 - let mut engine = setup_engine(block_number, None); - - // Prepare the simulation parameters - let params = SimulationParameters::new( - address_str("0x035fc5a31b2cf06af3a7e9b9b00a508b72dea342277c7415b770fbd69a6c5933"), - address_str("0x022b05f9396d2c48183f6deaf138a57522bcc8b35b67dee919f76403d1783136"), - vec![ - felt_str("0x10884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28"), /* Felt252 */ - felt_str("62399604864"), // The lower bits of Uint256 - felt_str("0"), // The upper bits of Uint256 - ], - "approve".to_owned(), - None, - Some(u128::MAX), - block_number, - ); - - // Simulate the transaction - let result = engine - .simulate(¶ms) - .expect("should simulate"); - - let expected_result = SimulationResult::new( - vec![felt_str("1")], - vec![( - address_str( - "980641348758169158361564622616439166824113829417782360965256920656439161142", - ), - vec![ - ( - class_hash_str( - "0x04ec12998482b49cff9925cf695c114762a27c32bcd1afe898073bdab6f0d307", - ), - felt_str("0"), - ), - ( - class_hash_str( - "0x04ec12998482b49cff9925cf695c114762a27c32bcd1afe898073bdab6f0d306", - ), - felt_str("62399604864"), - ), - ] - .into_iter() - .collect(), - )] - .into_iter() - .collect(), - 0, - ); - assert_eq!(result, expected_result); - } - - // Simulation of an inner call to a Cairo 1 contract. - #[rstest] - #[cfg_attr(not(feature = "network_tests"), ignore)] - fn test_simulate_cairo1_call() { - // https://starkscan.co/tx/0x008f1f8ee931f40aa5ef9111e0836d68d8d1cf07801c0d17750d66937f02fb54 - - // Set up the engine - let block_number = 368719; // actual tx block is 368720 - let mut engine = setup_engine(block_numbe, None); - - // Prepare the simulation parameters - let params = SimulationParameters::new( - address_str("0x04eb4dcf306e28e13e6361bca368056d4bfd3051ee96fe6b7207662fbcaf3d2d"), - address_str("0x07d14dfd8ee95b41fce179170d88ba1f0d5a512e13aeb232f19cfeec0a88f8bf"), - vec![ - felt_str("602131441545"), - felt_str("1698855348"), - felt_str("28263441981469284"), - felt_str("841052542115774484"), - felt_str( - "3254871180842845207740459874836292658857302757892203765805208854602709573266", - ), - felt_str( - "3507176392343394624391389069340504903187207915538258427726787963729562556344", - ), - ], - "write_confirmation".to_owned(), - None, - Some(u128::MAX), - block_number, - ); - - // Simulate the transaction - let result = engine.simulate(¶ms); - - // Check the result - if let Err(err) = result { - panic!("Failed to simulate transaction with error: {:?}", err); - } - assert!(result.is_ok()); - dbg!("Simulation result is: {:?}", result.unwrap()); - } - - // Simulation of an external multicall. - #[rstest] - // #[cfg_attr(not(feature = "network_tests"), ignore)] - #[ignore] - fn test_simulate_multicall() { - // https://starkscan.co/tx/0x046e50c398bf08a69c7bbf1dedc35760556ba7c426a704d1ecb67378f01ffe59 - - // Set up the engine - let block_number = 366118; // actual block is 366119 - let mut engine = setup_engine(block_number, None); - - // Prepare the simulation parameters - let params = SimulationParameters::new( - address_str("0"), - address_str("0x0131c7d655f9636a761cf655dec380dba4ac71c99193fcce666521312a6a9303"), - vec![ - felt_str("2"), - felt_str( - "980641348758169158361564622616439166824113829417782360965256920656439161142", - ), - felt_str( - "949021990203918389843157787496164629863144228991510976554585288817234167820", - ), - felt_str("3"), - felt_str( - "467359278613506166151492726487752216059557962335532790304583050955123345960", - ), - felt_str("62399604864"), - felt_str("0"), - felt_str( - "467359278613506166151492726487752216059557962335532790304583050955123345960", - ), - felt_str( - "322637753074552370500544931377150993467524337001753746958704872129235461672", - ), - felt_str("7"), - felt_str("1"), - felt_str("62399604864"), - felt_str("0"), - felt_str("2265697025134158"), - felt_str("0"), - felt_str("4057938"), - felt_str("0"), - ], - "__execute__".to_owned(), - None, - Some(u128::MAX), - block_number, - ); - - // Simulate the transaction - let result = engine - .simulate(¶ms) - .expect("should simulate"); - - assert!(result.gas_used > 0, "Gas used should be positive"); - } - - #[rstest] - fn test_set_block_and_reset_cache() { - let contract_override_address = - address_str("0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3"); - - // Set up the engine - let block_number = 354498; - let contract_overrides = vec![ContractOverride::new( - contract_override_address.clone(), - class_hash_str( - "0x052c7ba99c77fc38dd3346beea6c0753c3471f2e3135af5bb837d6c9523fff62", /* Needs to be an actuall class hash to work with state reader */ - ), - None, - )]; - let mut engine = setup_engine(block_number, contract_overrides.into()); - - // Set state storage inital value - engine - .state - .cache_mut() - .storage_initial_values_mut() - .extend(vec![( - (contract_override_address.clone(), class_hash_str("0123")), - felt_str("0123"), - )]); - // Set state storage writes - engine - .state - .cache_mut() - .storage_writes_mut() - .extend(vec![( - (contract_override_address.clone(), class_hash_str("456")), - felt_str("456"), - )]); - - assert_eq!(engine.state.state_reader.block(), &BlockNumber(block_number).into()); - - // Set the block to a different block - let new_block_number = 354499; - engine.set_block_and_reset_cache(BlockNumber(new_block_number).into()); - - assert_eq!(engine.state.state_reader.block(), &BlockNumber(new_block_number).into()); - assert_eq!( - felt_str("0"), - engine - .state - .get_storage_at(&(contract_override_address.clone(), class_hash_str("0123"))) - .unwrap() - ); - assert_eq!( - felt_str("0"), - engine - .state - .get_storage_at(&(contract_override_address.clone(), class_hash_str("456"))) - .unwrap() - ); - } - - #[rstest] - fn test_clear_cache() { - // Set up the engine - let rpc_state_reader = Arc::new(StateReaderMock::new()); - let mut engine = SimulationEngine::new(rpc_state_reader.clone(), None).unwrap(); - - // Insert contracts in cache - let mut contract_classes = HashMap::new(); - let contract_hash: [u8; 32] = [1; 32]; - - let cargo_manifest_path = Path::new(env!("CARGO_MANIFEST_DIR")); - let path = cargo_manifest_path.join("tests/resources/fibonacci.json"); - let compiled_class = load_compiled_class_from_path(path).unwrap(); - contract_classes.insert(contract_hash, compiled_class.clone()); - - engine - .state - .set_contract_classes(contract_classes) - .unwrap(); - - // Clear cache - engine.clear_cache(rpc_state_reader.clone()); - - // Assert that we still have contracts cached - let contract_cache = engine.state.contract_classes(); - let cached_contract = contract_cache - .get(&contract_hash) - .unwrap() - .clone(); - - assert_eq!(cached_contract, compiled_class); - } -} From 02b4063fc38dd27583f516f9d0d357e168b7bae1 Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Tue, 22 Oct 2024 15:25:30 +0100 Subject: [PATCH 2/3] chore: Remove tycho_client This was used only in legacy code (that was hardcoded for ambient) --- don't change below this line --- ENG-3782 Took 44 minutes --- src/evm/mod.rs | 1 - src/evm/tycho_client.rs | 414 ---------------------------------------- src/evm/tycho_db.rs | 108 ++--------- 3 files changed, 14 insertions(+), 509 deletions(-) delete mode 100644 src/evm/tycho_client.rs diff --git a/src/evm/mod.rs b/src/evm/mod.rs index 7d205322..283576eb 100644 --- a/src/evm/mod.rs +++ b/src/evm/mod.rs @@ -2,6 +2,5 @@ pub mod account_storage; pub mod database; pub mod simulation; pub mod traces; -pub mod tycho_client; pub mod tycho_db; pub mod tycho_models; diff --git a/src/evm/tycho_client.rs b/src/evm/tycho_client.rs deleted file mode 100644 index e9ec9dba..00000000 --- a/src/evm/tycho_client.rs +++ /dev/null @@ -1,414 +0,0 @@ -use futures::StreamExt; -use hyper::{client::HttpConnector, Body, Client, Request, Uri}; -use std::{collections::HashMap, string::ToString}; -use thiserror::Error; -use tracing::{debug, error, info, instrument, trace, warn}; -use uuid::Uuid; - -use super::tycho_models::{ - BlockAccountChanges, Chain, Command, ExtractorIdentity, Response, WebSocketMessage, -}; -use crate::evm::tycho_models::{StateRequestBody, StateRequestParameters, StateRequestResponse}; -use async_trait::async_trait; -use futures::SinkExt; -use tokio::sync::mpsc::{self, Receiver}; -use tokio_tungstenite::{connect_async, tungstenite::protocol::Message}; - -/// TODO read consts from config -pub const TYCHO_SERVER_VERSION: &str = "v1"; -pub const AMBIENT_EXTRACTOR_HANDLE: &str = "vm:ambient"; -pub const AMBIENT_ACCOUNT_ADDRESS: [u8; 20] = [ - 0xaa, 0xaa, 0xaa, 0xaa, 0xa2, 0x4e, 0xee, 0xb8, 0xd5, 0x7d, 0x43, 0x12, 0x24, 0xf7, 0x38, 0x32, - 0xbc, 0x34, 0xf6, 0x88, -]; -#[derive(Error, Debug)] -pub enum TychoClientError { - #[error("Failed to parse URI: {0}. Error: {1}")] - UriParsing(String, String), - #[error("Failed to format request: {0}")] - FormatRequest(String), - #[error("Unexpected HTTP client error: {0}")] - HttpClient(String), - #[error("Failed to parse response: {0}")] - ParseResponse(String), -} - -#[derive(Debug, Clone)] -pub struct TychoHttpClientImpl { - http_client: Client, - uri: Uri, -} - -impl TychoHttpClientImpl { - pub fn new(base_uri: &str) -> Result { - let uri = base_uri - .parse::() - .map_err(|e| TychoClientError::UriParsing(base_uri.to_string(), e.to_string()))?; - - Ok(Self { http_client: Client::new(), uri }) - } -} - -#[async_trait] -pub trait TychoHttpClient { - async fn get_state( - &self, - filters: &StateRequestParameters, - request: &StateRequestBody, - ) -> Result; -} - -#[async_trait] -impl TychoHttpClient for TychoHttpClientImpl { - #[instrument(skip(self, filters, request))] - async fn get_state( - &self, - filters: &StateRequestParameters, - request: &StateRequestBody, - ) -> Result { - // Check if contract ids are specified - if request.contract_ids.is_none() || - request - .contract_ids - .as_ref() - .unwrap() - .is_empty() - { - warn!("No contract ids specified in request."); - } - - let uri = format!( - "{}/{}/contract_state?{}", - self.uri - .to_string() - .trim_end_matches('/'), - TYCHO_SERVER_VERSION, - filters.to_query_string() - ); - debug!(%uri, "Sending contract_state request to Tycho server"); - let body = serde_json::to_string(&request) - .map_err(|e| TychoClientError::FormatRequest(e.to_string()))?; - - let header = hyper::header::HeaderValue::from_str("application/json") - .map_err(|e| TychoClientError::FormatRequest(e.to_string()))?; - - let req = Request::post(uri) - .header(hyper::header::CONTENT_TYPE, header) - .body(Body::from(body)) - .map_err(|e| TychoClientError::FormatRequest(e.to_string()))?; - debug!(?req, "Sending request to Tycho server"); - - let response = self - .http_client - .request(req) - .await - .map_err(|e| TychoClientError::HttpClient(e.to_string()))?; - debug!(?response, "Received response from Tycho server"); - - let body = hyper::body::to_bytes(response.into_body()) - .await - .map_err(|e| TychoClientError::ParseResponse(e.to_string()))?; - let accounts: StateRequestResponse = serde_json::from_slice(&body) - .map_err(|e| TychoClientError::ParseResponse(e.to_string()))?; - info!(?accounts, "Received contract_state response from Tycho server"); - - Ok(accounts) - } -} - -pub struct TychoWsClientImpl { - uri: Uri, -} - -impl TychoWsClientImpl { - pub fn new(ws_uri: &str) -> Result { - let uri = ws_uri - .parse::() - .map_err(|e| TychoClientError::UriParsing(ws_uri.to_string(), e.to_string()))?; - - Ok(Self { uri }) - } -} - -#[async_trait] -pub trait TychoWsClient { - /// Subscribe to an extractor and receive realtime messages - fn subscribe(&self, extractor_id: ExtractorIdentity) -> Result<(), TychoClientError>; - - /// Unsubscribe from an extractor - fn unsubscribe(&self, subscription_id: Uuid) -> Result<(), TychoClientError>; - - /// Consumes realtime messages from the WebSocket server - async fn realtime_messages(&self) -> Receiver; -} - -#[async_trait] -impl TychoWsClient for TychoWsClientImpl { - #[allow(unused_variables)] - fn subscribe(&self, extractor_id: ExtractorIdentity) -> Result<(), TychoClientError> { - panic!("Not implemented"); - } - - #[allow(unused_variables)] - fn unsubscribe(&self, subscription_id: Uuid) -> Result<(), TychoClientError> { - panic!("Not implemented"); - } - - async fn realtime_messages(&self) -> Receiver { - // Create a channel to send and receive messages. - let (tx, rx) = mpsc::channel(30); //TODO: Set this properly. - - // Spawn a task to connect to the WebSocket server and listen for realtime messages. - let ws_uri = format!("{}{}/ws", self.uri, TYCHO_SERVER_VERSION); // TODO: Set path properly - info!(?ws_uri, "Spawning task to connect to WebSocket server"); - tokio::spawn(async move { - let mut active_extractors: HashMap = HashMap::new(); - - // Connect to Tycho server - info!(?ws_uri, "Connecting to WebSocket server"); - let (ws, _) = connect_async(&ws_uri) - .await - .map_err(|e| error!(error = %e, "Failed to connect to WebSocket server")) - .expect("connect to websocket"); - // Split the WebSocket into a sender and receive of messages. - let (mut ws_sink, ws_stream) = ws.split(); - - // Send a subscribe request to ambient extractor - // TODO: Read from config - let command = Command::Subscribe { - extractor_id: ExtractorIdentity::new(Chain::Ethereum, AMBIENT_EXTRACTOR_HANDLE), - }; - let _ = ws_sink - .send(Message::Text(serde_json::to_string(&command).unwrap())) - .await - .map_err(|e| error!(error = %e, "Failed to send subscribe request")); - - // Use the stream directly to listen for messages. - let mut incoming_messages = ws_stream.boxed(); - while let Some(msg) = incoming_messages.next().await { - match msg { - Ok(Message::Text(text)) => { - match serde_json::from_str::(&text) { - Ok(WebSocketMessage::BlockAccountChanges(block_state_changes)) => { - info!( - ?block_state_changes, - "Received a block state change, sending to channel" - ); - tx.send(block_state_changes) - .await - .map_err(|e| error!(error = %e, "Failed to send message")) - .expect("send message"); - } - Ok(WebSocketMessage::Response(Response::NewSubscription { - extractor_id, - subscription_id, - })) => { - info!( - ?extractor_id, - ?subscription_id, - "Received a new subscription" - ); - active_extractors.insert(subscription_id, extractor_id); - trace!(?active_extractors, "Active extractors"); - } - Ok(WebSocketMessage::Response(Response::SubscriptionEnded { - subscription_id, - })) => { - info!(?subscription_id, "Received a subscription ended"); - active_extractors - .remove(&subscription_id) - .expect("subscription id in active extractors"); - } - Err(e) => { - error!(error = %e, "Failed to deserialize message"); - } - } - } - Ok(Message::Ping(_)) => { - // Respond to pings with pongs. - ws_sink - .send(Message::Pong(Vec::new())) - .await - .unwrap(); - } - Ok(Message::Pong(_)) => { - // Do nothing. - } - Ok(Message::Close(_)) => { - // Close the connection. - drop(tx); - return; - } - Ok(unknown_msg) => { - info!("Received an unknown message type: {:?}", unknown_msg); - } - Err(e) => { - error!("Failed to get a websocket message: {}", e); - } - } - } - }); - - info!("Returning receiver"); - rx - } -} - -#[cfg(test)] -mod tests { - use crate::evm::tycho_models::{AccountUpdate, Block, ChangeType}; - use chrono::NaiveDateTime; - - use super::*; - - use mockito::Server; - - use revm::primitives::{Address, B256, U256 as rU256}; - use std::{net::TcpListener, str::FromStr}; - - #[tokio::test] - async fn test_realtime_messages() { - let server = TcpListener::bind("127.0.0.1:0").unwrap(); - let addr = server.local_addr().unwrap(); - - let server_thread = std::thread::spawn(move || { - // Accept only the first connection - if let Ok((stream, _)) = server.accept() { - let mut websocket = tungstenite::accept(stream).unwrap(); - - let test_msg_content = r#" - { - "extractor": "vm:ambient", - "chain": "ethereum", - "block": { - "number": 123, - "hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "parent_hash": - "0x0000000000000000000000000000000000000000000000000000000000000000", - "chain": "ethereum", "ts": "2023-09-14T00:00:00" - }, - "account_updates": { - "0x7a250d5630b4cf539739df2c5dacb4c659f2488d": { - "address": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d", - "chain": "ethereum", - "slots": {}, - "balance": - "0x00000000000000000000000000000000000000000000000000000000000001f4", - "code": "", "change": "Update" - } - }, - "new_pools": {} - } - "#; - - websocket - .send(Message::Text(test_msg_content.to_string())) - .expect("Failed to send message"); - - // Close the WebSocket connection - let _ = websocket.close(None); - } - }); - - // Now, you can create a client and connect to the mocked WebSocket server - let client = TychoWsClientImpl::new(&format!("ws://{}", addr)).unwrap(); - - // You can listen to the realtime_messages and expect the messages that you send from - // handle_connection - let mut rx = client.realtime_messages().await; - let received_msg = rx - .recv() - .await - .expect("receive message"); - - let expected_blk = Block { - number: 123, - hash: B256::from_str( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ) - .unwrap(), - parent_hash: B256::from_str( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ) - .unwrap(), - chain: Chain::Ethereum, - ts: NaiveDateTime::from_str("2023-09-14T00:00:00").unwrap(), - }; - let account_update = AccountUpdate::new( - Address::from_str("0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D").unwrap(), - Chain::Ethereum, - HashMap::new(), - Some(rU256::from(500)), - Some(Vec::::new()), - ChangeType::Update, - ); - let account_updates: HashMap = vec![( - Address::from_str("0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D").unwrap(), - account_update, - )] - .into_iter() - .collect(); - let expected = BlockAccountChanges::new( - "vm:ambient".to_string(), - Chain::Ethereum, - expected_blk, - account_updates, - HashMap::new(), - ); - - assert_eq!(received_msg, expected); - - server_thread.join().unwrap(); - } - - #[tokio::test] - async fn test_simple_route_mock_async() { - let mut server = Server::new_async().await; - let server_resp = r#" - { - "accounts": [ - { - "chain": "ethereum", - "address": "0x0000000000000000000000000000000000000000", - "title": "", - "slots": {}, - "balance": "0x1f4", - "code": "", - "code_hash": "0x5c06b7c5b3d910fd33bc2229846f9ddaf91d584d9b196e16636901ac3a77077e", - "balance_modify_tx": "0x0000000000000000000000000000000000000000000000000000000000000000", - "code_modify_tx": "0x0000000000000000000000000000000000000000000000000000000000000000", - "creation_tx": null - } - ] - } - "#; - // test that the response is deserialized correctly - serde_json::from_str::(server_resp).expect("deserialize"); - - let mocked_server = server - .mock("POST", "/v1/contract_state?chain=ethereum") - .expect(1) - .with_body(server_resp) - .create_async() - .await; - - let client = TychoHttpClientImpl::new(server.url().as_str()).expect("create client"); - - let response = client - .get_state(&Default::default(), &Default::default()) - .await - .expect("get state"); - let accounts = response.accounts; - - mocked_server.assert(); - assert_eq!(accounts.len(), 1); - assert_eq!(accounts[0].slots, HashMap::new()); - assert_eq!(accounts[0].balance, rU256::from(500)); - assert_eq!(accounts[0].code, Vec::::new()); - assert_eq!( - accounts[0].code_hash, - B256::from_str("0x5c06b7c5b3d910fd33bc2229846f9ddaf91d584d9b196e16636901ac3a77077e") - .unwrap() - ); - } -} diff --git a/src/evm/tycho_db.rs b/src/evm/tycho_db.rs index cdaf1ff6..2c19582e 100644 --- a/src/evm/tycho_db.rs +++ b/src/evm/tycho_db.rs @@ -11,8 +11,7 @@ use revm::{ use crate::evm::{ account_storage::{AccountStorage, StateUpdate}, database::BlockHeader, - tycho_client::{TychoClientError, TychoHttpClient, AMBIENT_ACCOUNT_ADDRESS}, - tycho_models::{AccountUpdate, ChangeType, StateRequestBody, StateRequestParameters, Version}, + tycho_models::{AccountUpdate, ChangeType}, }; /// Perform bytecode analysis on the code of an account. @@ -25,6 +24,18 @@ pub fn to_analysed(account_info: AccountInfo) -> AccountInfo { } } +#[derive(Error, Debug)] +pub enum TychoClientError { + #[error("Failed to parse URI: {0}. Error: {1}")] + UriParsing(String, String), + #[error("Failed to format request: {0}")] + FormatRequest(String), + #[error("Unexpected HTTP client error: {0}")] + HttpClient(String), + #[error("Failed to parse response: {0}")] + ParseResponse(String), +} + #[derive(Error, Debug)] pub enum PreCachedDBError { #[error("Account {0} not found")] @@ -64,40 +75,6 @@ impl PreCachedDB { }) } - /// Initialize the state of the database. - #[instrument(skip_all)] - async fn initialize_state( - &self, - client: &impl TychoHttpClient, - ) -> Result<(), PreCachedDBError> { - info!("Getting current state"); - let state = client - .get_state( - &StateRequestParameters::default(), - &StateRequestBody::new( - Some(vec![Address::from(AMBIENT_ACCOUNT_ADDRESS)]), - Version::default(), - ), - ) - .await - .map_err(PreCachedDBError::TychoClientError)?; - - for account in state.accounts.into_iter() { - info!(%account.address, "Initializing account"); - self.init_account( - account.address, - AccountInfo::new( - account.balance, - 0, - account.code_hash, - Bytecode::new_raw(Bytes::from(account.code)), - ), - Some(account.slots), - ); - } - Ok(()) - } - #[instrument(skip_all)] pub async fn update(&self, account_updates: Vec, block: Option) { // Block the current thread until the future completes. @@ -373,20 +350,13 @@ impl DatabaseRef for PreCachedDB { #[cfg(test)] mod tests { - use async_trait::async_trait; use chrono::DateTime; use revm::primitives::U256 as rU256; use rstest::{fixture, rstest}; use std::{error::Error, str::FromStr}; - use crate::evm::{ - tycho_client::TychoClientError, - tycho_models::{ - AccountUpdate, Block, Chain, ChangeType, ResponseAccount, StateRequestParameters, - StateRequestResponse, - }, - }; + use crate::evm::tycho_models::{AccountUpdate, Block, Chain, ChangeType}; use super::*; @@ -537,56 +507,6 @@ mod tests { Ok(()) } - pub struct MockTychoClient { - mock_state: StateRequestResponse, - } - - impl MockTychoClient { - pub fn new(mock_state: StateRequestResponse) -> Self { - MockTychoClient { mock_state } - } - } - - #[fixture] - pub fn mock_client() -> MockTychoClient { - let mut contract_slots = HashMap::::new(); - contract_slots.insert(rU256::from(1), rU256::from(987)); - - let creation_tx = - B256::from_str("0x1234000000000000000000000000000000000000000000000000000000000000") - .unwrap(); - - let account: ResponseAccount = ResponseAccount { - chain: Chain::Ethereum, - address: Address::from_str("0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc").unwrap(), - title: "mock".to_owned(), - slots: contract_slots, - balance: rU256::from(123), - code: Vec::::new(), - code_hash: B256::from_str( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ) - .unwrap(), - balance_modify_tx: creation_tx, - code_modify_tx: creation_tx, - creation_tx: Some(creation_tx), - }; - - let mock_state = StateRequestResponse::new(vec![account]); - MockTychoClient::new(mock_state) - } - - #[async_trait] - impl TychoHttpClient for MockTychoClient { - async fn get_state( - &self, - _filters: &StateRequestParameters, - _request: &StateRequestBody, - ) -> Result { - Ok(self.mock_state.clone()) - } - } - #[rstest] #[tokio::test] async fn test_update() { From a6c2e9b60dd46fc51cac30ef7c88bd30bff2b053 Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Tue, 22 Oct 2024 16:26:46 +0100 Subject: [PATCH 3/3] chore: Remove all mentions to starknet code Remove unnecessary dependencies --- don't change below this line --- ENG-3782 Took 53 minutes --- Cargo.lock | 21 - Cargo.toml | 17 - protosim_py/Cargo.toml | 2 +- protosim_py/protosim_starknet_demo.py | 152 -- .../python/protosim_py/starknet/__init__.py | 7 - protosim_py/src/lib.rs | 11 - protosim_py/src/starknet_simulation_py.rs | 71 - protosim_py/src/starknet_structs_py.rs | 224 --- src/evm/tycho_models.rs | 1 - src/lib.rs | 10 - src/tests/mod.rs | 1 - src/tests/starknet/mod.rs | 1 - src/tests/starknet/resources/fibonacci.cairo | 18 - src/tests/starknet/resources/fibonacci.casm | 492 ----- src/tests/starknet/resources/fibonacci.json | 1729 ----------------- .../starknet/test_starknet_simulation.rs | 315 --- 16 files changed, 1 insertion(+), 3071 deletions(-) delete mode 100644 protosim_py/protosim_starknet_demo.py delete mode 100644 protosim_py/python/protosim_py/starknet/__init__.py delete mode 100644 protosim_py/src/starknet_simulation_py.rs delete mode 100644 protosim_py/src/starknet_structs_py.rs delete mode 100644 src/tests/mod.rs delete mode 100644 src/tests/starknet/mod.rs delete mode 100644 src/tests/starknet/resources/fibonacci.cairo delete mode 100644 src/tests/starknet/resources/fibonacci.casm delete mode 100644 src/tests/starknet/resources/fibonacci.json delete mode 100644 src/tests/starknet/test_starknet_simulation.rs diff --git a/Cargo.lock b/Cargo.lock index 7e9c46f2..0f48dd52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3037,18 +3037,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "enum_dispatch" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11f36e95862220b211a6e2aa5eca09b4fa391b13cd52ceb8035a24bf65a79de2" -dependencies = [ - "once_cell", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "enumn" version = "0.1.8" @@ -6248,18 +6236,14 @@ name = "protosim" version = "0.23.1" dependencies = [ "approx", - "async-trait", - "cairo-vm", "chrono", "dotenv", - "enum_dispatch", "ethabi 13.0.0", "ethers", "foundry-config", "foundry-evm", "futures 0.3.28", "hex", - "hyper 0.14.27", "mini-moka", "mockito", "num-traits 0.2.17", @@ -6270,18 +6254,13 @@ dependencies = [ "rstest", "serde", "serde_json", - "starknet", - "starknet_api", - "starknet_in_rust", "strum 0.25.0", "strum_macros 0.25.2", "tempfile", "thiserror", "tokio", - "tokio-tungstenite 0.20.1", "tracing", "tracing-subscriber", - "tungstenite 0.20.1", "tycho-client", "tycho-core", "uuid 1.4.1", diff --git a/Cargo.toml b/Cargo.toml index 26c270dc..fc8081db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,13 +9,9 @@ members = ["protosim_py"] [dependencies] ethabi = "13.0" ethers = "2.0.13" -enum_dispatch = "0.3.8" serde_json = "1.0.105" serde = { version = "1.0", features = ["rc"] } tokio = { version = "1.38.0", features = ["full"] } -tokio-tungstenite = "0.20.1" -async-trait = "0.1.73" -hyper = "0.14.27" futures = "0.3.28" revm = { version = "12.1.0", features = ["ethersdb", "serde"] } hex = "0.4.3" @@ -36,11 +32,6 @@ reqwest = { version = "0.12.7", features = ["blocking"] } tycho-core = { git = "ssh://github.com/propeller-heads/tycho-indexer.git", package = "tycho-core", tag = "0.31.3" } tycho-client = { git = "ssh://github.com/propeller-heads/tycho-indexer.git", package = "tycho-client", tag = "0.31.3" } rpc_state_reader = { git = "https://github.com/propeller-heads/starknet_in_rust.git", package = "rpc_state_reader", branch = "feature/bump-cairo-lang-version", optional = true } -starknet_in_rust = { git = "https://github.com/propeller-heads/starknet_in_rust.git", package = "starknet_in_rust", branch = "feature/bump-cairo-lang-version", optional = true } -starknet_api = { version = "0.4.1", optional = true } -starknet = { version = "0.5.0", optional = true } -cairo-vm = { version = "0.8.5", features = ["cairo-1-hints"], optional = true } - foundry-config = { git = "https://github.com/foundry-rs/foundry", rev = "2544793" } foundry-evm = { git = "https://github.com/foundry-rs/foundry", rev = "2544793" } revm-inspectors = { version = "0.5", features = ["serde"] } @@ -55,19 +46,11 @@ tracing-subscriber = { version = "0.3.17", default-features = false, features = "env-filter", "fmt", ] } -tungstenite = "0.20.1" tempfile = "3.13.0" [features] default = [] network_tests = [] -starknet = [ - "dep:starknet_in_rust", - "dep:starknet_api", - "dep:starknet", - "dep:cairo-vm", - "dep:rpc_state_reader", -] [profile.bench] debug = true diff --git a/protosim_py/Cargo.toml b/protosim_py/Cargo.toml index 97ce5116..74c8e445 100644 --- a/protosim_py/Cargo.toml +++ b/protosim_py/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["cdylib"] num-bigint = "0.4.3" pyo3 = { version = "0.19", features = ["num-bigint", "extension-module"] } pyo3-asyncio = { version = "0.19", features = ["tokio-runtime"] } -protosim = { path = "../", features = ["starknet"] } +protosim = { path = "../"} tokio = { version = "1.38.0", features = ["full"] } ethers = "2.0.13" once_cell = "1.17.2" diff --git a/protosim_py/protosim_starknet_demo.py b/protosim_py/protosim_starknet_demo.py deleted file mode 100644 index 93e5fbb1..00000000 --- a/protosim_py/protosim_starknet_demo.py +++ /dev/null @@ -1,152 +0,0 @@ -"""Example of running a Starknet simulation in Rust from Python. - -(Build and) install the `protosim_py` package in your Python before running this. -See the Readme.md file for instructions. -""" - -import os -from protosim_py import ( - StarknetSimulationEngine, - StarknetSimulationParameters, - StarknetContractOverride, -) -from dotenv import load_dotenv -import logging - -FORMAT = "%(levelname)s %(name)s %(asctime)-15s %(filename)s:%(lineno)d %(message)s" -logging.basicConfig(format=FORMAT) -logging.getLogger().setLevel(logging.INFO) - -U256MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935 -U128MAX = 340282366920938463463374607431768211455 - -# Addresses as constants -BOB_ADDRESS = "0x065c19e14e2587d2de74c561b2113446ca4b389aabe6da1dc4accb6404599e99" -EKUBO_ADDRESS = "0x00000005dd3d2f4429af886cd1a3b08289dbcea99a294197e9eb43b0e0325b4b" -EKUBO_SIMPLE_SWAP_ADDRESS = ( - "0x07a83729aaaae6344d6fca558614cd22ecdd3f5cd90ec0cd20c8d6bf08170431" -) -USDC_ADDRESS = "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8" -ETH_ADDRESS = "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" -DAI_ADDRESS = "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3" - - -def setup_engine(contract_overrides: list = None) -> StarknetSimulationEngine: - load_dotenv() - rpc_url = os.getenv("STARKNET_RPC_URL") - if rpc_url is None: - raise Exception("STARKNET_RPC_URL env variable is not set") - - contract_overrides = contract_overrides if contract_overrides is not None else [] - engine = StarknetSimulationEngine( - rpc_endpoint=rpc_url, - feeder_url="https://alpha-mainnet.starknet.io/feeder_gateway", - contract_overrides=contract_overrides, - ) - return engine - - -def test_starknet_approve_simulation(): - print("Running Starknet simulation") - - # Load api key from env variable or .env file - engine = setup_engine() - - params = StarknetSimulationParameters( - caller="0x035fc5a31b2cf06af3a7e9b9b00a508b72dea342277c7415b770fbd69a6c5933", - to="0x022b05f9396d2c48183f6deaf138a57522bcc8b35b67dee919f76403d1783136", - data=[ - 467359278613506166151492726487752216059557962335532790304583050955123345960, - 62399604864, - 0, - ], - entry_point="approve", - block_number=366118, - ) - - print("Running approval simulation") - result = engine.run_sim(params) - print("Approval simulation result:") - print(f"result: {result.result=}") - print(f"states_updates: {result.states_updates=}") - print(f"gas_used: {result.gas_used=}") - - -# Test consecutive simulations -def test_starknet_swap_simulation(): - block_number = 194554 - token0 = DAI_ADDRESS - token1 = ETH_ADDRESS - test_wallet = BOB_ADDRESS - ekubo_swap_address = EKUBO_SIMPLE_SWAP_ADDRESS - sell_amount = "0x5afb5ab61ef191" - - # Construct engine with contract overrides - sell_token_contract_override = StarknetContractOverride( - token0, - "0x02760f25d5a4fb2bdde5f561fd0b44a3dee78c28903577d37d669939d97036a0", - None, - ) - engine = setup_engine([sell_token_contract_override]) - - # Construct simulation parameters - storage_overrides = { - token0: { - int( - "2039938672845109684464553252816414832543773106309397125013760479565072283554" - ): int("25609114925068689"), - int( - "1919009528300487416898558168639787817852314761514939568475739027942176236393" - ): int("2421600066015287788594"), - } - } - params = StarknetSimulationParameters( - caller=test_wallet, - to=ekubo_swap_address, - data=[ - int(token0, 16), - int(token1, 16), - int("0xc49ba5e353f7d00000000000000000", 16), - 5982, - 0, - int(sell_amount, 16), - 0, - 0, - int("0x65740af99bee7b4bf062fb147160000", 16), - 0, - 0, - int(test_wallet, 16), - 0, - ], # Call data for the swap - entry_point="swap", - overrides=storage_overrides, - block_number=block_number, - gas_limit=U128MAX, - ) - - # Run simulation - print("Running swap simulation #1") - result = engine.run_sim(params) - assert result.gas_used == 9480810 - assert result.result[2] == 21909951468890105 - print("Simulation result:") - print(f"result: {result.result=}") - print(f"states_updates: {result.states_updates=}") - print(f"gas_used: {result.gas_used=}") - - # Run simulation again - # Running the simulation should not persist any state changes, so running it again should give the same result - print("Running swap simulation #2") - result = engine.run_sim(params) - assert result.gas_used == 9480810 - assert result.result[2] == 21909951468890105 - print("Simulation result:") - print(f"result: {result.result=}") - print(f"states_updates: {result.states_updates=}") - print(f"gas_used: {result.gas_used=}") - - -if __name__ == "__main__": - test_starknet_approve_simulation() - - test_starknet_swap_simulation() diff --git a/protosim_py/python/protosim_py/starknet/__init__.py b/protosim_py/python/protosim_py/starknet/__init__.py deleted file mode 100644 index 6966cbb0..00000000 --- a/protosim_py/python/protosim_py/starknet/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from protosim_py._protosim_py import ( - StarknetSimulationEngine, - StarknetContractOverride, - StarknetSimulationEngine, - StarknetSimulationResult, - StarknetSimulationParameters, -) diff --git a/protosim_py/src/lib.rs b/protosim_py/src/lib.rs index d5903a9f..448cfdc4 100644 --- a/protosim_py/src/lib.rs +++ b/protosim_py/src/lib.rs @@ -1,9 +1,5 @@ use pyo3::prelude::*; use simulation_py::SimulationEngine; -// use starknet_simulation_py::StarknetSimulationEngine; -// use starknet_structs_py::{ -// StarknetContractOverride, StarknetSimulationParameters, StarknetSimulationResult, -// }; use structs_py::{ AccountInfo, AccountUpdate, BlockHeader, SimulationDB, SimulationParameters, SimulationResult, StateUpdate, TychoDB, @@ -11,8 +7,6 @@ use structs_py::{ use tracing_subscriber::EnvFilter; mod simulation_py; -// mod starknet_simulation_py; -// mod starknet_structs_py; mod structs_py; /// Transaction simulation using EVM implemented in Rust @@ -49,10 +43,5 @@ fn _protosim_py(_py: Python, m: &PyModule) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::()?; - // m.add_class::()?; - // m.add_class::()?; - // m.add_class::()?; - // m.add_class::()?; - Ok(()) } diff --git a/protosim_py/src/starknet_simulation_py.rs b/protosim_py/src/starknet_simulation_py.rs deleted file mode 100644 index b514dde5..00000000 --- a/protosim_py/src/starknet_simulation_py.rs +++ /dev/null @@ -1,71 +0,0 @@ -use protosim::{ - rpc_state_reader::rpc_state::{BlockTag, BlockValue, RpcChain, RpcState}, - starknet_simulation::{rpc_reader::RpcStateReader, simulation::SimulationEngine}, -}; -use pyo3::prelude::*; -use std::sync::Arc; - -use crate::starknet_structs_py::{ - StarknetContractOverride, StarknetSimulationErrorDetails, StarknetSimulationParameters, - StarknetSimulationResult, -}; - -/// Starknet transaction simulation engine. -/// -/// Data not provided in overrides will be fetched from an RPC node and cached locally. -#[pyclass] -pub struct StarknetSimulationEngine(SimulationEngine); - -#[pymethods] -impl StarknetSimulationEngine { - /// Create a new Starknet simulation engine. - /// - /// # Arguments - /// - /// * `rpc_endpoint` - The RPC endpoint to use for RPC calls. - /// * `feeder_url` - The feeder URL to use for RPC calls. - /// * `contract_overrides` - A list of contract overrides to use for simulation. - #[allow(unused_variables)] - #[new] - fn new( - rpc_endpoint: String, - feeder_url: String, - contract_overrides: Vec, - ) -> Self { - // Create a state reader. It does not matter what block we use as running the simulation - // will set it to the correct block from parameters. - let state_reader = RpcStateReader::new(RpcState::new( - RpcChain::MainNet, - BlockValue::Tag(BlockTag::Latest), - &rpc_endpoint, - &feeder_url, - )); - let engine = SimulationEngine::new( - Arc::new(state_reader), - Some( - contract_overrides - .into_iter() - .map(|override_| override_.into()) - .collect(), - ), - ) - .expect("Failed to create simulation engine"); - Self(engine) - } - - /// Simulate a Starknet transaction. - /// - /// # Arguments - /// - /// * `params` - The simulation parameters of type `StarknetSimulationParameters`. - #[allow(unused_variables)] - fn run_sim( - mut self_: PyRefMut, - params: StarknetSimulationParameters, - ) -> PyResult { - match self_.0.simulate(¶ms.into()) { - Ok(sim_res) => Ok(sim_res.into()), - Err(sim_err) => Err(PyErr::from(StarknetSimulationErrorDetails::from(sim_err))), - } - } -} diff --git a/protosim_py/src/starknet_structs_py.rs b/protosim_py/src/starknet_structs_py.rs deleted file mode 100644 index 8e3de0ad..00000000 --- a/protosim_py/src/starknet_structs_py.rs +++ /dev/null @@ -1,224 +0,0 @@ -use std::collections::{hash_map::Entry, HashMap}; - -use num_bigint::BigUint; -use pyo3::{exceptions::PyRuntimeError, prelude::*}; - -use protosim::{ - starknet_in_rust::{felt::Felt252, utils::Address}, - starknet_simulation::{ - address_str, class_hash_str, - simulation::{ - ContractOverride as RustContractOverride, Overrides, SimulationError, - SimulationParameters, SimulationResult, StorageHash, - }, - }, -}; - -pub fn python_overrides_to_rust( - input: HashMap>, -) -> HashMap { - input - .into_iter() - .fold(HashMap::new(), |mut acc, (address, slots)| { - let address = address_str(&address).expect("should be valid address"); - for (slot, value) in slots { - let slot = Felt252::from(slot).to_be_bytes(); - let value = Felt252::from(value); - match acc.entry(address.clone()) { - Entry::Occupied(mut entry) => { - entry.get_mut().insert(slot, value); - } - Entry::Vacant(entry) => { - let mut new_map = HashMap::new(); - new_map.insert(slot, value); - entry.insert(new_map); - } - } - } - acc - }) -} - -pub fn rust_overrides_to_python( - input: HashMap>, -) -> HashMap> { - input - .into_iter() - .fold(HashMap::new(), |mut result, (address, inner_map)| { - let inner_result = - inner_map - .into_iter() - .fold(HashMap::new(), |mut inner_result, (slot, value)| { - inner_result.insert(BigUint::from_bytes_be(&slot), value.to_biguint()); - inner_result - }); - result.insert(str_address(address), inner_result); - result - }) -} - -fn str_address(address: Address) -> String { - let hex_string = address.0.to_str_radix(16); - format!("0x{}", hex_string) -} - -/// Parameters for Starknet transaction simulation. -#[derive(Clone, Debug)] -#[pyclass] -pub struct StarknetSimulationParameters { - /// Address of the sending account - #[pyo3(get)] - pub caller: String, - /// Address of the receiving account/contract - #[pyo3(get)] - pub to: String, - /// Calldata - #[pyo3(get)] - pub data: Vec, - /// The contract function/entry point to call e.g. "transfer" - pub entry_point: String, - #[pyo3(get)] - /// Starknet state overrides. - /// Will be merged with the existing state. Will take effect only for current simulation. - /// Must be given as a contract address to its variable override map. - pub overrides: Option>>, - /// Limit of gas to be used by the transaction - #[pyo3(get)] - pub gas_limit: Option, - /// The block number to be used by the transaction. This is independent of the states block. - #[pyo3(get)] - pub block_number: u64, -} - -#[pymethods] -impl StarknetSimulationParameters { - #[new] - pub fn new( - caller: String, - to: String, - data: Vec, - entry_point: String, - block_number: u64, - overrides: Option>>, - gas_limit: Option, - ) -> Self { - Self { caller, to, data, entry_point, overrides, gas_limit, block_number } - } -} - -impl From for SimulationParameters { - fn from(value: StarknetSimulationParameters) -> Self { - Self { - caller: address_str(&value.caller).expect("should be valid address"), - to: address_str(&value.to).expect("should be valid address"), - data: value - .data - .into_iter() - .map(Felt252::from) - .collect(), - entry_point: value.entry_point, - overrides: value - .overrides - .map(python_overrides_to_rust), - gas_limit: value.gas_limit, - block_number: value.block_number, - } - } -} - -/// Starknet transaction simulation result. -#[pyclass] -#[derive(Clone, Debug)] -pub struct StarknetSimulationResult { - /// Output of transaction execution - #[pyo3(get)] - pub result: Vec, - /// State changes caused by the transaction - #[pyo3(get)] - pub states_updates: HashMap>, - /// Gas used by the transaction (already reduced by the refunded gas) - #[pyo3(get)] - pub gas_used: u128, -} - -impl From for StarknetSimulationResult { - fn from(value: SimulationResult) -> Self { - Self { - result: value - .result - .into_iter() - .map(|felt| felt.to_biguint()) - .collect(), - states_updates: rust_overrides_to_python(value.state_updates), - gas_used: value.gas_used, - } - } -} - -/// Contract override for simulation engine. -/// -/// For example to override an ERC20 contract to a standardized implementation. -#[pyclass] -#[derive(Clone, Debug)] -pub struct StarknetContractOverride { - /// Address of the contract to override represented as a hexadecimal string. - #[pyo3(get)] - pub address: String, - /// Class hash of the overriden contract code represented as a hexadecimal string. - #[pyo3(get)] - pub class_hash: String, - /// Path to contract source code - /// - /// Supports .casm (Cairo 0) and .json () files. - #[pyo3(get)] - pub path: Option, -} - -#[pymethods] -impl StarknetContractOverride { - #[new] - pub fn new(address: String, class_hash: String, path: Option) -> Self { - Self { address, class_hash, path } - } -} - -impl From for RustContractOverride { - fn from(contract_override: StarknetContractOverride) -> Self { - let StarknetContractOverride { address, class_hash, path } = contract_override; - - RustContractOverride::new( - address_str(&address).expect("should be valid address"), - class_hash_str(&class_hash).expect("should be valid class hash"), - path, - ) - } -} - -/// Details of a Starknet simulation error. -#[pyclass] -#[derive(Debug)] -pub(crate) struct StarknetSimulationErrorDetails { - #[pyo3(get)] - pub reason: String, -} - -#[pymethods] -impl StarknetSimulationErrorDetails { - fn __repr__(&self) -> String { - format!("SimulationError(reason={})", self.reason) - } -} - -impl From for PyErr { - fn from(err: StarknetSimulationErrorDetails) -> PyErr { - PyRuntimeError::new_err(err) - } -} - -// This indirection is needed cause SimulationError -// is defined in an external create -impl From for StarknetSimulationErrorDetails { - fn from(err: SimulationError) -> Self { - StarknetSimulationErrorDetails { reason: err.to_string() } - } -} diff --git a/src/evm/tycho_models.rs b/src/evm/tycho_models.rs index 712d16b9..1ff75941 100644 --- a/src/evm/tycho_models.rs +++ b/src/evm/tycho_models.rs @@ -118,7 +118,6 @@ impl BlockAccountChanges { pub enum Chain { #[default] Ethereum, - Starknet, ZkSync, } diff --git a/src/lib.rs b/src/lib.rs index 3b2da18b..595d66f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,14 +23,4 @@ pub mod models; pub mod protocol; pub mod safe_math; pub mod serde_helpers; - -// #[cfg(feature = "starknet")] -// pub mod starknet_simulation; pub mod u256_num; - -// #[cfg(feature = "starknet")] -// pub use rpc_state_reader; -// #[cfg(feature = "starknet")] -// pub use starknet_api; -// #[cfg(feature = "starknet")] -// pub use starknet_in_rust; diff --git a/src/tests/mod.rs b/src/tests/mod.rs deleted file mode 100644 index fad3dd63..00000000 --- a/src/tests/mod.rs +++ /dev/null @@ -1 +0,0 @@ -mod starknet; diff --git a/src/tests/starknet/mod.rs b/src/tests/starknet/mod.rs deleted file mode 100644 index 7ba543ec..00000000 --- a/src/tests/starknet/mod.rs +++ /dev/null @@ -1 +0,0 @@ -// mod test_starknet_simulation; diff --git a/src/tests/starknet/resources/fibonacci.cairo b/src/tests/starknet/resources/fibonacci.cairo deleted file mode 100644 index 14544914..00000000 --- a/src/tests/starknet/resources/fibonacci.cairo +++ /dev/null @@ -1,18 +0,0 @@ -%lang starknet - -@external -func main() { - // Call fib(1, 1, 10). - let result: felt = fib(1, 1, 500); - ret; -} - -func fib(first_element, second_element, n) -> (res: felt) { - jmp fib_body if n != 0; - tempvar result = second_element; - return (second_element,); - - fib_body: - tempvar y = first_element + second_element; - return fib(second_element, y, n - 1); -} \ No newline at end of file diff --git a/src/tests/starknet/resources/fibonacci.casm b/src/tests/starknet/resources/fibonacci.casm deleted file mode 100644 index 1895bffd..00000000 --- a/src/tests/starknet/resources/fibonacci.casm +++ /dev/null @@ -1,492 +0,0 @@ -{ - "prime": "0x800000000000011000000000000000000000000000000000000000000000001", - "compiler_version": "1.1.0", - "bytecode": [ - "0xa0680017fff8000", - "0x7", - "0x482680017ffa8000", - "0xfffffffffffffffffffffffffffff7a4", - "0x400280007ff97fff", - "0x10780017fff7fff", - "0xa7", - "0x4825800180007ffa", - "0x85c", - "0x400280007ff97fff", - "0x480a7ffc7fff8000", - "0x480a7ffd7fff8000", - "0x1104800180018000", - "0xaf", - "0x482680017ff98000", - "0x1", - "0x20680017fff7ffd", - "0x8e", - "0x48127ffb7fff8000", - "0x48127ffb7fff8000", - "0x1104800180018000", - "0xa7", - "0x20680017fff7ffe", - "0x7a", - "0x48127ffc7fff8000", - "0x48127ffc7fff8000", - "0x1104800180018000", - "0xa1", - "0x20680017fff7ffe", - "0x66", - "0x48307ffc80007ffd", - "0x4824800180007fff", - "0x0", - "0x20680017fff7fff", - "0x4", - "0x10780017fff7fff", - "0x6", - "0x480680017fff8000", - "0x0", - "0x10780017fff7fff", - "0x4", - "0x480680017fff8000", - "0x1", - "0x480680017fff8000", - "0x1", - "0x48307ffe80007fff", - "0x20680017fff7fff", - "0x43", - "0x1104800180018000", - "0xfd", - "0x482480017fff8000", - "0xfc", - "0x480080007fff8000", - "0xa0680017fff8000", - "0x9", - "0x4824800180007fc4", - "0x0", - "0x482480017fff8000", - "0x100000000000000000000000000000000", - "0x400080007fd37fff", - "0x10780017fff7fff", - "0x26", - "0x4824800180007fc4", - "0x0", - "0x400080007fd47fff", - "0x482480017fd48000", - "0x1", - "0x48127ffe7fff8000", - "0x48127fd17fff8000", - "0x48127fe17fff8000", - "0x48127ff07fff8000", - "0x1104800180018000", - "0x9b", - "0x20680017fff7ffd", - "0x11", - "0x40780017fff7fff", - "0x1", - "0x48127ffe7fff8000", - "0x48127ffe7fff8000", - "0x48127ffd7fff8000", - "0x1104800180018000", - "0xd6", - "0x48127ff37fff8000", - "0x48127ff37fff8000", - "0x480a7ffb7fff8000", - "0x480680017fff8000", - "0x0", - "0x48127ffa7fff8000", - "0x48127ffa7fff8000", - "0x208b7fff7fff7ffe", - "0x48127ffb7fff8000", - "0x48127ffb7fff8000", - "0x480a7ffb7fff8000", - "0x480680017fff8000", - "0x1", - "0x48127ffa7fff8000", - "0x48127ffa7fff8000", - "0x208b7fff7fff7ffe", - "0x40780017fff7fff", - "0x1", - "0x480680017fff8000", - "0x4f7574206f6620676173", - "0x400080007ffe7fff", - "0x482480017fd18000", - "0x1", - "0x48127fbf7fff8000", - "0x480a7ffb7fff8000", - "0x480680017fff8000", - "0x1", - "0x48127ffa7fff8000", - "0x482480017ff98000", - "0x1", - "0x208b7fff7fff7ffe", - "0x480a7ffb7fff8000", - "0x1104800180018000", - "0xb9", - "0x40780017fff7fff", - "0x1", - "0x480680017fff8000", - "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", - "0x400080007ffe7fff", - "0x48127fd47fff8000", - "0x48127fc27fff8000", - "0x48127ffb7fff8000", - "0x480680017fff8000", - "0x1", - "0x48127ffa7fff8000", - "0x482480017ff98000", - "0x1", - "0x208b7fff7fff7ffe", - "0x40780017fff7fff", - "0x1", - "0x480680017fff8000", - "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", - "0x400080007ffe7fff", - "0x48127fdd7fff8000", - "0x48127fcb7fff8000", - "0x480a7ffb7fff8000", - "0x480680017fff8000", - "0x1", - "0x48127ffa7fff8000", - "0x482480017ff98000", - "0x1", - "0x208b7fff7fff7ffe", - "0x40780017fff7fff", - "0x1", - "0x480680017fff8000", - "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", - "0x400080007ffe7fff", - "0x48127fed7fff8000", - "0x48127fdb7fff8000", - "0x480a7ffb7fff8000", - "0x480680017fff8000", - "0x1", - "0x48127ffa7fff8000", - "0x482480017ff98000", - "0x1", - "0x208b7fff7fff7ffe", - "0x40780017fff7fff", - "0x1", - "0x480680017fff8000", - "0x496e70757420746f6f2073686f727420666f7220617267756d656e7473", - "0x400080007ffe7fff", - "0x48127ffd7fff8000", - "0x48127feb7fff8000", - "0x480a7ffb7fff8000", - "0x480680017fff8000", - "0x1", - "0x48127ffa7fff8000", - "0x482480017ff98000", - "0x1", - "0x208b7fff7fff7ffe", - "0x40780017fff7fff", - "0x1", - "0x480680017fff8000", - "0x4f7574206f6620676173", - "0x400080007ffe7fff", - "0x482680017ff98000", - "0x1", - "0x480a7ffa7fff8000", - "0x480a7ffb7fff8000", - "0x480680017fff8000", - "0x1", - "0x48127ffa7fff8000", - "0x482480017ff98000", - "0x1", - "0x208b7fff7fff7ffe", - "0x48297ffc80007ffd", - "0x20680017fff7fff", - "0x4", - "0x10780017fff7fff", - "0xa", - "0x482680017ffc8000", - "0x1", - "0x480a7ffd7fff8000", - "0x480680017fff8000", - "0x0", - "0x480a7ffc7fff8000", - "0x10780017fff7fff", - "0x8", - "0x480a7ffc7fff8000", - "0x480a7ffd7fff8000", - "0x480680017fff8000", - "0x1", - "0x480680017fff8000", - "0x0", - "0x48127ffc7fff8000", - "0x48127ffc7fff8000", - "0x20680017fff7ffc", - "0x9", - "0x480080007ffd8000", - "0x48127ffd7fff8000", - "0x48127ffd7fff8000", - "0x480680017fff8000", - "0x0", - "0x48127ffc7fff8000", - "0x208b7fff7fff7ffe", - "0x40780017fff7fff", - "0x1", - "0x48127ffd7fff8000", - "0x48127ffd7fff8000", - "0x480680017fff8000", - "0x1", - "0x480680017fff8000", - "0x0", - "0x208b7fff7fff7ffe", - "0x1104800180018000", - "0x4b", - "0x482480017fff8000", - "0x4a", - "0x480080007fff8000", - "0xa0680017fff8000", - "0x9", - "0x4825800180007ffa", - "0xa0a", - "0x482480017fff8000", - "0x100000000000000000000000000000000", - "0x400280007ff97fff", - "0x10780017fff7fff", - "0x2a", - "0x4825800180007ffa", - "0xa0a", - "0x400280007ff97fff", - "0x482680017ff98000", - "0x1", - "0x20780017fff7ffd", - "0x7", - "0x48127fff7fff8000", - "0x48127ffd7fff8000", - "0x480a7ffb7fff8000", - "0x10780017fff7fff", - "0xf", - "0x48127fff7fff8000", - "0x48127ffd7fff8000", - "0x480a7ffc7fff8000", - "0x482a7ffc7ffb8000", - "0x4825800180007ffd", - "0x1", - "0x1104800180018000", - "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe1", - "0x20680017fff7ffd", - "0xd", - "0x48127ffb7fff8000", - "0x48127ffb7fff8000", - "0x48127ffd7fff8000", - "0x48127ffd7fff8000", - "0x48127ffd7fff8000", - "0x480680017fff8000", - "0x0", - "0x480680017fff8000", - "0x0", - "0x48127ffb7fff8000", - "0x208b7fff7fff7ffe", - "0x48127ffb7fff8000", - "0x48127ffb7fff8000", - "0x480680017fff8000", - "0x1", - "0x48127ffb7fff8000", - "0x48127ffb7fff8000", - "0x208b7fff7fff7ffe", - "0x40780017fff7fff", - "0x1", - "0x480680017fff8000", - "0x4f7574206f6620676173", - "0x400080007ffe7fff", - "0x482680017ff98000", - "0x1", - "0x480a7ffa7fff8000", - "0x480680017fff8000", - "0x1", - "0x48127ffb7fff8000", - "0x482480017ffa8000", - "0x1", - "0x208b7fff7fff7ffe", - "0x400380007ffd7ffb", - "0x480a7ffc7fff8000", - "0x482680017ffd8000", - "0x1", - "0x208b7fff7fff7ffe", - "0x480a7ffd7fff8000", - "0x208b7fff7fff7ffe" - ], - "hints": [ - [ - 0, - [ - { - "TestLessThanOrEqual": { - "lhs": { - "Immediate": "0x85c" - }, - "rhs": { - "Deref": { - "register": "FP", - "offset": -6 - } - }, - "dst": { - "register": "AP", - "offset": 0 - } - } - } - ] - ], - [ - 53, - [ - { - "TestLessThanOrEqual": { - "lhs": { - "Immediate": "0x0" - }, - "rhs": { - "Deref": { - "register": "AP", - "offset": -59 - } - }, - "dst": { - "register": "AP", - "offset": 0 - } - } - } - ] - ], - [ - 75, - [ - { - "AllocSegment": { - "dst": { - "register": "AP", - "offset": 0 - } - } - } - ] - ], - [ - 98, - [ - { - "AllocSegment": { - "dst": { - "register": "AP", - "offset": 0 - } - } - } - ] - ], - [ - 116, - [ - { - "AllocSegment": { - "dst": { - "register": "AP", - "offset": 0 - } - } - } - ] - ], - [ - 130, - [ - { - "AllocSegment": { - "dst": { - "register": "AP", - "offset": 0 - } - } - } - ] - ], - [ - 144, - [ - { - "AllocSegment": { - "dst": { - "register": "AP", - "offset": 0 - } - } - } - ] - ], - [ - 158, - [ - { - "AllocSegment": { - "dst": { - "register": "AP", - "offset": 0 - } - } - } - ] - ], - [ - 172, - [ - { - "AllocSegment": { - "dst": { - "register": "AP", - "offset": 0 - } - } - } - ] - ], - [ - 231, - [ - { - "TestLessThanOrEqual": { - "lhs": { - "Immediate": "0xa0a" - }, - "rhs": { - "Deref": { - "register": "FP", - "offset": -6 - } - }, - "dst": { - "register": "AP", - "offset": 0 - } - } - } - ] - ], - [ - 280, - [ - { - "AllocSegment": { - "dst": { - "register": "AP", - "offset": 0 - } - } - } - ] - ] - ], - "entry_points_by_type": { - "EXTERNAL": [ - { - "selector": "0x112e35f48499939272000bd72eb840e502ca4c3aefa8800992e8defb746e0c9", - "offset": 0, - "builtins": [ - "range_check" - ] - } - ], - "L1_HANDLER": [], - "CONSTRUCTOR": [] - } -} \ No newline at end of file diff --git a/src/tests/starknet/resources/fibonacci.json b/src/tests/starknet/resources/fibonacci.json deleted file mode 100644 index 707db5d9..00000000 --- a/src/tests/starknet/resources/fibonacci.json +++ /dev/null @@ -1,1729 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "name": "main", - "outputs": [], - "type": "function" - } - ], - "entry_points_by_type": { - "CONSTRUCTOR": [], - "EXTERNAL": [ - { - "offset": "0x9", - "selector": "0xe2054f8a912367e38a22ce773328ff8aabf8082c4120bad9ef085e1dbf29a7" - } - ], - "L1_HANDLER": [] - }, - "program": { - "attributes": [], - "builtins": [ - "range_check" - ], - "compiler_version": "0.10.3", - "data": [ - "0x480680017fff8000", - "0x1", - "0x480680017fff8000", - "0x1", - "0x480680017fff8000", - "0x1f4", - "0x1104800180018000", - "0xe", - "0x208b7fff7fff7ffe", - "0x402b7ffd7ffc7ffd", - "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff7", - "0x40780017fff7fff", - "0x1", - "0x480280007ffb8000", - "0x480280017ffb8000", - "0x480680017fff8000", - "0x0", - "0x48127ffc7fff8000", - "0x208b7fff7fff7ffe", - "0x20780017fff7ffd", - "0x5", - "0x480a7ffc7fff8000", - "0x480a7ffc7fff8000", - "0x208b7fff7fff7ffe", - "0x482a7ffc7ffb8000", - "0x480a7ffc7fff8000", - "0x48127ffe7fff8000", - "0x482680017ffd8000", - "0x800000000000011000000000000000000000000000000000000000000000000", - "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff7", - "0x208b7fff7fff7ffe" - ], - "debug_info": { - "file_contents": { - "autogen/starknet/arg_processor/01cba52f8515996bb9d7070bde81ff39281d096d7024a558efcba6e1fd2402cf.cairo": "assert [cast(fp + (-4), felt*)] = __calldata_actual_size;\n", - "autogen/starknet/external/main/3f2c77ab4e9866f148094b3f3c2497496b7ce8700b8370e7f1bc10658a33d640.cairo": "let syscall_ptr = [cast([cast(fp + (-5), felt**)] + 0, felt*)];\n", - "autogen/starknet/external/main/93099bea078b47105ec080392b498d5fa602cf51e6076f4584216f16f5b4c273.cairo": "return (syscall_ptr,range_check_ptr,retdata_size,retdata);\n", - "autogen/starknet/external/main/dea87e21810c5054c7ac0edc4fbbd20c423f211a2599b2da1352b95a8ad2b5c7.cairo": "let ret_value = __wrapped_func{}();\n%{ memory[ap] = segments.add() %} // Allocate memory for return value.\ntempvar retdata: felt*;\nlet retdata_size = 0;\n", - "autogen/starknet/external/main/fd099223670ab5d428127810c2328d37c65c29951c7abc7cebaa651b40be0a6a.cairo": "let range_check_ptr = [cast([cast(fp + (-5), felt**)] + 1, felt*)];\n" - }, - "instruction_locations": { - "0": { - "accessible_scopes": [ - "__main__", - "__main__", - "__main__.main" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 29, - "end_line": 6, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 28, - "start_line": 6 - } - }, - "2": { - "accessible_scopes": [ - "__main__", - "__main__", - "__main__.main" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 32, - "end_line": 6, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 31, - "start_line": 6 - } - }, - "4": { - "accessible_scopes": [ - "__main__", - "__main__", - "__main__.main" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 37, - "end_line": 6, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 34, - "start_line": 6 - } - }, - "6": { - "accessible_scopes": [ - "__main__", - "__main__", - "__main__.main" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 38, - "end_line": 6, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 24, - "start_line": 6 - } - }, - "8": { - "accessible_scopes": [ - "__main__", - "__main__", - "__main__.main" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 8, - "end_line": 7, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 5, - "start_line": 7 - } - }, - "9": { - "accessible_scopes": [ - "__main__", - "__main__", - "__wrappers__", - "__wrappers__.main" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 58, - "end_line": 1, - "input_file": { - "filename": "autogen/starknet/arg_processor/01cba52f8515996bb9d7070bde81ff39281d096d7024a558efcba6e1fd2402cf.cairo" - }, - "parent_location": [ - { - "end_col": 10, - "end_line": 4, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 6, - "start_line": 4 - }, - "While handling calldata of" - ], - "start_col": 1, - "start_line": 1 - } - }, - "10": { - "accessible_scopes": [ - "__main__", - "__main__", - "__wrappers__", - "__wrappers__.main" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 10, - "end_line": 4, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 6, - "start_line": 4 - } - }, - "12": { - "accessible_scopes": [ - "__main__", - "__main__", - "__wrappers__", - "__wrappers__.main" - ], - "flow_tracking_data": null, - "hints": [ - { - "location": { - "end_col": 34, - "end_line": 2, - "input_file": { - "filename": "autogen/starknet/external/main/dea87e21810c5054c7ac0edc4fbbd20c423f211a2599b2da1352b95a8ad2b5c7.cairo" - }, - "parent_location": [ - { - "end_col": 10, - "end_line": 4, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 6, - "start_line": 4 - }, - "While constructing the external wrapper for:" - ], - "start_col": 1, - "start_line": 2 - }, - "n_prefix_newlines": 0 - } - ], - "inst": { - "end_col": 24, - "end_line": 3, - "input_file": { - "filename": "autogen/starknet/external/main/dea87e21810c5054c7ac0edc4fbbd20c423f211a2599b2da1352b95a8ad2b5c7.cairo" - }, - "parent_location": [ - { - "end_col": 10, - "end_line": 4, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 6, - "start_line": 4 - }, - "While constructing the external wrapper for:" - ], - "start_col": 1, - "start_line": 3 - } - }, - "14": { - "accessible_scopes": [ - "__main__", - "__main__", - "__wrappers__", - "__wrappers__.main" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 63, - "end_line": 1, - "input_file": { - "filename": "autogen/starknet/external/main/3f2c77ab4e9866f148094b3f3c2497496b7ce8700b8370e7f1bc10658a33d640.cairo" - }, - "parent_location": [ - { - "end_col": 10, - "end_line": 4, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "parent_location": [ - { - "end_col": 20, - "end_line": 1, - "input_file": { - "filename": "autogen/starknet/external/main/93099bea078b47105ec080392b498d5fa602cf51e6076f4584216f16f5b4c273.cairo" - }, - "parent_location": [ - { - "end_col": 10, - "end_line": 4, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 6, - "start_line": 4 - }, - "While constructing the external wrapper for:" - ], - "start_col": 9, - "start_line": 1 - }, - "While expanding the reference 'syscall_ptr' in:" - ], - "start_col": 6, - "start_line": 4 - }, - "While constructing the external wrapper for:" - ], - "start_col": 19, - "start_line": 1 - } - }, - "15": { - "accessible_scopes": [ - "__main__", - "__main__", - "__wrappers__", - "__wrappers__.main" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 67, - "end_line": 1, - "input_file": { - "filename": "autogen/starknet/external/main/fd099223670ab5d428127810c2328d37c65c29951c7abc7cebaa651b40be0a6a.cairo" - }, - "parent_location": [ - { - "end_col": 10, - "end_line": 4, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "parent_location": [ - { - "end_col": 36, - "end_line": 1, - "input_file": { - "filename": "autogen/starknet/external/main/93099bea078b47105ec080392b498d5fa602cf51e6076f4584216f16f5b4c273.cairo" - }, - "parent_location": [ - { - "end_col": 10, - "end_line": 4, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 6, - "start_line": 4 - }, - "While constructing the external wrapper for:" - ], - "start_col": 21, - "start_line": 1 - }, - "While expanding the reference 'range_check_ptr' in:" - ], - "start_col": 6, - "start_line": 4 - }, - "While constructing the external wrapper for:" - ], - "start_col": 23, - "start_line": 1 - } - }, - "16": { - "accessible_scopes": [ - "__main__", - "__main__", - "__wrappers__", - "__wrappers__.main" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 21, - "end_line": 4, - "input_file": { - "filename": "autogen/starknet/external/main/dea87e21810c5054c7ac0edc4fbbd20c423f211a2599b2da1352b95a8ad2b5c7.cairo" - }, - "parent_location": [ - { - "end_col": 10, - "end_line": 4, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "parent_location": [ - { - "end_col": 49, - "end_line": 1, - "input_file": { - "filename": "autogen/starknet/external/main/93099bea078b47105ec080392b498d5fa602cf51e6076f4584216f16f5b4c273.cairo" - }, - "parent_location": [ - { - "end_col": 10, - "end_line": 4, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 6, - "start_line": 4 - }, - "While constructing the external wrapper for:" - ], - "start_col": 37, - "start_line": 1 - }, - "While expanding the reference 'retdata_size' in:" - ], - "start_col": 6, - "start_line": 4 - }, - "While constructing the external wrapper for:" - ], - "start_col": 20, - "start_line": 4 - } - }, - "18": { - "accessible_scopes": [ - "__main__", - "__main__", - "__wrappers__", - "__wrappers__.main" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 16, - "end_line": 3, - "input_file": { - "filename": "autogen/starknet/external/main/dea87e21810c5054c7ac0edc4fbbd20c423f211a2599b2da1352b95a8ad2b5c7.cairo" - }, - "parent_location": [ - { - "end_col": 10, - "end_line": 4, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "parent_location": [ - { - "end_col": 57, - "end_line": 1, - "input_file": { - "filename": "autogen/starknet/external/main/93099bea078b47105ec080392b498d5fa602cf51e6076f4584216f16f5b4c273.cairo" - }, - "parent_location": [ - { - "end_col": 10, - "end_line": 4, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 6, - "start_line": 4 - }, - "While constructing the external wrapper for:" - ], - "start_col": 50, - "start_line": 1 - }, - "While expanding the reference 'retdata' in:" - ], - "start_col": 6, - "start_line": 4 - }, - "While constructing the external wrapper for:" - ], - "start_col": 9, - "start_line": 3 - } - }, - "19": { - "accessible_scopes": [ - "__main__", - "__main__", - "__wrappers__", - "__wrappers__.main" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 59, - "end_line": 1, - "input_file": { - "filename": "autogen/starknet/external/main/93099bea078b47105ec080392b498d5fa602cf51e6076f4584216f16f5b4c273.cairo" - }, - "parent_location": [ - { - "end_col": 10, - "end_line": 4, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 6, - "start_line": 4 - }, - "While constructing the external wrapper for:" - ], - "start_col": 1, - "start_line": 1 - } - }, - "20": { - "accessible_scopes": [ - "__main__", - "__main__.fib" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 27, - "end_line": 11, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 5, - "start_line": 11 - } - }, - "22": { - "accessible_scopes": [ - "__main__", - "__main__.fib" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 39, - "end_line": 10, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "parent_location": [ - { - "end_col": 36, - "end_line": 12, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 22, - "start_line": 12 - }, - "While expanding the reference 'second_element' in:" - ], - "start_col": 25, - "start_line": 10 - } - }, - "23": { - "accessible_scopes": [ - "__main__", - "__main__.fib" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 39, - "end_line": 10, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "parent_location": [ - { - "end_col": 27, - "end_line": 13, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 13, - "start_line": 13 - }, - "While expanding the reference 'second_element' in:" - ], - "start_col": 25, - "start_line": 10 - } - }, - "24": { - "accessible_scopes": [ - "__main__", - "__main__.fib" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 30, - "end_line": 13, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 5, - "start_line": 13 - } - }, - "25": { - "accessible_scopes": [ - "__main__", - "__main__.fib" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 47, - "end_line": 16, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 17, - "start_line": 16 - } - }, - "26": { - "accessible_scopes": [ - "__main__", - "__main__.fib" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 39, - "end_line": 10, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "parent_location": [ - { - "end_col": 30, - "end_line": 17, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 16, - "start_line": 17 - }, - "While expanding the reference 'second_element' in:" - ], - "start_col": 25, - "start_line": 10 - } - }, - "27": { - "accessible_scopes": [ - "__main__", - "__main__.fib" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 14, - "end_line": 16, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "parent_location": [ - { - "end_col": 33, - "end_line": 17, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 32, - "start_line": 17 - }, - "While expanding the reference 'y' in:" - ], - "start_col": 13, - "start_line": 16 - } - }, - "28": { - "accessible_scopes": [ - "__main__", - "__main__.fib" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 40, - "end_line": 17, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 35, - "start_line": 17 - } - }, - "30": { - "accessible_scopes": [ - "__main__", - "__main__.fib" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 41, - "end_line": 17, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 12, - "start_line": 17 - } - }, - "32": { - "accessible_scopes": [ - "__main__", - "__main__.fib" - ], - "flow_tracking_data": null, - "hints": [], - "inst": { - "end_col": 42, - "end_line": 17, - "input_file": { - "filename": "../starknet_tendermint_sequencer/programs/fibonacci.cairo" - }, - "start_col": 5, - "start_line": 17 - } - } - } - }, - "hints": { - "12": [ - { - "accessible_scopes": [ - "__main__", - "__main__", - "__wrappers__", - "__wrappers__.main" - ], - "code": "memory[ap] = segments.add()", - "flow_tracking_data": { - "ap_tracking": { - "group": 3, - "offset": 0 - }, - "reference_ids": {} - } - } - ] - }, - "identifiers": { - "__main__.fib": { - "decorators": [], - "pc": 20, - "type": "function" - }, - "__main__.fib.Args": { - "full_name": "__main__.fib.Args", - "members": { - "first_element": { - "cairo_type": "felt", - "offset": 0 - }, - "n": { - "cairo_type": "felt", - "offset": 2 - }, - "second_element": { - "cairo_type": "felt", - "offset": 1 - } - }, - "size": 3, - "type": "struct" - }, - "__main__.fib.ImplicitArgs": { - "full_name": "__main__.fib.ImplicitArgs", - "members": {}, - "size": 0, - "type": "struct" - }, - "__main__.fib.Return": { - "cairo_type": "(res: felt)", - "type": "type_definition" - }, - "__main__.fib.SIZEOF_LOCALS": { - "type": "const", - "value": 0 - }, - "__main__.fib.fib_body": { - "pc": 25, - "type": "label" - }, - "__main__.main": { - "decorators": [ - "external" - ], - "pc": 0, - "type": "function" - }, - "__main__.main.Args": { - "full_name": "__main__.main.Args", - "members": {}, - "size": 0, - "type": "struct" - }, - "__main__.main.ImplicitArgs": { - "full_name": "__main__.main.ImplicitArgs", - "members": {}, - "size": 0, - "type": "struct" - }, - "__main__.main.Return": { - "cairo_type": "()", - "type": "type_definition" - }, - "__main__.main.SIZEOF_LOCALS": { - "type": "const", - "value": 0 - }, - "__wrappers__.main": { - "decorators": [ - "external" - ], - "pc": 9, - "type": "function" - }, - "__wrappers__.main.Args": { - "full_name": "__wrappers__.main.Args", - "members": {}, - "size": 0, - "type": "struct" - }, - "__wrappers__.main.ImplicitArgs": { - "full_name": "__wrappers__.main.ImplicitArgs", - "members": {}, - "size": 0, - "type": "struct" - }, - "__wrappers__.main.Return": { - "cairo_type": "(syscall_ptr: felt, range_check_ptr: felt, size: felt, retdata: felt*)", - "type": "type_definition" - }, - "__wrappers__.main.SIZEOF_LOCALS": { - "type": "const", - "value": 0 - }, - "__wrappers__.main.__wrapped_func": { - "destination": "__main__.main", - "type": "alias" - }, - "__wrappers__.main_encode_return.memcpy": { - "destination": "starkware.cairo.common.memcpy.memcpy", - "type": "alias" - }, - "starkware.cairo.common.bool.FALSE": { - "type": "const", - "value": 0 - }, - "starkware.cairo.common.bool.TRUE": { - "type": "const", - "value": 1 - }, - "starkware.cairo.common.cairo_builtins.BitwiseBuiltin": { - "full_name": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin", - "members": { - "x": { - "cairo_type": "felt", - "offset": 0 - }, - "x_and_y": { - "cairo_type": "felt", - "offset": 2 - }, - "x_or_y": { - "cairo_type": "felt", - "offset": 4 - }, - "x_xor_y": { - "cairo_type": "felt", - "offset": 3 - }, - "y": { - "cairo_type": "felt", - "offset": 1 - } - }, - "size": 5, - "type": "struct" - }, - "starkware.cairo.common.cairo_builtins.EcOpBuiltin": { - "full_name": "starkware.cairo.common.cairo_builtins.EcOpBuiltin", - "members": { - "m": { - "cairo_type": "felt", - "offset": 4 - }, - "p": { - "cairo_type": "starkware.cairo.common.ec_point.EcPoint", - "offset": 0 - }, - "q": { - "cairo_type": "starkware.cairo.common.ec_point.EcPoint", - "offset": 2 - }, - "r": { - "cairo_type": "starkware.cairo.common.ec_point.EcPoint", - "offset": 5 - } - }, - "size": 7, - "type": "struct" - }, - "starkware.cairo.common.cairo_builtins.EcPoint": { - "destination": "starkware.cairo.common.ec_point.EcPoint", - "type": "alias" - }, - "starkware.cairo.common.cairo_builtins.HashBuiltin": { - "full_name": "starkware.cairo.common.cairo_builtins.HashBuiltin", - "members": { - "result": { - "cairo_type": "felt", - "offset": 2 - }, - "x": { - "cairo_type": "felt", - "offset": 0 - }, - "y": { - "cairo_type": "felt", - "offset": 1 - } - }, - "size": 3, - "type": "struct" - }, - "starkware.cairo.common.cairo_builtins.KeccakBuiltin": { - "full_name": "starkware.cairo.common.cairo_builtins.KeccakBuiltin", - "members": { - "input": { - "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", - "offset": 0 - }, - "output": { - "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", - "offset": 8 - } - }, - "size": 16, - "type": "struct" - }, - "starkware.cairo.common.cairo_builtins.KeccakBuiltinState": { - "destination": "starkware.cairo.common.keccak_state.KeccakBuiltinState", - "type": "alias" - }, - "starkware.cairo.common.cairo_builtins.SignatureBuiltin": { - "full_name": "starkware.cairo.common.cairo_builtins.SignatureBuiltin", - "members": { - "message": { - "cairo_type": "felt", - "offset": 1 - }, - "pub_key": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 2, - "type": "struct" - }, - "starkware.cairo.common.dict_access.DictAccess": { - "full_name": "starkware.cairo.common.dict_access.DictAccess", - "members": { - "key": { - "cairo_type": "felt", - "offset": 0 - }, - "new_value": { - "cairo_type": "felt", - "offset": 2 - }, - "prev_value": { - "cairo_type": "felt", - "offset": 1 - } - }, - "size": 3, - "type": "struct" - }, - "starkware.cairo.common.ec_point.EcPoint": { - "full_name": "starkware.cairo.common.ec_point.EcPoint", - "members": { - "x": { - "cairo_type": "felt", - "offset": 0 - }, - "y": { - "cairo_type": "felt", - "offset": 1 - } - }, - "size": 2, - "type": "struct" - }, - "starkware.cairo.common.hash.HashBuiltin": { - "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", - "type": "alias" - }, - "starkware.cairo.common.keccak_state.KeccakBuiltinState": { - "full_name": "starkware.cairo.common.keccak_state.KeccakBuiltinState", - "members": { - "s0": { - "cairo_type": "felt", - "offset": 0 - }, - "s1": { - "cairo_type": "felt", - "offset": 1 - }, - "s2": { - "cairo_type": "felt", - "offset": 2 - }, - "s3": { - "cairo_type": "felt", - "offset": 3 - }, - "s4": { - "cairo_type": "felt", - "offset": 4 - }, - "s5": { - "cairo_type": "felt", - "offset": 5 - }, - "s6": { - "cairo_type": "felt", - "offset": 6 - }, - "s7": { - "cairo_type": "felt", - "offset": 7 - } - }, - "size": 8, - "type": "struct" - }, - "starkware.cairo.common.math.FALSE": { - "destination": "starkware.cairo.common.bool.FALSE", - "type": "alias" - }, - "starkware.cairo.common.math.TRUE": { - "destination": "starkware.cairo.common.bool.TRUE", - "type": "alias" - }, - "starkware.starknet.common.storage.ADDR_BOUND": { - "type": "const", - "value": -106710729501573572985208420194530329073740042555888586719489 - }, - "starkware.starknet.common.storage.MAX_STORAGE_ITEM_SIZE": { - "type": "const", - "value": 256 - }, - "starkware.starknet.common.storage.assert_250_bit": { - "destination": "starkware.cairo.common.math.assert_250_bit", - "type": "alias" - }, - "starkware.starknet.common.syscalls.CALL_CONTRACT_SELECTOR": { - "type": "const", - "value": 20853273475220472486191784820 - }, - "starkware.starknet.common.syscalls.CallContract": { - "full_name": "starkware.starknet.common.syscalls.CallContract", - "members": { - "request": { - "cairo_type": "starkware.starknet.common.syscalls.CallContractRequest", - "offset": 0 - }, - "response": { - "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", - "offset": 5 - } - }, - "size": 7, - "type": "struct" - }, - "starkware.starknet.common.syscalls.CallContractRequest": { - "full_name": "starkware.starknet.common.syscalls.CallContractRequest", - "members": { - "calldata": { - "cairo_type": "felt*", - "offset": 4 - }, - "calldata_size": { - "cairo_type": "felt", - "offset": 3 - }, - "contract_address": { - "cairo_type": "felt", - "offset": 1 - }, - "function_selector": { - "cairo_type": "felt", - "offset": 2 - }, - "selector": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 5, - "type": "struct" - }, - "starkware.starknet.common.syscalls.CallContractResponse": { - "full_name": "starkware.starknet.common.syscalls.CallContractResponse", - "members": { - "retdata": { - "cairo_type": "felt*", - "offset": 1 - }, - "retdata_size": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 2, - "type": "struct" - }, - "starkware.starknet.common.syscalls.DELEGATE_CALL_SELECTOR": { - "type": "const", - "value": 21167594061783206823196716140 - }, - "starkware.starknet.common.syscalls.DELEGATE_L1_HANDLER_SELECTOR": { - "type": "const", - "value": 23274015802972845247556842986379118667122 - }, - "starkware.starknet.common.syscalls.DEPLOY_SELECTOR": { - "type": "const", - "value": 75202468540281 - }, - "starkware.starknet.common.syscalls.Deploy": { - "full_name": "starkware.starknet.common.syscalls.Deploy", - "members": { - "request": { - "cairo_type": "starkware.starknet.common.syscalls.DeployRequest", - "offset": 0 - }, - "response": { - "cairo_type": "starkware.starknet.common.syscalls.DeployResponse", - "offset": 6 - } - }, - "size": 9, - "type": "struct" - }, - "starkware.starknet.common.syscalls.DeployRequest": { - "full_name": "starkware.starknet.common.syscalls.DeployRequest", - "members": { - "class_hash": { - "cairo_type": "felt", - "offset": 1 - }, - "constructor_calldata": { - "cairo_type": "felt*", - "offset": 4 - }, - "constructor_calldata_size": { - "cairo_type": "felt", - "offset": 3 - }, - "contract_address_salt": { - "cairo_type": "felt", - "offset": 2 - }, - "deploy_from_zero": { - "cairo_type": "felt", - "offset": 5 - }, - "selector": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 6, - "type": "struct" - }, - "starkware.starknet.common.syscalls.DeployResponse": { - "full_name": "starkware.starknet.common.syscalls.DeployResponse", - "members": { - "constructor_retdata": { - "cairo_type": "felt*", - "offset": 2 - }, - "constructor_retdata_size": { - "cairo_type": "felt", - "offset": 1 - }, - "contract_address": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 3, - "type": "struct" - }, - "starkware.starknet.common.syscalls.DictAccess": { - "destination": "starkware.cairo.common.dict_access.DictAccess", - "type": "alias" - }, - "starkware.starknet.common.syscalls.EMIT_EVENT_SELECTOR": { - "type": "const", - "value": 1280709301550335749748 - }, - "starkware.starknet.common.syscalls.EmitEvent": { - "full_name": "starkware.starknet.common.syscalls.EmitEvent", - "members": { - "data": { - "cairo_type": "felt*", - "offset": 4 - }, - "data_len": { - "cairo_type": "felt", - "offset": 3 - }, - "keys": { - "cairo_type": "felt*", - "offset": 2 - }, - "keys_len": { - "cairo_type": "felt", - "offset": 1 - }, - "selector": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 5, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GET_BLOCK_NUMBER_SELECTOR": { - "type": "const", - "value": 1448089106835523001438702345020786 - }, - "starkware.starknet.common.syscalls.GET_BLOCK_TIMESTAMP_SELECTOR": { - "type": "const", - "value": 24294903732626645868215235778792757751152 - }, - "starkware.starknet.common.syscalls.GET_CALLER_ADDRESS_SELECTOR": { - "type": "const", - "value": 94901967781393078444254803017658102643 - }, - "starkware.starknet.common.syscalls.GET_CONTRACT_ADDRESS_SELECTOR": { - "type": "const", - "value": 6219495360805491471215297013070624192820083 - }, - "starkware.starknet.common.syscalls.GET_SEQUENCER_ADDRESS_SELECTOR": { - "type": "const", - "value": 1592190833581991703053805829594610833820054387 - }, - "starkware.starknet.common.syscalls.GET_TX_INFO_SELECTOR": { - "type": "const", - "value": 1317029390204112103023 - }, - "starkware.starknet.common.syscalls.GET_TX_SIGNATURE_SELECTOR": { - "type": "const", - "value": 1448089128652340074717162277007973 - }, - "starkware.starknet.common.syscalls.GetBlockNumber": { - "full_name": "starkware.starknet.common.syscalls.GetBlockNumber", - "members": { - "request": { - "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberRequest", - "offset": 0 - }, - "response": { - "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberResponse", - "offset": 1 - } - }, - "size": 2, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetBlockNumberRequest": { - "full_name": "starkware.starknet.common.syscalls.GetBlockNumberRequest", - "members": { - "selector": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 1, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetBlockNumberResponse": { - "full_name": "starkware.starknet.common.syscalls.GetBlockNumberResponse", - "members": { - "block_number": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 1, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetBlockTimestamp": { - "full_name": "starkware.starknet.common.syscalls.GetBlockTimestamp", - "members": { - "request": { - "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", - "offset": 0 - }, - "response": { - "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", - "offset": 1 - } - }, - "size": 2, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetBlockTimestampRequest": { - "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", - "members": { - "selector": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 1, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetBlockTimestampResponse": { - "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", - "members": { - "block_timestamp": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 1, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetCallerAddress": { - "full_name": "starkware.starknet.common.syscalls.GetCallerAddress", - "members": { - "request": { - "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressRequest", - "offset": 0 - }, - "response": { - "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressResponse", - "offset": 1 - } - }, - "size": 2, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetCallerAddressRequest": { - "full_name": "starkware.starknet.common.syscalls.GetCallerAddressRequest", - "members": { - "selector": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 1, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetCallerAddressResponse": { - "full_name": "starkware.starknet.common.syscalls.GetCallerAddressResponse", - "members": { - "caller_address": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 1, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetContractAddress": { - "full_name": "starkware.starknet.common.syscalls.GetContractAddress", - "members": { - "request": { - "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressRequest", - "offset": 0 - }, - "response": { - "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressResponse", - "offset": 1 - } - }, - "size": 2, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetContractAddressRequest": { - "full_name": "starkware.starknet.common.syscalls.GetContractAddressRequest", - "members": { - "selector": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 1, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetContractAddressResponse": { - "full_name": "starkware.starknet.common.syscalls.GetContractAddressResponse", - "members": { - "contract_address": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 1, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetSequencerAddress": { - "full_name": "starkware.starknet.common.syscalls.GetSequencerAddress", - "members": { - "request": { - "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", - "offset": 0 - }, - "response": { - "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", - "offset": 1 - } - }, - "size": 2, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetSequencerAddressRequest": { - "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", - "members": { - "selector": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 1, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetSequencerAddressResponse": { - "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", - "members": { - "sequencer_address": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 1, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetTxInfo": { - "full_name": "starkware.starknet.common.syscalls.GetTxInfo", - "members": { - "request": { - "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoRequest", - "offset": 0 - }, - "response": { - "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoResponse", - "offset": 1 - } - }, - "size": 2, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetTxInfoRequest": { - "full_name": "starkware.starknet.common.syscalls.GetTxInfoRequest", - "members": { - "selector": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 1, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetTxInfoResponse": { - "full_name": "starkware.starknet.common.syscalls.GetTxInfoResponse", - "members": { - "tx_info": { - "cairo_type": "starkware.starknet.common.syscalls.TxInfo*", - "offset": 0 - } - }, - "size": 1, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetTxSignature": { - "full_name": "starkware.starknet.common.syscalls.GetTxSignature", - "members": { - "request": { - "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureRequest", - "offset": 0 - }, - "response": { - "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureResponse", - "offset": 1 - } - }, - "size": 3, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetTxSignatureRequest": { - "full_name": "starkware.starknet.common.syscalls.GetTxSignatureRequest", - "members": { - "selector": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 1, - "type": "struct" - }, - "starkware.starknet.common.syscalls.GetTxSignatureResponse": { - "full_name": "starkware.starknet.common.syscalls.GetTxSignatureResponse", - "members": { - "signature": { - "cairo_type": "felt*", - "offset": 1 - }, - "signature_len": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 2, - "type": "struct" - }, - "starkware.starknet.common.syscalls.LIBRARY_CALL_L1_HANDLER_SELECTOR": { - "type": "const", - "value": 436233452754198157705746250789557519228244616562 - }, - "starkware.starknet.common.syscalls.LIBRARY_CALL_SELECTOR": { - "type": "const", - "value": 92376026794327011772951660 - }, - "starkware.starknet.common.syscalls.LibraryCall": { - "full_name": "starkware.starknet.common.syscalls.LibraryCall", - "members": { - "request": { - "cairo_type": "starkware.starknet.common.syscalls.LibraryCallRequest", - "offset": 0 - }, - "response": { - "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", - "offset": 5 - } - }, - "size": 7, - "type": "struct" - }, - "starkware.starknet.common.syscalls.LibraryCallRequest": { - "full_name": "starkware.starknet.common.syscalls.LibraryCallRequest", - "members": { - "calldata": { - "cairo_type": "felt*", - "offset": 4 - }, - "calldata_size": { - "cairo_type": "felt", - "offset": 3 - }, - "class_hash": { - "cairo_type": "felt", - "offset": 1 - }, - "function_selector": { - "cairo_type": "felt", - "offset": 2 - }, - "selector": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 5, - "type": "struct" - }, - "starkware.starknet.common.syscalls.SEND_MESSAGE_TO_L1_SELECTOR": { - "type": "const", - "value": 433017908768303439907196859243777073 - }, - "starkware.starknet.common.syscalls.STORAGE_READ_SELECTOR": { - "type": "const", - "value": 100890693370601760042082660 - }, - "starkware.starknet.common.syscalls.STORAGE_WRITE_SELECTOR": { - "type": "const", - "value": 25828017502874050592466629733 - }, - "starkware.starknet.common.syscalls.SendMessageToL1SysCall": { - "full_name": "starkware.starknet.common.syscalls.SendMessageToL1SysCall", - "members": { - "payload_ptr": { - "cairo_type": "felt*", - "offset": 3 - }, - "payload_size": { - "cairo_type": "felt", - "offset": 2 - }, - "selector": { - "cairo_type": "felt", - "offset": 0 - }, - "to_address": { - "cairo_type": "felt", - "offset": 1 - } - }, - "size": 4, - "type": "struct" - }, - "starkware.starknet.common.syscalls.StorageRead": { - "full_name": "starkware.starknet.common.syscalls.StorageRead", - "members": { - "request": { - "cairo_type": "starkware.starknet.common.syscalls.StorageReadRequest", - "offset": 0 - }, - "response": { - "cairo_type": "starkware.starknet.common.syscalls.StorageReadResponse", - "offset": 2 - } - }, - "size": 3, - "type": "struct" - }, - "starkware.starknet.common.syscalls.StorageReadRequest": { - "full_name": "starkware.starknet.common.syscalls.StorageReadRequest", - "members": { - "address": { - "cairo_type": "felt", - "offset": 1 - }, - "selector": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 2, - "type": "struct" - }, - "starkware.starknet.common.syscalls.StorageReadResponse": { - "full_name": "starkware.starknet.common.syscalls.StorageReadResponse", - "members": { - "value": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 1, - "type": "struct" - }, - "starkware.starknet.common.syscalls.StorageWrite": { - "full_name": "starkware.starknet.common.syscalls.StorageWrite", - "members": { - "address": { - "cairo_type": "felt", - "offset": 1 - }, - "selector": { - "cairo_type": "felt", - "offset": 0 - }, - "value": { - "cairo_type": "felt", - "offset": 2 - } - }, - "size": 3, - "type": "struct" - }, - "starkware.starknet.common.syscalls.TxInfo": { - "full_name": "starkware.starknet.common.syscalls.TxInfo", - "members": { - "account_contract_address": { - "cairo_type": "felt", - "offset": 1 - }, - "chain_id": { - "cairo_type": "felt", - "offset": 6 - }, - "max_fee": { - "cairo_type": "felt", - "offset": 2 - }, - "nonce": { - "cairo_type": "felt", - "offset": 7 - }, - "signature": { - "cairo_type": "felt*", - "offset": 4 - }, - "signature_len": { - "cairo_type": "felt", - "offset": 3 - }, - "transaction_hash": { - "cairo_type": "felt", - "offset": 5 - }, - "version": { - "cairo_type": "felt", - "offset": 0 - } - }, - "size": 8, - "type": "struct" - } - }, - "main_scope": "__main__", - "prime": "0x800000000000011000000000000000000000000000000000000000000000001", - "reference_manager": { - "references": [] - } - } -} \ No newline at end of file diff --git a/src/tests/starknet/test_starknet_simulation.rs b/src/tests/starknet/test_starknet_simulation.rs deleted file mode 100644 index bd0d68f5..00000000 --- a/src/tests/starknet/test_starknet_simulation.rs +++ /dev/null @@ -1,315 +0,0 @@ -#[cfg(test)] -mod tests { - use cairo_vm::felt::Felt252; - use dotenv::dotenv; - use protosim::starknet_simulation::{ - rpc_reader::RpcStateReader, - simulation::{ContractOverride, Overrides, SimulationEngine, SimulationParameters}, - }; - use rpc_state_reader::rpc_state::{BlockTag, RpcChain, RpcState}; - use starknet_in_rust::utils::{felt_to_hash, get_storage_var_address, Address, ClassHash}; - use std::{collections::HashMap, env, sync::Arc}; - - const BOB_ADDRESS: &str = "0x065c19e14e2587d2de74c561b2113446ca4b389aabe6da1dc4accb6404599e99"; - const EKUBO_ADDRESS: &str = - "0x00000005dd3d2f4429af886cd1a3b08289dbcea99a294197e9eb43b0e0325b4b"; - const EKUBO_SIMPLE_SWAP_ADDRESS: &str = - "0x07a83729aaaae6344d6fca558614cd22ecdd3f5cd90ec0cd20c8d6bf08170431"; - const USDC_ADDRESS: &str = "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8"; - const ETH_ADDRESS: &str = "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"; - const DAI_ADDRESS: &str = "0xda114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3"; - - pub fn felt_str(val: &str) -> Felt252 { - let base = if val.starts_with("0x") { 16_u32 } else { 10_u32 }; - let stripped_val = val.strip_prefix("0x").unwrap_or(val); - - Felt252::parse_bytes(stripped_val.as_bytes(), base).expect("Failed to parse input") - } - - pub fn address_str(val: &str) -> Address { - Address(felt_str(val)) - } - - /// Setup Starknet RPC state reader - /// - /// Does not accept block number as input since it is overwritten by the simulation engine, - /// taking it as a parameter might make the user think that it is permanent - fn setup_reader() -> RpcStateReader { - let eth_rpc_url = env::var("ETH_RPC_URL").unwrap_or_else(|_| { - dotenv().expect("Missing .env file"); - env::var("ETH_RPC_URL").expect("Missing ETH_RPC_URL in .env file") - }); - let rpc_endpoint = format!("https://{}.infura.io/v3/{}", RpcChain::MainNet, eth_rpc_url); - let feeder_url = format!("https://{}.starknet.io/feeder_gateway", RpcChain::MainNet); - RpcStateReader::new(RpcState::new( - RpcChain::MainNet, - BlockTag::Latest.into(), - &rpc_endpoint, - &feeder_url, - )) - } - - /// Setup simulation engine with contract overrides - fn setup_engine( - contract_overrides: Option>, - ) -> SimulationEngine { - let rpc_state_reader = Arc::new(setup_reader()); - let contract_overrides = contract_overrides.unwrap_or_default(); - SimulationEngine::new(rpc_state_reader, contract_overrides.into()).unwrap() - } - - fn construct_token_contract_override(token: Address) -> ContractOverride { - // ERC20 contract overrides - using USDC token contract template - let class_hash: ClassHash = - hex::decode("02760f25d5a4fb2bdde5f561fd0b44a3dee78c28903577d37d669939d97036a0") - .unwrap() - .as_slice() - .try_into() - .unwrap(); - - ContractOverride::new(token, class_hash, None) - } - - fn add_balance_override( - mut overrides: Overrides, - address: Address, - amount: Felt252, - ) -> Overrides { - // override balance - let balance_storage_hash = - felt_to_hash(&get_storage_var_address("ERC20_balances", &[address.0.clone()]).unwrap()); - overrides.insert(balance_storage_hash, amount); - overrides - } - - #[test] - // #[cfg_attr(not(feature = "network_tests"), ignore)] - #[ignore] - fn test_consecutive_simulations_ekubo() { - // Test vars - let block_number = 194554; - let token0 = address_str(DAI_ADDRESS); - let token1 = address_str(ETH_ADDRESS); - let test_wallet = address_str(BOB_ADDRESS); - let ekubo_swap_address = address_str(EKUBO_SIMPLE_SWAP_ADDRESS); - let ekubo_core_address = address_str(EKUBO_ADDRESS); - let sell_amount = felt_str("0x5afb5ab61ef191"); - - // Construct engine with contract overrides - let sell_token_contract_override = construct_token_contract_override(token0.clone()); - let mut engine = setup_engine(Some(vec![sell_token_contract_override])); - - // Construct simulation overrides - token balances - let mut token_overrides = Overrides::new(); - // mock having transferred tokens to the swap contract before triggering the swap function - token_overrides = - add_balance_override(token_overrides, ekubo_swap_address.clone(), sell_amount.clone()); - // mock the core contract's reserve balance since this is checked during swap and errors if - // incorrect - token_overrides = add_balance_override( - token_overrides, - ekubo_core_address, - felt_str("2421600066015287788594"), - ); - let mut storage_overrides = HashMap::new(); - storage_overrides.insert(token0.clone(), token_overrides); - - // obtained from this Ekubo simple swap call: https://starkscan.co/call/0x04857b5a7af37e9b9f6fae27923d725f07016a4449f74f5ab91c04f13bbc8d23_1_3 - let swap_calldata = vec![ - // Pool key data - token0.0, // token0 - token1.0, // token1 - felt_str("0xc49ba5e353f7d00000000000000000"), // fee - Felt252::from(5982), // tick spacing - Felt252::from(0), // extension - // Swap data - sell_amount, // amount - Felt252::from(0), // amount sign - Felt252::from(0), // istoken1 - felt_str("0x65740af99bee7b4bf062fb147160000"), // sqrt ratio limit (lower bits) - Felt252::from(0), // sqrt ratio limit (upper bits) - Felt252::from(0), // skip ahead - test_wallet.0.clone(), // recipient - Felt252::from(0), // calculated_amount_threshold - ]; - - let params = SimulationParameters::new( - test_wallet, - ekubo_swap_address, - swap_calldata, - "swap".to_owned(), - Some(storage_overrides), - Some(u128::MAX), - block_number, - ); - - // SIMULATION 1 - let result0 = engine.simulate(¶ms); - dbg!(&result0); - assert!(result0.is_ok()); - let res = result0.unwrap(); - assert_eq!(res.gas_used, 9480810); - assert_eq!(res.result[2], felt_str("21909951468890105")); // check amount out - - // SIMULATION 2 - - let result1 = engine.simulate(¶ms); - dbg!(&result1); - assert!(result1.is_ok()); - let res = result1.unwrap(); - assert_eq!(res.gas_used, 9480810); - assert_eq!(res.result[2], felt_str("21909951468890105")); // check amount out is not - // affected by previous simulation - } - - #[test] - fn test_get_eth_usdc_spot_price_ekubo() { - let block_number = 367676; - let mut engine = setup_engine(None); - - let swap_calldata = vec![ - felt_str(ETH_ADDRESS), // token0 - felt_str(USDC_ADDRESS), // token1 - felt_str("170141183460469235273462165868118016"), // fee - Felt252::from(1000), // tick spacing - Felt252::from(0), // extension - ]; - - let params = SimulationParameters::new( - address_str(BOB_ADDRESS), - address_str(EKUBO_ADDRESS), - swap_calldata, - "get_pool_price".to_owned(), - None, - Some(100000), - block_number, - ); - - let result = engine.simulate(¶ms); - - let res = result.unwrap().result[0].clone(); - - // To get the human readable price we will need to convert this on the Python side like - // this: https://www.wolframalpha.com/input?i=(14458875492015717597830515600275777+/+2**128)**2*10**12 - assert_eq!(res, felt_str("14458875492015717597830515600275777")) - } - - #[test] - fn test_get_dai_usdc_spot_price_ekubo() { - let block_number = 426179; - let mut engine = setup_engine(None); - - let swap_calldata = vec![ - felt_str(DAI_ADDRESS), // token0 - felt_str(USDC_ADDRESS), // token1 - felt_str("170141183460469235273462165868118016"), // fee - Felt252::from(1000), // tick spacing - Felt252::from(0), // extension - ]; - - let params = SimulationParameters::new( - address_str(BOB_ADDRESS), - address_str(EKUBO_ADDRESS), - swap_calldata, - "get_pool_price".to_owned(), - None, - Some(100000), - block_number, - ); - - let result = engine.simulate(¶ms); - - let res = result.unwrap().result[0].clone(); - - // To get the human readable price we will need to convert this on the Python side like - // this: https://www.wolframalpha.com/input?i=(340321610937302884216160363291566+/+2**128)**2*10**12 - assert_eq!(res, felt_str("340288844056980486564646108486642")) - } - - #[test] - // #[cfg_attr(not(feature = "network_tests"), ignore)] - #[ignore] - fn test_get_amount_out_eth_dai() { - let test_wallet = address_str(BOB_ADDRESS); - let ekubo_swap_address = address_str(EKUBO_SIMPLE_SWAP_ADDRESS); - - // Test vars - let block_number = 386000; - let token0 = address_str(DAI_ADDRESS); - let token1 = address_str(ETH_ADDRESS); - let tokens = [token0.clone(), token1.clone()]; - let sell_amount = felt_str("0x2386f26fc10000"); - let expected_buy_amount = "18801973723146384196"; - let sell_token_index = 1; - - // Get ekubo's balance of sell token - let mut engine = setup_engine(None); - - let balance_params = SimulationParameters::new( - test_wallet.clone(), - tokens[sell_token_index].clone(), - vec![felt_str(EKUBO_ADDRESS)], - "balanceOf".to_owned(), - None, - Some(u128::MAX), - block_number, - ); - - let balance = engine.simulate(&balance_params); - - // Construct engine with contract overrides - let sell_token_contract_override = - construct_token_contract_override(tokens[sell_token_index].clone()); - let mut engine = setup_engine(Some(vec![sell_token_contract_override])); - // Construct simulation overrides - token balances - let mut token_overrides = Overrides::new(); - // mock having transferred tokens to the swap contract before triggering the swap function - token_overrides = - add_balance_override(token_overrides, ekubo_swap_address.clone(), sell_amount.clone()); - // mock the core contract's reserve balance since this is checked during swap and errors if - // incorrect - token_overrides = add_balance_override( - token_overrides, - address_str(EKUBO_ADDRESS), - balance.unwrap().result[0].to_owned(), - ); - let mut storage_overrides = HashMap::new(); - storage_overrides.insert(tokens[sell_token_index].clone(), token_overrides); - - let swap_calldata = vec![ - // Pool key data - token0.0, // token0 - token1.0, // token1 - felt_str("0x20c49ba5e353f80000000000000000"), // fee - Felt252::from(1000), // tick spacing - Felt252::from(0), // extension - // Swap data - sell_amount, // amount - Felt252::from(0), // amount sign - Felt252::from(1), // istoken1 - felt_str("0x6f3528fe26840249f4b191ef6dff7928"), // sqrt ratio limit (lower bits) - felt_str("0xfffffc080ed7b455"), // sqrt ratio limit (upper bits) - Felt252::from(0), // skip ahead - test_wallet.0.clone(), // recipient - Felt252::from(0), // calculated_amount_threshold - ]; - - let params = SimulationParameters::new( - test_wallet.clone(), - ekubo_swap_address.clone(), - swap_calldata, - "swap".to_owned(), - Some(storage_overrides.clone()), - Some(u128::MAX), - block_number, - ); - - let result0 = engine.simulate(¶ms); - assert!(result0.is_ok()); - let res = result0.unwrap(); - let amount_out_index = if sell_token_index == 1 { 0 } else { 2 }; - assert_eq!(res.gas_used, 7701570); - assert_eq!(res.result[amount_out_index], felt_str(expected_buy_amount)); - // check amount out - } -}