diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 4b82d43f..44dd6aeb 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -139,7 +139,7 @@ async fn main() -> Result<()> { let user_name = "arbitrageur"; let user_address = B160::from_str("0x0000000000000000000000000000000000000002").unwrap(); - manager.create_user(user_address, user_name); + manager.create_user(user_address, user_name).unwrap(); println!("Arbitraguer created at: {}", user_address); diff --git a/crates/simulate/src/agent/admin.rs b/crates/simulate/src/agent/admin.rs deleted file mode 100644 index 4f90e8d4..00000000 --- a/crates/simulate/src/agent/admin.rs +++ /dev/null @@ -1,50 +0,0 @@ -#![warn(missing_docs)] -//! Describes the agent that will always come alongside any simulation. -use std::str::FromStr; - -use crossbeam_channel::Receiver; -use revm::primitives::{Account, AccountInfo, Address, Log, B160, U256}; - -use crate::agent::{Agent, TransactSettings}; - -/// An agent that is always spawned with any simulation to take control of initial setup, etc. -pub struct Admin { - /// Public address of the simulation manager. - pub address: B160, - /// revm-primitive account of the simulation manager. - pub account: Account, - /// Contains the default transaction options for revm such as gas limit and gas price. - pub transact_settings: TransactSettings, - /// The receiver for the crossbeam channel that events are sent down from manager's dispatch. - pub event_receiver: Receiver>, -} - -impl Agent for Admin { - fn address(&self) -> Address { - self.address - } - fn transact_settings(&self) -> &TransactSettings { - &self.transact_settings - } - fn receiver(&self) -> crossbeam_channel::Receiver> { - self.event_receiver.clone() - } - fn filter_events(&self) { - todo!(); - } -} - -impl Admin { - /// Constructor function to instantiate a - pub fn new(event_receiver: Receiver>) -> Self { - Self { - address: B160::from_str("0x0000000000000000000000000000000000000001").unwrap(), - account: Account::from(AccountInfo::default()), - transact_settings: TransactSettings { - gas_limit: u64::MAX, - gas_price: U256::ZERO, /* This should stay zero for the admin so we don't have to fund it. */ - }, - event_receiver, - } - } -} diff --git a/crates/simulate/src/agent/mod.rs b/crates/simulate/src/agent/mod.rs index a64bb5e9..9019634b 100644 --- a/crates/simulate/src/agent/mod.rs +++ b/crates/simulate/src/agent/mod.rs @@ -14,7 +14,6 @@ use revm::primitives::{Address, ExecutionResult, Log, Output, TransactTo, TxEnv, use crate::environment::{IsDeployed, NotDeployed, SimulationContract, SimulationEnvironment}; -pub mod admin; pub mod user; /// Describes the gas settings for a transaction. pub struct TransactSettings { diff --git a/crates/simulate/src/agent/user.rs b/crates/simulate/src/agent/user.rs index 194fdab1..4ec4dc72 100644 --- a/crates/simulate/src/agent/user.rs +++ b/crates/simulate/src/agent/user.rs @@ -40,7 +40,7 @@ impl User { address, account: Account::from(AccountInfo::default()), transact_settings: TransactSettings { - gas_limit: u64::MAX, + gas_limit: u64::MAX, // TODO: Users should have a gas limit. gas_price: U256::ZERO, // TODO: Users should have an associated gas price. }, event_receiver, diff --git a/crates/simulate/src/lib.rs b/crates/simulate/src/lib.rs index 3a54b1f4..66ba2882 100644 --- a/crates/simulate/src/lib.rs +++ b/crates/simulate/src/lib.rs @@ -132,7 +132,7 @@ mod tests { // Create a user to mint tokens to. let user_name = "alice"; let user_address = B160::from_str("0x0000000000000000000000000000000000000002").unwrap(); - manager.create_user(user_address, user_name); // TODO: This should probably be done by the manager itself. THough it will be something to consider when we have more agents. + manager.create_user(user_address, user_name).unwrap(); // TODO: This should probably be done by the manager itself. THough it will be something to consider when we have more agents. // Allocating new tokens to user by calling Arbiter Token's ERC20 'mint' instance. let mint_amount = U256::from(1000); @@ -254,7 +254,7 @@ mod tests { let mut manager = SimulationManager::default(); let user_name = "alice"; let user_address = B160::from_str("0x0000000000000000000000000000000000000002").unwrap(); - manager.create_user(user_address, user_name); + manager.create_user(user_address, user_name).unwrap(); // Get bytecode and abi for the writer contract. let writer = SimulationContract::new( diff --git a/crates/simulate/src/manager.rs b/crates/simulate/src/manager.rs index 01e1c5ca..27f9f702 100644 --- a/crates/simulate/src/manager.rs +++ b/crates/simulate/src/manager.rs @@ -9,7 +9,7 @@ use crossbeam_channel::unbounded; use revm::primitives::{AccountInfo, ExecutionResult, Log, Output, B160}; use crate::{ - agent::{admin::Admin, user::User, Agent}, + agent::{user::User, Agent}, environment::SimulationEnvironment, }; @@ -31,15 +31,16 @@ impl<'a> Default for SimulationManager<'a> { } impl<'a> SimulationManager<'a> { - /// Constructor function to instantiate a + /// Constructor function to instantiate a manager that has a default admin user and a simulation environment. + /// The admin will always be given the 0x0...1 address. pub fn new() -> Self { let (event_sender_admin, event_receiver_admin) = unbounded::>(); let mut simulation_manager = Self { environment: SimulationEnvironment::new(), agents: HashMap::new(), }; - let admin = Box::new(Admin::new(event_receiver_admin)); - simulation_manager.add_agent("admin", admin); + let admin = Box::new(User::new(event_receiver_admin, B160::from_low_u64_be(1))); + simulation_manager.add_agent("admin", admin).unwrap(); simulation_manager .environment .add_sender(event_sender_admin); @@ -52,13 +53,22 @@ impl<'a> SimulationManager<'a> { } /// Add an [`Agent`] to the current simulation. - pub fn add_agent(&mut self, name: &'a str, agent: Box) { + pub fn add_agent(&mut self, name: &'a str, agent: Box) -> Result<(), String> { + if self + .agents + .values() + .into_iter() + .any(|agent_in_db| agent_in_db.address() == agent.address()) + { + return Err("Agent already exists in the simulation environment.".to_string()); + }; self.agents.insert(name, agent); + Ok(()) } // TODO: maybe should make the name optional here, but I struggled with this. /// Allow the manager to create a dummy user account. - pub fn create_user(&mut self, address: B160, name: &'a str) { + pub fn create_user(&mut self, address: B160, name: &'a str) -> Result<(), String> { self.environment .evm .db() @@ -66,8 +76,9 @@ impl<'a> SimulationManager<'a> { .insert_account_info(address, AccountInfo::default()); let (event_sender_user, event_receiver_user) = unbounded::>(); let user = Box::new(User::new(event_receiver_user, address)); - self.add_agent(name, user); - self.environment.add_sender(event_sender_user) + self.add_agent(name, user)?; + self.environment.add_sender(event_sender_user); + Ok(()) } /// Takes an `ExecutionResult` and returns the raw bytes of the output that can then be decoded. @@ -95,3 +106,10 @@ impl<'a> SimulationManager<'a> { } } } + +#[test] +fn test_agent_address_collision() { + let mut manager = SimulationManager::default(); + let result = manager.create_user(B160::from_low_u64_be(1), "alice"); + assert!(result.is_err()); +}