Skip to content

Commit 685a903

Browse files
committed
clippy
1 parent c5918cf commit 685a903

File tree

2 files changed

+147
-100
lines changed

2 files changed

+147
-100
lines changed

src/tasks/submit/flashbots/task.rs

Lines changed: 105 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,24 @@
11
//! Flashbots Task receives simulated blocks from an upstream channel and
22
//! submits them to the Flashbots relay as bundles.
3-
use core::error;
4-
53
use crate::{
64
config::{HostProvider, ZenithInstance},
75
quincey::Quincey,
86
tasks::{
9-
block::sim::{self, SimResult},
10-
submit::flashbots::FlashbotsProvider,
7+
block::sim::SimResult,
8+
submit::{SubmitPrep, flashbots::FlashbotsProvider},
119
},
1210
utils,
1311
};
1412
use alloy::{
1513
consensus::SimpleCoder,
16-
network::{Ethereum, EthereumWallet, TransactionBuilder},
14+
eips::Encodable2718,
1715
primitives::{TxHash, U256},
18-
providers::{Provider, SendableTx, fillers::TxFiller},
19-
rlp::{BytesMut, bytes},
20-
rpc::types::{
21-
TransactionRequest,
22-
mev::{BundleItem, MevSendBundle, ProtocolVersion},
23-
},
16+
rpc::types::mev::{BundleItem, MevSendBundle, ProtocolVersion},
2417
};
2518
use init4_bin_base::deps::tracing::{debug, error};
2619
use signet_constants::SignetSystemConstants;
2720
use signet_types::SignRequest;
28-
use signet_zenith::{
29-
Alloy2718Coder,
30-
Zenith::{BlockHeader, submitBlockCall},
31-
ZenithBlock,
32-
};
21+
use signet_zenith::{Alloy2718Coder, Zenith::BlockHeader, ZenithBlock};
3322
use tokio::{sync::mpsc, task::JoinHandle};
3423

3524
/// Errors that the `FlashbotsTask` can encounter.
@@ -57,28 +46,77 @@ pub struct FlashbotsTask {
5746
pub zenith: ZenithInstance<HostProvider>,
5847
/// Channel for sending hashes of outbound transactions.
5948
pub outbound: mpsc::UnboundedSender<TxHash>,
49+
/// Determines if the BundleHelper contract should be used for block submission.
50+
/// NB: If bundle_helper is not used, instead the Zenith contract
51+
/// submitBlock function is used.
52+
bundle_helper: bool,
6053
}
6154

6255
impl FlashbotsTask {
6356
/// Returns a new `FlashbotsTask` instance that receives `SimResult` types from the given
6457
/// channel and handles their preparation, submission to the Flashbots network.
65-
pub fn new(
58+
pub const fn new(
6659
config: crate::config::BuilderConfig,
6760
constants: SignetSystemConstants,
6861
quincey: Quincey,
6962
zenith: ZenithInstance<HostProvider>,
7063
outbound: mpsc::UnboundedSender<TxHash>,
64+
bundle_helper: bool,
7165
) -> FlashbotsTask {
72-
Self { config, constants, quincey, zenith, outbound }
66+
Self { config, constants, quincey, zenith, outbound, bundle_helper }
7367
}
7468

7569
/// Returns a reference to the inner `HostProvider`
7670
pub fn host_provider(&self) -> HostProvider {
7771
self.zenith.provider().clone()
7872
}
7973

80-
/// Prepares a bundle transaction from the simulation result.
81-
pub async fn prepare_bundle(
74+
/// Prepares a MEV bundle with the configured submit call
75+
pub async fn prepare(&self, sim_result: &SimResult) -> Result<MevSendBundle, FlashbotsError> {
76+
match self.bundle_helper {
77+
true => self.prepare_bundle_helper(sim_result).await,
78+
false => self.prepare_zenith(sim_result).await,
79+
}
80+
}
81+
82+
/// Prepares a BundleHelper call containing the rollup block and corresponding fills into a MEV bundle.
83+
async fn prepare_bundle_helper(
84+
&self,
85+
sim_result: &SimResult,
86+
) -> Result<MevSendBundle, FlashbotsError> {
87+
let mut bundle_body = Vec::new();
88+
89+
let prep = SubmitPrep::new(
90+
&sim_result.block,
91+
self.host_provider(),
92+
self.quincey.clone(),
93+
self.config.clone(),
94+
self.constants.clone(),
95+
);
96+
97+
let tx = prep.prep_transaction(&sim_result.env.prev_header).await.map_err(|err| {
98+
error!(?err, "failed to prepare bumpable transaction");
99+
FlashbotsError::PreparationError(err.to_string())
100+
})?;
101+
102+
let sendable = self.host_provider().fill(tx.req().clone()).await.map_err(|err| {
103+
error!(?err, "failed to fill transaction");
104+
FlashbotsError::PreparationError(err.to_string())
105+
})?;
106+
107+
if let Some(envelope) = sendable.as_envelope() {
108+
bundle_body
109+
.push(BundleItem::Tx { tx: envelope.encoded_2718().into(), can_revert: true });
110+
debug!(tx_hash = ?envelope.hash(), "added filled transaction to bundle");
111+
}
112+
113+
let bundle = MevSendBundle::new(0, Some(0), ProtocolVersion::V0_1, bundle_body);
114+
115+
Ok(bundle)
116+
}
117+
118+
/// Creates a Zenith `submitBlock` transaction and packages it into a MEV bundle from a given simulation result.
119+
async fn prepare_zenith(
82120
&self,
83121
sim_result: &SimResult,
84122
) -> Result<MevSendBundle, FlashbotsError> {
@@ -91,10 +129,10 @@ impl FlashbotsTask {
91129
hostBlockNumber: U256::from(host_block_number),
92130
gasLimit: U256::from(self.config.rollup_block_gas_limit),
93131
rewardAddress: self.config.builder_rewards_address,
94-
blockDataHash: sim_result.block.contents_hash().clone(),
132+
blockDataHash: *sim_result.block.contents_hash(),
95133
};
96134

97-
// Create the raw Zenith block
135+
// Create the raw Zenith block from the header
98136
let block =
99137
ZenithBlock::<Alloy2718Coder>::new(header, sim_result.block.transactions().to_vec());
100138

@@ -104,7 +142,7 @@ impl FlashbotsTask {
104142
FlashbotsError::PreparationError(err.to_string())
105143
})?;
106144

107-
// Sign the block
145+
// Sign the rollup block contents
108146
let signature = self
109147
.quincey
110148
.get_signature(&SignRequest {
@@ -113,44 +151,62 @@ impl FlashbotsTask {
113151
ru_chain_id: U256::from(self.constants.ru_chain_id()),
114152
gas_limit: U256::from(self.config.rollup_block_gas_limit),
115153
ru_reward_address: self.config.builder_rewards_address,
116-
contents: sim_result.block.contents_hash().clone(),
154+
contents: *sim_result.block.contents_hash(),
117155
})
118156
.await
119157
.map_err(|err| {
120158
error!(?err, "failed to get signature for block");
121159
FlashbotsError::PreparationError(err.to_string())
122160
})?;
123161

124-
// Extract v, r, and s values from the signature
162+
// Extract the v, r, and s values from the signature
125163
let (v, r, s) = utils::extract_signature_components(&signature.sig);
126164

127-
// Create the Zenith submit block call transaction and attach the sidecar to it
128-
let submit_block_call = self
129-
.zenith
130-
.submitBlock(header, v, r, s, block.encoded_txns().to_vec().into())
131-
.sidecar(sidecar);
132-
133-
// Create the MEV bundle from the target block and bundle body
165+
// Create a MEV bundle and add the host fills to it
134166
let mut bundle_body = Vec::new();
135-
136-
// Add host fills to the MEV bundle
137167
let host_fills = sim_result.block.host_fills();
138168
for fill in host_fills {
139-
let tx = fill.to_fill_tx(self.constants.ru_orders());
140-
let filled_tx = self.zenith.provider().fill(tx.into()).await.map_err(|err| {
169+
// Create a host fill transaction with the rollup orders contract and sign it
170+
let tx_req = fill.to_fill_tx(self.constants.ru_orders());
171+
let sendable = self.host_provider().fill(tx_req).await.map_err(|err| {
141172
error!(?err, "failed to fill transaction");
142173
FlashbotsError::PreparationError(err.to_string())
143174
})?;
175+
176+
// Add them to the MEV bundle
177+
if let Some(envelope) = sendable.as_envelope() {
178+
bundle_body
179+
.push(BundleItem::Tx { tx: envelope.encoded_2718().into(), can_revert: true });
180+
debug!(tx_hash = ?envelope.hash(), "added filled transaction to MEV bundle");
181+
}
144182
}
145183

146-
// TODO: Then add the submit block tx
147-
// bundle_body.push(submit_block_call.into_transaction_request());
184+
// Create the Zenith submit block call transaction and attach the sidecar to it
185+
let submit_block_call = self
186+
.zenith
187+
.submitBlock(header, v, r, s, block.encoded_txns().to_vec().into())
188+
.sidecar(sidecar);
189+
190+
// Create the transaction request for the submit call
191+
let rollup_tx = submit_block_call.into_transaction_request();
192+
let signed = self.host_provider().fill(rollup_tx).await.map_err(|err| {
193+
error!(?err, "failed to sign rollup transaction");
194+
FlashbotsError::PreparationError(err.to_string())
195+
})?;
196+
197+
// Sign the rollup block tx and add it to the MEV bundle as the last transaction.
198+
if let Some(envelope) = signed.as_envelope() {
199+
bundle_body
200+
.push(BundleItem::Tx { tx: envelope.encoded_2718().into(), can_revert: false });
201+
debug!(tx_hash = ?envelope.hash(), "added rollup transaction to MEV bundle");
202+
}
148203

204+
// Create the MEV bundle and return it
149205
let bundle = MevSendBundle::new(
150206
target_block,
151207
Some(target_block),
152208
ProtocolVersion::V0_1,
153-
bundle_body, // TODO: Fill with host_fills, then add the rollup transaction
209+
bundle_body,
154210
);
155211

156212
Ok(bundle)
@@ -160,31 +216,26 @@ impl FlashbotsTask {
160216
async fn task_future(self, mut inbound: mpsc::UnboundedReceiver<SimResult>) {
161217
debug!("starting flashbots task");
162218

163-
let zenith = self.config.connect_zenith(self.host_provider());
164-
165-
let flashbots = FlashbotsProvider::new(
166-
self.config.flashbots_endpoint.clone(), // TODO: Handle proper Option checks here
167-
zenith,
168-
&self.config,
169-
);
219+
let flashbots = FlashbotsProvider::new(&self.config);
170220

171221
loop {
222+
// Wait for a sim result to come in
172223
let Some(sim_result) = inbound.recv().await else {
173224
debug!("upstream task gone - exiting flashbots task");
174225
break;
175226
};
176227
debug!(?sim_result.env.block_env.number, "simulation block received");
177228

178-
// Prepare the Flashbots bundle from the SimResult, skipping on error.
179-
let bundle = match self.prepare_bundle(&sim_result).await {
180-
Ok(b) => b,
181-
Err(err) => {
182-
error!(?err, "bundle preparation failed");
183-
continue;
184-
}
229+
// Prepare a MEV bundle with the configured call type from the sim result
230+
let bundle = if let Ok(bundle) = self.prepare(&sim_result).await {
231+
debug!("bundle prepared");
232+
bundle
233+
} else {
234+
debug!("bundle preparation failed");
235+
continue;
185236
};
186237

187-
// simulate then send the bundle
238+
// simulate the bundle against Flashbots then send the bundle
188239
let sim_bundle_result = flashbots.simulate_bundle(bundle.clone()).await;
189240
match sim_bundle_result {
190241
Ok(_) => {

tests/flashbots_provider_test.rs

Lines changed: 42 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,54 @@
11
//! Integration tests for the FlashbotsProvider.
22
//! These tests require the `FLASHBOTS_ENDPOINT` env var to be set.
3-
#[cfg(test)]
4-
mod tests {
5-
use builder::tasks::submit::flashbots::FlashbotsProvider;
6-
use alloy::{
7-
primitives::FixedBytes,
8-
rpc::types::mev::{EthBundleHash, MevSendBundle},
9-
};
10-
use builder::test_utils::{setup_logging, setup_test_config};
11-
12-
#[tokio::test]
13-
#[ignore = "integration test"]
14-
async fn smoke_root_provider() {
15-
setup_logging();
16-
let flashbots = get_test_provider().await;
17-
assert_eq!(flashbots.relay_url.as_str(), "http://localhost:9062/");
18-
19-
let status = flashbots
20-
.bundle_status(EthBundleHash { bundle_hash: FixedBytes::default() }, 0)
21-
.await;
22-
assert!(status.is_err());
23-
}
243
25-
#[tokio::test]
26-
#[ignore = "integration test"]
27-
async fn smoke_simulate_bundle() {
28-
let flashbots = get_test_provider().await;
4+
use builder::tasks::submit::flashbots::FlashbotsProvider;
5+
use alloy::{
6+
primitives::FixedBytes,
7+
rpc::types::mev::{EthBundleHash, MevSendBundle},
8+
};
9+
use builder::test_utils::{setup_logging, setup_test_config};
10+
11+
#[tokio::test]
12+
#[ignore = "integration test"]
13+
async fn smoke_root_provider() {
14+
setup_logging();
15+
let flashbots = get_test_provider().await;
16+
assert_eq!(flashbots.relay_url.as_str(), "http://localhost:9062/");
17+
18+
let status = flashbots
19+
.bundle_status(EthBundleHash { bundle_hash: FixedBytes::default() }, 0)
20+
.await;
21+
assert!(status.is_err());
22+
}
2923

30-
let res = flashbots.simulate_bundle(MevSendBundle::default()).await;
24+
#[tokio::test]
25+
#[ignore = "integration test"]
26+
async fn smoke_simulate_bundle() {
27+
let flashbots = get_test_provider().await;
3128

32-
if let Err(err) = &res {
33-
let msg = format!("{err}");
34-
assert!(msg.contains("mev_simBundle"));
35-
}
29+
let res = flashbots.simulate_bundle(MevSendBundle::default()).await;
3630

37-
assert!(res.is_err());
31+
if let Err(err) = &res {
32+
let msg = format!("{err}");
33+
assert!(msg.contains("mev_simBundle"));
3834
}
35+
assert!(res.is_err());
36+
}
3937

40-
#[tokio::test]
41-
#[ignore = "integration test"]
42-
async fn smoke_send_bundle() {
43-
let flashbots = get_test_provider().await;
44-
let res = flashbots.send_bundle(MevSendBundle::default()).await;
45-
46-
if let Err(err) = &res {
47-
let msg = format!("{err}");
48-
assert!(msg.contains("mev_sendBundle"));
49-
}
38+
#[tokio::test]
39+
#[ignore = "integration test"]
40+
async fn smoke_send_bundle() {
41+
let flashbots = get_test_provider().await;
42+
let res = flashbots.send_bundle(MevSendBundle::default()).await;
5043

51-
assert!(res.is_ok() || res.is_err());
44+
if let Err(err) = &res {
45+
let msg = format!("{err}");
46+
assert!(msg.contains("mev_sendBundle"));
5247
}
48+
assert!(res.is_ok() || res.is_err());
49+
}
5350

54-
async fn get_test_provider() -> FlashbotsProvider {
55-
let config = setup_test_config().unwrap();
56-
FlashbotsProvider::new(&config.clone())
57-
}
51+
async fn get_test_provider() -> FlashbotsProvider {
52+
let config = setup_test_config().unwrap();
53+
FlashbotsProvider::new(&config.clone())
5854
}

0 commit comments

Comments
 (0)