Skip to content

Commit 89a0889

Browse files
committed
move simumlation calls to builder tx
1 parent c6bee14 commit 89a0889

File tree

3 files changed

+174
-33
lines changed

3 files changed

+174
-33
lines changed

crates/op-rbuilder/src/builders/builder_tx.rs

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use alloy_consensus::TxEip1559;
1+
use alloy_consensus::{Transaction, TxEip1559};
22
use alloy_eips::{Encodable2718, eip7623::TOTAL_COST_FLOOR_PER_TOKEN};
33
use alloy_evm::Database;
44
use alloy_op_evm::OpEvm;
@@ -387,6 +387,84 @@ pub trait BuilderTransactions<ExtraCtx: Debug + Default = (), Extra: Debug + Def
387387
}
388388
}
389389
}
390+
391+
fn sign_tx(
392+
&self,
393+
to: Address,
394+
from: Signer,
395+
gas_used: Option<u64>,
396+
calldata: Bytes,
397+
ctx: &OpPayloadBuilderCtx<ExtraCtx>,
398+
db: &mut State<impl Database>,
399+
) -> Result<Recovered<OpTransactionSigned>, BuilderTransactionError> {
400+
let nonce = get_nonce(db, from.address)?;
401+
// Create the EIP-1559 transaction
402+
let tx = OpTypedTransaction::Eip1559(TxEip1559 {
403+
chain_id: ctx.chain_id(),
404+
nonce,
405+
// Due to EIP-150, 63/64 of available gas is forwarded to external calls so need to add a buffer
406+
gas_limit: gas_used
407+
.map(|gas| gas * 64 / 63)
408+
.unwrap_or(ctx.block_gas_limit()),
409+
max_fee_per_gas: ctx.base_fee().into(),
410+
to: TxKind::Call(to),
411+
input: calldata,
412+
..Default::default()
413+
});
414+
Ok(from.sign_tx(tx)?)
415+
}
416+
417+
fn simulate_call(
418+
&self,
419+
signed_tx: Recovered<OpTransactionSigned>,
420+
expected_topic: Option<B256>,
421+
revert_handler: impl FnOnce(Bytes) -> BuilderTransactionError,
422+
evm: &mut OpEvm<
423+
&mut State<StateProviderDatabase<impl StateProvider>>,
424+
NoOpInspector,
425+
PrecompilesMap,
426+
>,
427+
) -> Result<SimulationSuccessResult, BuilderTransactionError> {
428+
let ResultAndState { result, state } = match evm.transact(&signed_tx) {
429+
Ok(res) => res,
430+
Err(err) => {
431+
if err.is_invalid_tx_err() {
432+
return Err(BuilderTransactionError::InvalidTransactionError(Box::new(
433+
err,
434+
)));
435+
} else {
436+
return Err(BuilderTransactionError::EvmExecutionError(Box::new(err)));
437+
}
438+
}
439+
};
440+
441+
match result {
442+
ExecutionResult::Success {
443+
logs,
444+
gas_used,
445+
output,
446+
..
447+
} => {
448+
if let Some(topic) = expected_topic
449+
&& !logs.iter().any(|log| log.topics().first() == Some(&topic))
450+
{
451+
return Err(BuilderTransactionError::InvalidContract(
452+
signed_tx.to().unwrap_or_default(),
453+
InvalidContractDataError::InvalidLogs(topic),
454+
));
455+
}
456+
Ok(SimulationSuccessResult {
457+
gas_used,
458+
output: output.into_data(),
459+
state_changes: state,
460+
})
461+
}
462+
ExecutionResult::Revert { output, .. } => Err(revert_handler(output)),
463+
ExecutionResult::Halt { reason, .. } => Err(BuilderTransactionError::other(
464+
BuilderTransactionError::TransactionHalted(reason),
465+
)),
466+
}
467+
}
390468
}
391469

392470
#[derive(Debug, Clone)]

crates/op-rbuilder/src/flashtestations/builder_tx.rs

Lines changed: 95 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -374,9 +374,13 @@ where
374374
}
375375
.abi_encode();
376376
let SimulationSuccessResult { output, .. } =
377-
self.simulate_call(contract_address, calldata.into(), None, ctx, evm)?;
378-
U256::abi_decode(&output)
379-
.map_err(|_| BuilderTransactionError::InvalidContract(contract_address))
377+
self.simulate_flashtestation_call(contract_address, calldata, None, ctx, evm)?;
378+
U256::abi_decode(&output).map_err(|_| {
379+
BuilderTransactionError::InvalidContract(
380+
contract_address,
381+
InvalidContractDataError::OutputAbiDecodeError,
382+
)
383+
})
380384
}
381385

382386
fn registration_permit_signature(
@@ -396,28 +400,36 @@ where
396400
deadline: U256::from(ctx.timestamp()),
397401
}
398402
.abi_encode();
399-
let SimulationSuccessResult { output, .. } = self.simulate_call(
403+
let SimulationSuccessResult { output, .. } = self.simulate_flashtestation_call(
400404
self.registry_address,
401-
struct_hash_calldata.into(),
405+
struct_hash_calldata,
402406
None,
403407
ctx,
404408
evm,
405409
)?;
406-
let struct_hash = B256::abi_decode(&output)
407-
.map_err(|_| BuilderTransactionError::InvalidContract(self.registry_address))?;
410+
let struct_hash = B256::abi_decode(&output).map_err(|_| {
411+
BuilderTransactionError::InvalidContract(
412+
self.registry_address,
413+
InvalidContractDataError::OutputAbiDecodeError,
414+
)
415+
})?;
408416
let typed_data_hash_calldata = IFlashtestationRegistry::hashTypedDataV4Call {
409417
structHash: struct_hash,
410418
}
411419
.abi_encode();
412-
let SimulationSuccessResult { output, .. } = self.simulate_call(
420+
let SimulationSuccessResult { output, .. } = self.simulate_flashtestation_call(
413421
self.registry_address,
414-
typed_data_hash_calldata.into(),
422+
typed_data_hash_calldata,
415423
None,
416424
ctx,
417425
evm,
418426
)?;
419-
let typed_data_hash = B256::abi_decode(&output)
420-
.map_err(|_| BuilderTransactionError::InvalidContract(self.registry_address))?;
427+
let typed_data_hash = B256::abi_decode(&output).map_err(|_| {
428+
BuilderTransactionError::InvalidContract(
429+
self.registry_address,
430+
InvalidContractDataError::OutputAbiDecodeError,
431+
)
432+
})?;
421433
let signature = self.tee_service_signer.sign_message(typed_data_hash)?;
422434
Ok(signature)
423435
}
@@ -441,17 +453,17 @@ where
441453
signature: signature.as_bytes().into(),
442454
}
443455
.abi_encode();
444-
let SimulationSuccessResult { gas_used, .. } = self.simulate_call(
456+
let SimulationSuccessResult { gas_used, .. } = self.simulate_flashtestation_call(
445457
self.registry_address,
446-
calldata.clone().into(),
458+
calldata.clone(),
447459
Some(TEEServiceRegistered::SIGNATURE_HASH),
448460
ctx,
449461
evm,
450462
)?;
451463
let signed_tx = self.sign_tx(
452464
self.registry_address,
453-
self.builder_key,
454-
gas_used,
465+
self.builder_signer,
466+
Some(gas_used),
455467
calldata.into(),
456468
ctx,
457469
evm.db_mut(),
@@ -483,28 +495,36 @@ where
483495
nonce: permit_nonce,
484496
}
485497
.abi_encode();
486-
let SimulationSuccessResult { output, .. } = self.simulate_call(
498+
let SimulationSuccessResult { output, .. } = self.simulate_flashtestation_call(
487499
self.builder_policy_address,
488-
struct_hash_calldata.into(),
500+
struct_hash_calldata,
489501
None,
490502
ctx,
491503
evm,
492504
)?;
493-
let struct_hash = B256::abi_decode(&output)
494-
.map_err(|_| BuilderTransactionError::InvalidContract(self.builder_policy_address))?;
505+
let struct_hash = B256::abi_decode(&output).map_err(|_| {
506+
BuilderTransactionError::InvalidContract(
507+
self.builder_policy_address,
508+
InvalidContractDataError::OutputAbiDecodeError,
509+
)
510+
})?;
495511
let typed_data_hash_calldata = IBlockBuilderPolicy::getHashedTypeDataV4Call {
496512
structHash: struct_hash,
497513
}
498514
.abi_encode();
499-
let SimulationSuccessResult { output, .. } = self.simulate_call(
515+
let SimulationSuccessResult { output, .. } = self.simulate_flashtestation_call(
500516
self.builder_policy_address,
501-
typed_data_hash_calldata.into(),
517+
typed_data_hash_calldata,
502518
None,
503519
ctx,
504520
evm,
505521
)?;
506-
let typed_data_hash = B256::abi_decode(&output)
507-
.map_err(|_| BuilderTransactionError::InvalidContract(self.builder_policy_address))?;
522+
let typed_data_hash = B256::abi_decode(&output).map_err(|_| {
523+
BuilderTransactionError::InvalidContract(
524+
self.builder_policy_address,
525+
InvalidContractDataError::OutputAbiDecodeError,
526+
)
527+
})?;
508528
let signature = self.tee_service_signer.sign_message(typed_data_hash)?;
509529
Ok(signature)
510530
}
@@ -535,17 +555,17 @@ where
535555
eip712Sig: signature.as_bytes().into(),
536556
}
537557
.abi_encode();
538-
let SimulationSuccessResult { gas_used, .. } = self.simulate_call(
558+
let SimulationSuccessResult { gas_used, .. } = self.simulate_flashtestation_call(
539559
self.builder_policy_address,
540-
calldata.clone().into(),
560+
calldata.clone(),
541561
Some(BlockBuilderProofVerified::SIGNATURE_HASH),
542562
ctx,
543563
evm,
544564
)?;
545565
let signed_tx = self.sign_tx(
546566
self.builder_policy_address,
547-
self.builder_key,
548-
gas_used,
567+
self.builder_signer,
568+
Some(gas_used),
549569
calldata.into(),
550570
ctx,
551571
evm.db_mut(),
@@ -559,6 +579,54 @@ where
559579
is_top_of_block: false,
560580
})
561581
}
582+
583+
fn simulate_flashtestation_call(
584+
&self,
585+
contract_address: Address,
586+
calldata: Vec<u8>,
587+
expected_topic: Option<B256>,
588+
ctx: &OpPayloadBuilderCtx<ExtraCtx>,
589+
evm: &mut OpEvm<
590+
&mut State<StateProviderDatabase<impl StateProvider>>,
591+
NoOpInspector,
592+
PrecompilesMap,
593+
>,
594+
) -> Result<SimulationSuccessResult, BuilderTransactionError> {
595+
let signed_tx = self.sign_tx(
596+
contract_address,
597+
self.builder_signer,
598+
None,
599+
calldata.into(),
600+
ctx,
601+
evm.db_mut(),
602+
)?;
603+
let revert_handler = if contract_address == self.registry_address {
604+
Self::handle_registry_reverts
605+
} else {
606+
Self::handle_block_builder_policy_reverts
607+
};
608+
self.simulate_call(signed_tx, expected_topic, revert_handler, evm)
609+
}
610+
611+
fn handle_registry_reverts(revert_output: Bytes) -> BuilderTransactionError {
612+
let revert_reason =
613+
IFlashtestationRegistry::IFlashtestationRegistryErrors::abi_decode(&revert_output)
614+
.map(FlashtestationRevertReason::FlashtestationRegistry)
615+
.unwrap_or_else(|_| {
616+
FlashtestationRevertReason::Unknown(hex::encode(revert_output))
617+
});
618+
BuilderTransactionError::TransactionReverted(Box::new(revert_reason))
619+
}
620+
621+
fn handle_block_builder_policy_reverts(revert_output: Bytes) -> BuilderTransactionError {
622+
let revert_reason =
623+
IBlockBuilderPolicy::IBlockBuilderPolicyErrors::abi_decode(&revert_output)
624+
.map(FlashtestationRevertReason::BlockBuilderPolicy)
625+
.unwrap_or_else(|_| {
626+
FlashtestationRevertReason::Unknown(hex::encode(revert_output))
627+
});
628+
BuilderTransactionError::TransactionReverted(Box::new(revert_reason))
629+
}
562630
}
563631

564632
impl<ExtraCtx, Extra> BuilderTransactions<ExtraCtx, Extra>

crates/op-rbuilder/src/flashtestations/mod.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,6 @@ sol!(
115115
}
116116

117117
type WorkloadId is bytes32;
118-
119-
120-
interface IERC20Permit {
121-
function nonces(address owner) external view returns (uint256);
122-
}
123118
);
124119

125120
pub mod args;

0 commit comments

Comments
 (0)