diff --git a/crates/bindings/src/arbiter_token.rs b/crates/bindings/src/arbiter_token.rs index fd77a12f..14137b48 100644 --- a/crates/bindings/src/arbiter_token.rs +++ b/crates/bindings/src/arbiter_token.rs @@ -4175,38 +4175,38 @@ pub mod arbiter_token { 34, 18, 32, - 87, - 152, - 21, - 207, - 182, + 153, 90, - 181, + 242, + 255, + 146, 139, - 94, - 147, - 135, - 210, - 182, - 140, - 119, - 93, - 122, - 154, - 226, - 144, - 80, - 239, - 135, - 36, - 61, - 84, - 86, + 164, 171, - 245, - 241, - 130, + 198, + 168, + 187, + 123, + 74, 137, + 145, + 246, + 218, + 157, + 148, + 174, + 237, + 79, + 4, + 237, + 254, + 194, + 245, + 217, + 23, + 205, + 139, + 239, 100, 115, 111, @@ -4215,7 +4215,7 @@ pub mod arbiter_token { 67, 0, 8, - 19, + 17, 0, 51, ]; @@ -7233,38 +7233,38 @@ pub mod arbiter_token { 34, 18, 32, - 87, - 152, - 21, - 207, - 182, + 153, 90, - 181, + 242, + 255, + 146, 139, - 94, - 147, - 135, - 210, - 182, - 140, - 119, - 93, - 122, - 154, - 226, - 144, - 80, - 239, - 135, - 36, - 61, - 84, - 86, + 164, 171, - 245, - 241, - 130, + 198, + 168, + 187, + 123, + 74, 137, + 145, + 246, + 218, + 157, + 148, + 174, + 237, + 79, + 4, + 237, + 254, + 194, + 245, + 217, + 23, + 205, + 139, + 239, 100, 115, 111, @@ -7273,7 +7273,7 @@ pub mod arbiter_token { 67, 0, 8, - 19, + 17, 0, 51, ]; diff --git a/crates/bindings/src/fixed_point_math_lib.rs b/crates/bindings/src/fixed_point_math_lib.rs index d28f865f..48f8604e 100644 --- a/crates/bindings/src/fixed_point_math_lib.rs +++ b/crates/bindings/src/fixed_point_math_lib.rs @@ -117,38 +117,38 @@ pub mod fixed_point_math_lib { 34, 18, 32, - 14, - 240, - 97, - 209, - 48, - 224, - 220, - 233, - 88, - 180, - 135, - 97, - 124, - 226, - 164, - 242, - 99, - 251, + 31, + 37, + 171, + 27, + 31, + 125, + 169, + 106, + 132, + 61, + 80, + 80, + 133, + 9, + 184, + 112, + 10, + 155, + 131, + 244, + 200, + 18, + 92, + 161, + 110, + 26, + 38, 4, - 7, - 75, - 172, - 78, - 95, - 173, - 94, - 99, - 194, - 226, - 156, - 14, - 36, + 21, + 118, + 210, + 3, 100, 115, 111, @@ -157,7 +157,7 @@ pub mod fixed_point_math_lib { 67, 0, 8, - 19, + 17, 0, 51, ]; @@ -209,38 +209,38 @@ pub mod fixed_point_math_lib { 34, 18, 32, - 14, - 240, - 97, - 209, - 48, - 224, - 220, - 233, - 88, - 180, - 135, - 97, - 124, - 226, - 164, - 242, - 99, - 251, + 31, + 37, + 171, + 27, + 31, + 125, + 169, + 106, + 132, + 61, + 80, + 80, + 133, + 9, + 184, + 112, + 10, + 155, + 131, + 244, + 200, + 18, + 92, + 161, + 110, + 26, + 38, 4, - 7, - 75, - 172, - 78, - 95, - 173, - 94, - 99, - 194, - 226, - 156, - 14, - 36, + 21, + 118, + 210, + 3, 100, 115, 111, @@ -249,7 +249,7 @@ pub mod fixed_point_math_lib { 67, 0, 8, - 19, + 17, 0, 51, ]; diff --git a/crates/bindings/src/liquid_exchange.rs b/crates/bindings/src/liquid_exchange.rs index 01e3b587..52eedfc8 100644 --- a/crates/bindings/src/liquid_exchange.rs +++ b/crates/bindings/src/liquid_exchange.rs @@ -1476,38 +1476,38 @@ pub mod liquid_exchange { 34, 18, 32, - 45, - 17, - 40, - 204, - 134, - 184, - 84, - 186, - 35, - 118, - 193, - 112, - 46, - 219, - 77, - 108, + 224, + 60, + 254, + 239, + 48, + 114, + 157, + 161, + 119, + 233, + 180, + 53, + 222, + 158, + 215, 149, - 51, - 195, - 54, - 69, - 123, - 226, - 236, - 52, - 117, - 193, - 138, + 175, + 63, + 116, + 149, + 201, + 204, + 96, + 47, + 28, + 146, 128, - 91, - 21, - 17, + 127, + 1, + 229, + 90, + 219, 100, 115, 111, @@ -1516,7 +1516,7 @@ pub mod liquid_exchange { 67, 0, 8, - 19, + 17, 0, 51, ]; @@ -2765,38 +2765,38 @@ pub mod liquid_exchange { 34, 18, 32, - 45, - 17, - 40, - 204, - 134, - 184, - 84, - 186, - 35, - 118, - 193, - 112, - 46, - 219, - 77, - 108, + 224, + 60, + 254, + 239, + 48, + 114, + 157, + 161, + 119, + 233, + 180, + 53, + 222, + 158, + 215, 149, - 51, - 195, - 54, - 69, - 123, - 226, - 236, - 52, - 117, - 193, - 138, + 175, + 63, + 116, + 149, + 201, + 204, + 96, + 47, + 28, + 146, 128, - 91, - 21, - 17, + 127, + 1, + 229, + 90, + 219, 100, 115, 111, @@ -2805,7 +2805,7 @@ pub mod liquid_exchange { 67, 0, 8, - 19, + 17, 0, 51, ]; diff --git a/crates/bindings/src/writer.rs b/crates/bindings/src/writer.rs index 77324494..2e2660b4 100644 --- a/crates/bindings/src/writer.rs +++ b/crates/bindings/src/writer.rs @@ -973,38 +973,38 @@ pub mod writer { 34, 18, 32, - 160, - 21, - 88, - 252, - 25, + 4, + 38, + 18, + 38, + 170, 149, + 59, 251, - 242, - 204, - 41, - 163, - 130, - 16, - 9, - 101, - 73, - 102, - 222, - 56, - 39, - 221, - 181, - 215, - 196, - 10, - 230, - 86, - 108, - 190, - 250, - 249, - 66, + 155, + 232, + 150, + 97, + 50, + 67, + 53, + 154, + 43, + 105, + 95, + 20, + 228, + 49, + 197, + 209, + 223, + 214, + 127, + 184, + 125, + 115, + 40, + 42, 100, 115, 111, @@ -1013,7 +1013,7 @@ pub mod writer { 67, 0, 8, - 19, + 17, 0, 51, ]; @@ -1944,38 +1944,38 @@ pub mod writer { 34, 18, 32, - 160, - 21, - 88, - 252, - 25, + 4, + 38, + 18, + 38, + 170, 149, + 59, 251, - 242, - 204, - 41, - 163, - 130, - 16, - 9, - 101, - 73, - 102, - 222, - 56, - 39, - 221, - 181, - 215, - 196, - 10, - 230, - 86, - 108, - 190, - 250, - 249, - 66, + 155, + 232, + 150, + 97, + 50, + 67, + 53, + 154, + 43, + 105, + 95, + 20, + 228, + 49, + 197, + 209, + 223, + 214, + 127, + 184, + 125, + 115, + 40, + 42, 100, 115, 111, @@ -1984,7 +1984,7 @@ pub mod writer { 67, 0, 8, - 19, + 17, 0, 51, ]; diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index e9fb6cee..2cc9b3e8 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -14,7 +14,7 @@ use eyre::Result; use on_chain::monitor::EventMonitor; use revm::primitives::{ruint::Uint, B160}; use simulate::{ - environment::SimulationContract, manager::SimulationManager, price_simulation::PriceSimulation, + contract::SimulationContract, manager::SimulationManager, price_simulation::PriceSimulation, utils::recast_address, }; mod config; @@ -79,7 +79,7 @@ async fn main() -> Result<()> { weth, ().into_tokens(), ); - println!("WETH deployed at: {}", weth.address.unwrap()); + println!("WETH deployed at: {}", weth.address); // Deploy the registry contract. let registry = SimulationContract::new( @@ -95,7 +95,7 @@ async fn main() -> Result<()> { registry, ().into_tokens(), ); - println!("Simple registry deployed at: {}", registry.address.unwrap()); + println!("Simple registry deployed at: {}", registry.address); // Deploy the portfolio contract. let portfolio = SimulationContract::new( @@ -107,15 +107,15 @@ async fn main() -> Result<()> { ); let portfolio_args = ( - recast_address(weth.address.unwrap()), - recast_address(registry.address.unwrap()), + recast_address(weth.address), + recast_address(registry.address), ); let portfolio = manager.agents.get("admin").unwrap().deploy( &mut manager.environment, portfolio, portfolio_args.into_tokens(), ); - println!("Portfolio deployed at: {}", portfolio.address.unwrap()); + println!("Portfolio deployed at: {}", portfolio.address); let arbiter_token = SimulationContract::new( BaseContract::from(arbiter_token::ARBITERTOKEN_ABI.clone()), @@ -136,10 +136,7 @@ async fn main() -> Result<()> { arbiter_token, args.into_tokens(), ); - println!( - "Arbiter Token deployed at: {}", - arbiter_token.address.unwrap() - ); + println!("Arbiter Token deployed at: {}", arbiter_token.address); // Create a user to mint tokens to. let user_name = "arbitrageur"; diff --git a/crates/simulate/Cargo.toml b/crates/simulate/Cargo.toml index c9ccdbc5..829c34ff 100644 --- a/crates/simulate/Cargo.toml +++ b/crates/simulate/Cargo.toml @@ -19,6 +19,11 @@ rand_chacha = "0.3.1" rand_distr = "0.4.3" plotly = "0.8.3" +# void_middleware +async-trait = "0.1.68" +serde = {version = "1.0.145", features= ["derive"]} +serde_json = "1.0.68" + # added for tests bindings = { path = "../bindings" } ethers = "2.0.2" diff --git a/crates/simulate/src/agent/mod.rs b/crates/simulate/src/agent/mod.rs index 9019634b..fd374e9a 100644 --- a/crates/simulate/src/agent/mod.rs +++ b/crates/simulate/src/agent/mod.rs @@ -12,7 +12,10 @@ use crossbeam_channel::Receiver; use ethers::abi::Token; use revm::primitives::{Address, ExecutionResult, Log, Output, TransactTo, TxEnv, B160, U256}; -use crate::environment::{IsDeployed, NotDeployed, SimulationContract, SimulationEnvironment}; +use crate::{ + contract::{IsDeployed, NotDeployed, SimulationContract}, + environment::SimulationEnvironment, +}; pub mod user; /// Describes the gas settings for a transaction. @@ -42,7 +45,7 @@ pub trait Agent { call_data: Bytes, value: U256, ) -> ExecutionResult { - let tx = self.build_call_transaction(contract.address.unwrap(), call_data, value); + let tx = self.build_call_transaction(contract.address, call_data, value); simulation_environment.execute(tx) } diff --git a/crates/simulate/src/contract.rs b/crates/simulate/src/contract.rs new file mode 100644 index 00000000..903625e8 --- /dev/null +++ b/crates/simulate/src/contract.rs @@ -0,0 +1,65 @@ +#![warn(missing_docs)] +//! This module contains the `SimulationContract` struct that is used to wrap around the ethers `BaseContract` and add some additional information relevant for revm and the simulation. +use std::marker::PhantomData; + +use ethers::prelude::BaseContract; +use revm::primitives::B160; + +#[derive(Debug, Clone)] +/// A struct use for `PhantomData` to indicate a lock on contracts that are not deployed. +pub struct NotDeployed; +#[derive(Debug)] +// TODO: It would be good to also allow the `IsDeployed` to also mention which `SimulationManager` has deployed it (when we have multiple managers). +/// A struct use for `PhantomData` to indicate an unlocked contract that is deployed. +pub struct IsDeployed; + +/// Trait that is used to allow for different statuses of contract fields depending on whether a contract is deployed or not. +pub trait DeploymentStatus { + /// The type of the address field. + type Address; +} + +impl DeploymentStatus for NotDeployed { + type Address = (); +} + +impl DeploymentStatus for IsDeployed { + type Address = B160; +} + +#[derive(Debug, Clone)] +/// A struct that wraps around the ethers `BaseContract` and adds some additional information relevant for revm and the simulation. +pub struct SimulationContract { + /// The ethers `BaseContract` that holds the ABI. + pub base_contract: BaseContract, + // TODO: Bytecode is really only used for deployment. Maybe we don't need to store it like this. + /// The contract's deployed bytecode. + pub bytecode: Vec, + /// The address of the contract within the relevant `SimulationEnvironment`. + pub address: Deployed::Address, + /// A `PhantomData` marker to indicate whether the contract is deployed or not. + pub deployed: PhantomData, +} + +impl SimulationContract { + /// A constructor function for `SimulationContract` that takes a `BaseContract` and the deployment bytecode. + pub fn new(base_contract: BaseContract, bytecode: Vec) -> Self { + Self { + base_contract, + bytecode, + address: (), + deployed: std::marker::PhantomData, + } + } + // TODO: This function can probably be made private. + /// Creates a new `SimulationContract` that is marked as deployed. + /// This is only called by implicitly by the `SimulationManager` inside of the `deploy` function. + pub(crate) fn to_deployed(&self, address: B160) -> SimulationContract { + SimulationContract { + base_contract: self.base_contract.clone(), + bytecode: self.bytecode.clone(), + address, + deployed: std::marker::PhantomData, + } + } +} diff --git a/crates/simulate/src/environment.rs b/crates/simulate/src/environment.rs index 2cf25639..6ce142c3 100644 --- a/crates/simulate/src/environment.rs +++ b/crates/simulate/src/environment.rs @@ -2,10 +2,9 @@ //! The environment that constitutes a simulation is handled here. use crossbeam_channel::Sender; -use ethers::prelude::BaseContract; use revm::{ db::{CacheDB, EmptyDB}, - primitives::{ExecutionResult, Log, TxEnv, B160}, + primitives::{ExecutionResult, Log, TxEnv}, EVM, }; @@ -18,29 +17,6 @@ pub struct SimulationEnvironment { // TODO: Perhaps add the contracts in here? } -#[derive(Debug, Clone)] -/// A struct use for `PhantomData` to indicate a lock on contracts that are not deployed. -pub struct NotDeployed; -#[derive(Debug)] -// TODO: It would be good to also allow the `IsDeployed` to also mention which `SimulationManager` has deployed it (when we have multiple managers). -/// A struct use for `PhantomData` to indicate an unlocked contract that is deployed. -pub struct IsDeployed; - -#[derive(Debug, Clone)] -/// A struct that wraps around the ethers `BaseContract` and adds some additional information relevant for revm and the simulation. -pub struct SimulationContract { - /// The ethers `BaseContract` that holds the ABI. - pub base_contract: BaseContract, - // TODO: Bytecode is really only used for deployment. Maybe we don't need to store it like this. - /// The contract's deployed bytecode. - pub bytecode: Vec, - //TODO: Options are not great here. We want an address for the deployment to some `SimulationEnvironment`. - /// The address of the contract within the relevant `SimulationEnvironment`. - pub address: Option, - /// A `PhantomData` marker to indicate whether the contract is deployed or not. - pub deployed: std::marker::PhantomData, -} - impl SimulationEnvironment { pub(crate) fn new() -> Self { let mut evm = EVM::new(); @@ -73,26 +49,3 @@ impl SimulationEnvironment { self.event_senders.push(sender); } } - -impl SimulationContract { - /// A constructor function for `SimulationContract` that takes a `BaseContract` and the deployment bytecode. - pub fn new(base_contract: BaseContract, bytecode: Vec) -> Self { - Self { - base_contract, - bytecode, - address: None, - deployed: std::marker::PhantomData, - } - } - // TODO: This function can probably be made private. - /// Creates a new `SimulationContract` that is marked as deployed. - /// This is only called by implicitly by the `SimulationManager` inside of the `deploy` function. - pub(crate) fn to_deployed(&self, address: B160) -> SimulationContract { - SimulationContract { - base_contract: self.base_contract.clone(), - bytecode: self.bytecode.clone(), - address: Some(address), - deployed: std::marker::PhantomData, - } - } -} diff --git a/crates/simulate/src/exchange.rs b/crates/simulate/src/exchange.rs index d4ea3574..35a528aa 100644 --- a/crates/simulate/src/exchange.rs +++ b/crates/simulate/src/exchange.rs @@ -30,9 +30,7 @@ mod tests { }; use revm::primitives::{ruint::Uint, B160}; - use crate::{ - environment::SimulationContract, manager::SimulationManager, utils::recast_address, - }; + use crate::{contract::SimulationContract, manager::SimulationManager, utils::recast_address}; #[test] fn test_swap_x_for_y_liquid_exchange() { // define the wad constant @@ -44,8 +42,8 @@ mod tests { // Set up a user named alice let user_name = "alice"; - let user_address = B160::from_low_u64_be(2); // TODO: Prevent address collisions - manager.create_user(user_address, user_name); + let user_address = B160::from_low_u64_be(2); + manager.create_user(user_address, user_name).unwrap(); // Pull out the admin and alice let admin = manager.agents.get("admin").unwrap(); @@ -83,9 +81,9 @@ mod tests { .collect(), ); let args = ( - recast_address(token_x.address.unwrap()), - recast_address(token_y.address.unwrap()), - U256::from(initial_price), + recast_address(token_x.address), + recast_address(token_y.address), + initial_price, ) .into_tokens(); let liquid_exchange_xy = admin.deploy(&mut manager.environment, liquid_exchange, args); @@ -102,10 +100,7 @@ mod tests { admin.call_contract(&mut manager.environment, &token_x, call_data, Uint::from(0)); // Mint max token_y to the liquid_exchange contract. - let args = ( - recast_address(liquid_exchange_xy.address.unwrap()), - U256::MAX, - ); + let args = (recast_address(liquid_exchange_xy.address), U256::MAX); let call_data = token_y .base_contract .encode("mint", args) @@ -115,10 +110,7 @@ mod tests { admin.call_contract(&mut manager.environment, &token_y, call_data, Uint::from(0)); // Have alice's approval for token_x to be spent by the liquid_exchange. - let args = ( - recast_address(liquid_exchange_xy.address.unwrap()), - U256::MAX, - ); + let args = (recast_address(liquid_exchange_xy.address), U256::MAX); let call_data = token_x .base_contract .encode("approve", args) @@ -131,13 +123,7 @@ mod tests { let swap_amount = mint_amount / 2; let call_data = liquid_exchange_xy .base_contract - .encode( - "swap", - ( - recast_address(token_x.address.unwrap()), - U256::from(swap_amount), - ), - ) + .encode("swap", (recast_address(token_x.address), swap_amount)) .unwrap() .into_iter() .collect(); @@ -195,7 +181,7 @@ mod tests { // Set up a user named alice let user_name = "alice"; let user_address = B160::from_low_u64_be(2); // TODO: Prevent address collisions - manager.create_user(user_address, user_name); + manager.create_user(user_address, user_name).unwrap(); // Pull out the admin and alice let admin = manager.agents.get("admin").unwrap(); @@ -233,9 +219,9 @@ mod tests { .collect(), ); let args = ( - recast_address(token_x.address.unwrap()), - recast_address(token_y.address.unwrap()), - U256::from(initial_price), + recast_address(token_x.address), + recast_address(token_y.address), + initial_price, ) .into_tokens(); let liquid_exchange_xy = admin.deploy(&mut manager.environment, liquid_exchange, args); @@ -252,10 +238,7 @@ mod tests { admin.call_contract(&mut manager.environment, &token_y, call_data, Uint::from(0)); // Mint max token_x to the liquid_exchange contract. - let args = ( - recast_address(liquid_exchange_xy.address.unwrap()), - U256::MAX, - ); + let args = (recast_address(liquid_exchange_xy.address), U256::MAX); let call_data = token_x .base_contract .encode("mint", args) @@ -265,10 +248,7 @@ mod tests { admin.call_contract(&mut manager.environment, &token_x, call_data, Uint::from(0)); // Have alice's approval for token_y to be spent by the liquid_exchange. - let args = ( - recast_address(liquid_exchange_xy.address.unwrap()), - U256::MAX, - ); + let args = (recast_address(liquid_exchange_xy.address), U256::MAX); let call_data = token_y .base_contract .encode("approve", args) @@ -281,13 +261,7 @@ mod tests { let swap_amount = mint_amount / 2; let call_data = liquid_exchange_xy .base_contract - .encode( - "swap", - ( - recast_address(token_y.address.unwrap()), - U256::from(swap_amount), - ), - ) + .encode("swap", (recast_address(token_y.address), swap_amount)) .unwrap() .into_iter() .collect(); @@ -389,7 +363,7 @@ mod tests { let token_y = admin.deploy(&mut manager.environment, arbiter_token, args); // Deploy LiquidExchange - let price_to_check = 1000; + let price_to_check = 1000; // TODO: this is wrong let initial_price = wad.checked_mul(U256::from(price_to_check)).unwrap(); let liquid_exchange = SimulationContract::new( BaseContract::from(bindings::liquid_exchange::LIQUIDEXCHANGE_ABI.clone()), @@ -399,9 +373,9 @@ mod tests { .collect(), ); let args = ( - recast_address(token_x.address.unwrap()), - recast_address(token_y.address.unwrap()), - U256::from(initial_price), + recast_address(token_x.address), + recast_address(token_y.address), + initial_price, ) .into_tokens(); let liquid_exchange_xy = admin.deploy(&mut manager.environment, liquid_exchange, args); diff --git a/crates/simulate/src/lib.rs b/crates/simulate/src/lib.rs index 66ba2882..2fe30505 100644 --- a/crates/simulate/src/lib.rs +++ b/crates/simulate/src/lib.rs @@ -2,9 +2,11 @@ //! Lib crate for describing simulations. pub mod agent; +pub mod contract; pub mod environment; pub mod exchange; pub mod manager; +pub mod middleware; pub mod price_simulation; pub mod utils; @@ -18,9 +20,7 @@ mod tests { }; use revm::primitives::{ruint::Uint, B160}; - use crate::{ - environment::SimulationContract, manager::SimulationManager, utils::recast_address, - }; + use crate::{contract::SimulationContract, manager::SimulationManager, utils::recast_address}; #[test] /// Test that the writer contract can echo a string. @@ -100,10 +100,7 @@ mod tests { arbiter_token, args.into_tokens(), ); - println!( - "Arbiter Token deployed at: {}", - arbiter_token.address.unwrap() - ); + println!("Arbiter Token deployed at: {}", arbiter_token.address); // Generate calldata for the 'name' function let call_data = arbiter_token @@ -231,7 +228,7 @@ mod tests { let logs = manager.agents.get("admin").unwrap().read_logs(); // Decode the logs - let log_topics: Vec = logs.clone()[0] + let log_topics: Vec = logs[0] .topics .clone() .into_iter() @@ -388,7 +385,7 @@ mod tests { let _execution_result = manager.agents.get("admin").unwrap().call_contract( &mut manager.environment, &writer, - call_data.clone(), + call_data, Uint::from(0), ); diff --git a/crates/simulate/src/manager.rs b/crates/simulate/src/manager.rs index 27f9f702..e97e8f98 100644 --- a/crates/simulate/src/manager.rs +++ b/crates/simulate/src/manager.rs @@ -2,7 +2,7 @@ //! Simulation managers are used to manage the environments for a simulation. //! Managers are responsible for adding agents, running agents, deploying contracts, calling contracts, and reading logs. -use std::collections::HashMap; +use std::{collections::HashMap, sync::Arc}; use bytes::Bytes; use crossbeam_channel::unbounded; @@ -11,6 +11,7 @@ use revm::primitives::{AccountInfo, ExecutionResult, Log, Output, B160}; use crate::{ agent::{user::User, Agent}, environment::SimulationEnvironment, + middleware::SimulationMiddleware, }; // TODO: Maybe need a `SimulationAccount` that abstracts some of the revm primitives further. @@ -22,6 +23,8 @@ pub struct SimulationManager<'a> { pub environment: SimulationEnvironment, /// The agents that are currently running in the simulation environment. pub agents: HashMap<&'a str, Box>, + /// The middleware that is used to interact with the simulation environment. + pub middleware: Arc, } impl<'a> Default for SimulationManager<'a> { @@ -38,6 +41,7 @@ impl<'a> SimulationManager<'a> { let mut simulation_manager = Self { environment: SimulationEnvironment::new(), agents: HashMap::new(), + middleware: Arc::new(SimulationMiddleware::default()), }; let admin = Box::new(User::new(event_receiver_admin, B160::from_low_u64_be(1))); simulation_manager.add_agent("admin", admin).unwrap(); @@ -95,14 +99,10 @@ impl<'a> SimulationManager<'a> { "This call halted for {:#?} and used {} gas.", reason, gas_used ), - // ExecutionResult::Revert { output, gas_used } => panic!( - // "This call reverted with output {:?} and used {} gas.", - // output, gas_used - // ), - ExecutionResult::Revert { output, .. } => { - println!("Revert!"); - output - } + ExecutionResult::Revert { output, gas_used } => panic!( + "This call reverted with output {:?} and used {} gas.", + output, gas_used + ), } } } diff --git a/crates/simulate/src/middleware.rs b/crates/simulate/src/middleware.rs new file mode 100644 index 00000000..b29579da --- /dev/null +++ b/crates/simulate/src/middleware.rs @@ -0,0 +1,65 @@ +#![warn(missing_docs)] +//! This module contains the middleware for the Revm simulation environment. +//! Most of the middleware is essentially a placeholder, but it is necessary to have a middleware to work with bindings more efficiently. + +use std::fmt::Debug; + +use ethers::{ + prelude::ProviderError, + providers::{Middleware, MockProvider}, +}; + +/// The [`SimulationMiddleware`] allows for a "dummy" middleware to be used in the simulation environment. +#[derive(Debug, Default)] +pub struct SimulationMiddleware; + +impl Middleware for SimulationMiddleware { + type Provider = MockProvider; + type Error = ProviderError; + type Inner = Self; + + fn inner(&self) -> &Self::Inner { + self + } +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use bindings::writer::Writer; + use bytes::Bytes; + use ethers::{prelude::BaseContract, types::Address}; + + use super::*; + use crate::contract::SimulationContract; + + #[test] + fn test_simulation_middleware_calldata() { + let arc_middleware = Arc::new(SimulationMiddleware::default()); + let writer = Writer::new(Address::from_low_u64_be(1), arc_middleware); + let thing = writer.echo_string(String::from("Hello, world!")); + let calldata = thing.calldata().unwrap(); + + // Get bytecode and abi for the writer contract. + let writer = SimulationContract::new( + BaseContract::from(bindings::writer::WRITER_ABI.clone()), + bindings::writer::WRITER_BYTECODE + .clone() + .into_iter() + .collect(), + ); + + // Generate calldata for the 'echoString' function + let test_string = "Hello, world!"; + let input_arguments = test_string.to_string(); + let call_data: Bytes = writer + .base_contract + .encode("echoString", input_arguments) + .unwrap() + .into_iter() + .collect(); + + assert_eq!(calldata, call_data); + } +}