diff --git a/crates/core/CHANGELOG.md b/crates/core/CHANGELOG.md index 73b959da..2efdaa97 100644 --- a/crates/core/CHANGELOG.md +++ b/crates/core/CHANGELOG.md @@ -7,7 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased -- refactored `Contender` to use a typestate-based lifecycle instead of the runtime `ContenderState` enum ([#507](https://github.com/flashbots/contender/pull/507)) +- save errors to db in NilCallback ([#511](https://github.com/flashbots/contender/pull/511/changes)) +- refactored `Contender` to use a typestate-based lifecycle instead of the runtime `ContenderState` enum ([#507](https://github.com/flashbots/contender/pull/507/changes)) - `Contender` is now generic over a `State` parameter (defaults to `Uninitialized`) - `initialize(self)` consumes the uninitialized contender and returns `Contender<..., Initialized<...>>` - `spam`, `fund_accounts`, `scenario`, and `scenario_mut` are only callable on `Contender<..., Initialized<...>>` diff --git a/crates/core/src/spammer/tx_callback.rs b/crates/core/src/spammer/tx_callback.rs index 6db16fc8..7f467e74 100644 --- a/crates/core/src/spammer/tx_callback.rs +++ b/crates/core/src/spammer/tx_callback.rs @@ -206,12 +206,30 @@ fn join_callback_handles( impl OnTxSent for NilCallback { fn on_tx_sent( &self, - _tx_res: PendingTransactionConfig, + tx_res: PendingTransactionConfig, _req: &NamedTxRequest, - _extra: RuntimeTxInfo, - _tx_handlers: Option>>, + extra: RuntimeTxInfo, + tx_handlers: Option>>, ) -> Option>> { - // do nothing + // Even when receipts are disabled, record txs that failed to send + // so "insufficient funds" and similar errors appear in the DB. + if extra.error.is_some() { + if let Some(tx_actors) = tx_handlers { + let handle = crate::spawn_with_session(async move { + let tx_actor = tx_actors["default"].clone(); + let tx = CacheTx { + tx_hash: *tx_res.tx_hash(), + start_timestamp_ms: extra.start_timestamp_ms, + end_timestamp_ms: extra.end_timestamp_ms, + kind: extra.kind, + error: extra.error, + }; + let _ = tx_actor.cache_run_tx(tx).await; + Ok(()) + }); + return Some(handle); + } + } None } }