Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 16 additions & 45 deletions crates/bundle/src/call/driver.rs
Original file line number Diff line number Diff line change
@@ -1,47 +1,17 @@
use crate::{SignetCallBundle, SignetCallBundleResponse};
use crate::{SignetBundleError, SignetCallBundle, SignetCallBundleResponse};
use alloy::{consensus::TxEnvelope, primitives::U256};
use signet_evm::OrderDetector;
use signet_types::{MarketContext, MarketError};
use signet_types::MarketContext;
use std::fmt::Debug;
use trevm::{
revm::{primitives::EVMError, Database, DatabaseCommit},
revm::{Database, DatabaseCommit},
trevm_bail, trevm_ensure, unwrap_or_trevm_err, BundleDriver, BundleError,
};

/// Errors that can occur when running a bundle on the Signet EVM.
#[derive(thiserror::Error)]
pub enum SignetBundleError<Db: Database> {
/// A primitive [`BundleError`] error ocurred.
#[error(transparent)]
BundleError(#[from] BundleError<Db>),
/// A [`MarketError`] ocurred.
#[error(transparent)]
MarketError(#[from] MarketError),
}

impl<Db: Database> Debug for SignetBundleError<Db> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SignetBundleError::BundleError(e) => write!(f, "BundleError({:?})", e),
SignetBundleError::MarketError(e) => write!(f, "MarketError({:?})", e),
}
}
}

impl<Db: Database> From<EVMError<Db::Error>> for SignetBundleError<Db> {
fn from(e: EVMError<Db::Error>) -> Self {
SignetBundleError::BundleError(BundleError::EVMError { inner: e })
}
}

impl<Db: Database> SignetBundleError<Db> {
/// Instantiate a new [`SignetBundleError`] from a [`Database::Error`].
pub const fn evm_db(e: Db::Error) -> Self {
SignetBundleError::BundleError(BundleError::EVMError { inner: EVMError::Database(e) })
}
}

/// A bundle driver for the Signet EVM.
///
/// This type allows for the simulation of a [`SignetCallBundle`] and ensuring
/// that it conforms to market rules as a unit.
#[derive(Debug)]
pub struct SignetBundleDriver<'a> {
/// The bundle to drive.
Expand All @@ -57,7 +27,7 @@ pub struct SignetBundleDriver<'a> {
impl<'a> SignetBundleDriver<'a> {
/// Create a new bundle driver with the given bundle and response.
pub fn new(bundle: &'a SignetCallBundle, host_chain_id: u64) -> Self {
let context = bundle.make_context(host_chain_id);
let context = bundle.build_context(host_chain_id);
Self { bundle, response: Default::default(), context, host_chain_id }
}
}
Expand All @@ -84,13 +54,13 @@ impl SignetBundleDriver<'_> {
}

/// Clear the driver, resetting the response and the market context. This
/// reset the driver, allowing for resimulation of the same bundle.
/// resets the driver, allowing for re-simulation of the same bundle.
///
/// The returned context contains the amount of overfill, i.e. the amount
/// that was filled, but not required by the orders in the bundle.
pub fn clear(&mut self) -> (SignetCallBundleResponse, MarketContext) {
let r = std::mem::take(&mut self.response);
let context = self.bundle.make_context(self.host_chain_id);
let context = self.bundle.build_context(self.host_chain_id);
let c = std::mem::replace(&mut self.context, context);
(r, c)
}
Expand Down Expand Up @@ -159,10 +129,12 @@ impl<I> BundleDriver<OrderDetector<I>> for SignetBundleDriver<'_> {

// Check if the block we're in is valid for this bundle. Both must match
trevm_ensure!(
trevm.inner().block().number.to::<u64>() == bundle.block_number,
trevm.block_number().to::<u64>() == bundle.block_number,
trevm,
BundleError::BlockNumberMismatch.into()
);
// Set the state block number this simulation was based on
self.response.state_block_number = trevm.block_number().to::<u64>();

// Check if the state block number is valid (not 0, and not a tag)
trevm_ensure!(
Expand All @@ -177,11 +149,10 @@ impl<I> BundleDriver<OrderDetector<I>> for SignetBundleDriver<'_> {

trevm.try_with_block(self.bundle, |mut trevm| {
// Get the coinbase and basefee from the block
let coinbase = trevm.inner().block().coinbase;
let basefee = trevm.inner().block().basefee;

// Set the state block number this simulation was based on
self.response.state_block_number = trevm.inner().block().number.to::<u64>();
// NB: Do not move these outside the `try_with_block` closure, as
// they may be rewritten by the bundle
let coinbase = trevm.block().coinbase;
let basefee = trevm.block().basefee;

// Cache the pre simulation coinbase balance, so we can use it to calculate the coinbase diff after every tx simulated.
let initial_coinbase_balance = unwrap_or_trevm_err!(
Expand Down
39 changes: 39 additions & 0 deletions crates/bundle/src/call/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use signet_types::MarketError;
use std::fmt::Debug;
use trevm::{
revm::{primitives::EVMError, Database},
BundleError,
};

/// Errors that can occur when running a bundle on the Signet EVM.
#[derive(thiserror::Error)]
pub enum SignetBundleError<Db: Database> {
/// A primitive [`BundleError`] error ocurred.
#[error(transparent)]
BundleError(#[from] BundleError<Db>),
/// A [`MarketError`] ocurred.
#[error(transparent)]
MarketError(#[from] MarketError),
}

impl<Db: Database> Debug for SignetBundleError<Db> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SignetBundleError::BundleError(e) => write!(f, "BundleError({:?})", e),
SignetBundleError::MarketError(e) => write!(f, "MarketError({:?})", e),
}
}
}

impl<Db: Database> From<EVMError<Db::Error>> for SignetBundleError<Db> {
fn from(e: EVMError<Db::Error>) -> Self {
SignetBundleError::BundleError(BundleError::EVMError { inner: e })
}
}

impl<Db: Database> SignetBundleError<Db> {
/// Instantiate a new [`SignetBundleError`] from a [`Database::Error`].
pub const fn evm_db(e: Db::Error) -> Self {
SignetBundleError::BundleError(BundleError::EVMError { inner: EVMError::Database(e) })
}
}
5 changes: 4 additions & 1 deletion crates/bundle/src/call/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
mod driver;
pub use driver::{SignetBundleDriver, SignetBundleError};
pub use driver::SignetBundleDriver;

mod error;
pub use error::SignetBundleError;

mod trevm;

Expand Down
24 changes: 17 additions & 7 deletions crates/bundle/src/call/trevm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,22 @@ use trevm::{revm::primitives::BlockEnv, Block};

impl Block for SignetCallBundle {
fn fill_block_env(&self, block_env: &mut BlockEnv) {
block_env.number =
self.bundle.state_block_number.as_number().map(U256::from).unwrap_or(block_env.number);
block_env.timestamp = self.bundle.timestamp.map(U256::from).unwrap_or(block_env.timestamp);
block_env.gas_limit = self.bundle.gas_limit.map(U256::from).unwrap_or(block_env.gas_limit);
block_env.difficulty =
self.bundle.difficulty.map(U256::from).unwrap_or(block_env.difficulty);
block_env.basefee = self.bundle.base_fee.map(U256::from).unwrap_or(block_env.basefee);
let BlockEnv {
number,
coinbase,
timestamp,
gas_limit,
basefee,
difficulty,
prevrandao: _,
blob_excess_gas_and_price: _,
} = block_env;

*number = self.bundle.state_block_number.as_number().map(U256::from).unwrap_or(*number);
*coinbase = self.bundle.coinbase.unwrap_or(*coinbase);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bugfix is here, coinbase was previously not set

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great catch

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya it's why i recommend destructuring in the implementation guide. easy to forget things

*timestamp = self.bundle.timestamp.map(U256::from).unwrap_or(*timestamp);
*gas_limit = self.bundle.gas_limit.map(U256::from).unwrap_or(*gas_limit);
*difficulty = self.bundle.difficulty.map(U256::from).unwrap_or(*difficulty);
*basefee = self.bundle.base_fee.map(U256::from).unwrap_or(*basefee);
}
}
16 changes: 14 additions & 2 deletions crates/bundle/src/call/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl SignetCallBundle {
}

/// Create a market context from the fills in this bundle.
pub fn make_context(&self, host_chain_id: u64) -> MarketContext {
pub fn build_context(&self, host_chain_id: u64) -> MarketContext {
let mut context = MarketContext::default();
self.host_fills.iter().for_each(|(asset, fills)| {
fills.iter().for_each(|(recipient, amount)| {
Expand Down Expand Up @@ -280,6 +280,18 @@ impl core::ops::DerefMut for SignetCallBundleResponse {
}
}

impl AsRef<EthCallBundleResponse> for SignetCallBundleResponse {
fn as_ref(&self) -> &EthCallBundleResponse {
&self.inner
}
}

impl AsMut<EthCallBundleResponse> for SignetCallBundleResponse {
fn as_mut(&mut self) -> &mut EthCallBundleResponse {
&mut self.inner
}
}

impl From<EthCallBundleResponse> for SignetCallBundleResponse {
fn from(inner: EthCallBundleResponse) -> Self {
Self { inner }
Expand All @@ -294,7 +306,7 @@ impl From<SignetCallBundleResponse> for EthCallBundleResponse {

impl SignetCallBundleResponse {
/// Accumulate a transaction result into the response.
pub fn accumulate_tx_result(&mut self, tx_result: EthCallBundleTransactionResult) {
fn accumulate_tx_result(&mut self, tx_result: EthCallBundleTransactionResult) {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using this instead of accumulate_tx would be incorrect

self.inner.total_gas_used += tx_result.gas_used;
self.inner.gas_fees += tx_result.gas_fees;
self.inner.results.push(tx_result);
Expand Down
Loading