diff --git a/crates/op-rbuilder/src/builders/builder_tx.rs b/crates/op-rbuilder/src/builders/builder_tx.rs index b79200d4e..a8ba3bd80 100644 --- a/crates/op-rbuilder/src/builders/builder_tx.rs +++ b/crates/op-rbuilder/src/builders/builder_tx.rs @@ -2,7 +2,7 @@ use alloy_consensus::TxEip1559; use alloy_eips::{Encodable2718, eip7623::TOTAL_COST_FLOOR_PER_TOKEN}; use alloy_evm::Database; use alloy_primitives::{ - Address, TxKind, + Address, B256, Log, TxKind, map::foldhash::{HashSet, HashSetExt}, }; use core::fmt::Debug; @@ -30,7 +30,22 @@ use crate::{ pub struct BuilderTransactionCtx { pub gas_used: u64, pub da_size: u64, - pub signed_tx: Option>, + pub signed_tx: Recovered, + // whether the transaction should be a top of block or + // bottom of block transaction + pub is_top_of_block: bool, +} + +impl BuilderTransactionCtx { + pub fn set_top_of_block(mut self) -> Self { + self.is_top_of_block = true; + self + } + + pub fn set_bottom_of_block(mut self) -> Self { + self.is_top_of_block = false; + self + } } /// Possible error variants during construction of builder txs. @@ -80,7 +95,6 @@ pub trait BuilderTransactions: Debug { info: &mut ExecutionInfo, ctx: &OpPayloadBuilderCtx, db: &mut State, - top_of_block: bool, ) -> Result, BuilderTransactionError>; fn add_builder_txs( @@ -98,30 +112,26 @@ pub trait BuilderTransactions: Debug { let mut invalid: HashSet
= HashSet::new(); - let builder_txs = self.simulate_builder_txs( - state_provider, - info, - builder_ctx, - evm.db_mut(), - top_of_block, - )?; + let builder_txs = + self.simulate_builder_txs(state_provider, info, builder_ctx, evm.db_mut())?; for builder_tx in builder_txs.iter() { - let signed_tx = match builder_tx.signed_tx.clone() { - Some(tx) => tx, - None => continue, - }; - if invalid.contains(&signed_tx.signer()) { - warn!(target: "payload_builder", tx_hash = ?signed_tx.tx_hash(), "builder signer invalid as previous builder tx reverted"); + if builder_tx.is_top_of_block != top_of_block { + // don't commit tx if the buidler tx is not being added in the intended + // position in the block + continue; + } + if invalid.contains(&builder_tx.signed_tx.signer()) { + warn!(target: "payload_builder", tx_hash = ?builder_tx.signed_tx.tx_hash(), "builder signer invalid as previous builder tx reverted"); continue; } let ResultAndState { result, state } = evm - .transact(&signed_tx) + .transact(&builder_tx.signed_tx) .map_err(|err| BuilderTransactionError::EvmExecutionError(Box::new(err)))?; if !result.is_success() { - warn!(target: "payload_builder", tx_hash = ?signed_tx.tx_hash(), "builder tx reverted"); - invalid.insert(signed_tx.signer()); + warn!(target: "payload_builder", tx_hash = ?builder_tx.signed_tx.tx_hash(), "builder tx reverted"); + invalid.insert(builder_tx.signed_tx.signer()); continue; } @@ -130,7 +140,7 @@ pub trait BuilderTransactions: Debug { info.cumulative_gas_used += gas_used; let ctx = ReceiptBuilderCtx { - tx: signed_tx.inner(), + tx: builder_tx.signed_tx.inner(), evm: &evm, result, state: &state, @@ -142,9 +152,9 @@ pub trait BuilderTransactions: Debug { evm.db_mut().commit(state); // Append sender and transaction to the respective lists - info.executed_senders.push(signed_tx.signer()); + info.executed_senders.push(builder_tx.signed_tx.signer()); info.executed_transactions - .push(signed_tx.clone().into_inner()); + .push(builder_tx.signed_tx.clone().into_inner()); } // Release the db reference by dropping evm @@ -172,12 +182,8 @@ pub trait BuilderTransactions: Debug { .evm_with_env(&mut simulation_state, ctx.evm_env.clone()); for builder_tx in builder_txs { - let signed_tx = match builder_tx.signed_tx.clone() { - Some(tx) => tx, - None => continue, - }; let ResultAndState { state, .. } = evm - .transact(&signed_tx) + .transact(&builder_tx.signed_tx) .map_err(|err| BuilderTransactionError::EvmExecutionError(Box::new(err)))?; evm.db_mut().commit(state); @@ -214,7 +220,8 @@ impl BuilderTxBase { Ok(Some(BuilderTransactionCtx { gas_used, da_size, - signed_tx: Some(signed_tx), + signed_tx, + is_top_of_block: false, })) } None => Ok(None), @@ -276,7 +283,7 @@ impl BuilderTxBase { } } -pub(super) fn get_nonce( +pub(crate) fn get_nonce( db: &mut State, address: Address, ) -> Result { @@ -284,3 +291,7 @@ pub(super) fn get_nonce( .map(|acc| acc.account_info().unwrap_or_default().nonce) .map_err(|_| BuilderTransactionError::AccountLoadFailed(address)) } + +pub(crate) fn log_exists(logs: &[Log], topic: &B256) -> bool { + logs.iter().any(|log| log.topics().first() == Some(topic)) +} diff --git a/crates/op-rbuilder/src/builders/flashblocks/builder_tx.rs b/crates/op-rbuilder/src/builders/flashblocks/builder_tx.rs index 3445bb2e5..7588dd4e3 100644 --- a/crates/op-rbuilder/src/builders/flashblocks/builder_tx.rs +++ b/crates/op-rbuilder/src/builders/flashblocks/builder_tx.rs @@ -2,8 +2,8 @@ use alloy_consensus::TxEip1559; use alloy_eips::Encodable2718; use alloy_evm::{Database, Evm}; use alloy_op_evm::OpEvm; -use alloy_primitives::{Address, Bytes, TxKind, U256}; -use alloy_sol_types::{SolCall, SolError, sol}; +use alloy_primitives::{Address, B256, TxKind}; +use alloy_sol_types::{Error, SolCall, SolEvent, SolInterface, sol}; use core::fmt::Debug; use op_alloy_consensus::OpTypedTransaction; use op_revm::OpHaltReason; @@ -21,7 +21,7 @@ use tracing::warn; use crate::{ builders::{ BuilderTransactionCtx, BuilderTransactionError, BuilderTransactions, - builder_tx::{BuilderTxBase, get_nonce}, + builder_tx::{BuilderTxBase, get_nonce, log_exists}, context::OpPayloadBuilderCtx, flashblocks::payload::FlashblocksExtraCtx, }, @@ -33,62 +33,34 @@ use crate::{ sol!( // From https://github.com/Uniswap/flashblocks_number_contract/blob/main/src/FlashblockNumber.sol #[sol(rpc, abi)] + #[derive(Debug)] interface IFlashblockNumber { function incrementFlashblockNumber() external; - } - // @notice Emitted when flashblock index is incremented - // @param newFlashblockIndex The new flashblock index (0-indexed within each L2 block) - event FlashblockIncremented(uint256 newFlashblockIndex); + // @notice Emitted when flashblock index is incremented + // @param newFlashblockIndex The new flashblock index (0-indexed within each L2 block) + event FlashblockIncremented(uint256 newFlashblockIndex); - /// ----------------------------------------------------------------------- - /// Errors - /// ----------------------------------------------------------------------- - error NonBuilderAddress(address addr); - error MismatchedFlashblockNumber(uint256 expectedFlashblockNumber, uint256 actualFlashblockNumber); + /// ----------------------------------------------------------------------- + /// Errors + /// ----------------------------------------------------------------------- + error NonBuilderAddress(address addr); + error MismatchedFlashblockNumber(uint256 expectedFlashblockNumber, uint256 actualFlashblockNumber); + } ); #[derive(Debug, thiserror::Error)] pub(super) enum FlashblockNumberError { - #[error("non builder address: {0}")] - NonBuilderAddress(Address), - #[error("mismatched flashblock number: expected {0}, actual {1}")] - MismatchedFlashblockNumber(U256, U256), - #[error("unknown revert: {0}")] - Unknown(String), + #[error("flashblocks number contract tx reverted: {0:?}")] + Revert(IFlashblockNumber::IFlashblockNumberErrors), + #[error("contract may be invalid, mismatch in log emitted: expected {0:?}")] + LogMismatch(B256), + #[error("unknown revert: {0} err: {1}")] + Unknown(String, Error), #[error("halt: {0:?}")] Halt(OpHaltReason), } -impl From for FlashblockNumberError { - fn from(value: Bytes) -> Self { - // Empty revert - if value.is_empty() { - return FlashblockNumberError::Unknown( - "Transaction reverted without reason".to_string(), - ); - } - - // Try to decode each custom error type - if let Ok(NonBuilderAddress { addr }) = NonBuilderAddress::abi_decode(&value) { - return FlashblockNumberError::NonBuilderAddress(addr); - } - - if let Ok(MismatchedFlashblockNumber { - expectedFlashblockNumber, - actualFlashblockNumber, - }) = MismatchedFlashblockNumber::abi_decode(&value) - { - return FlashblockNumberError::MismatchedFlashblockNumber( - expectedFlashblockNumber, - actualFlashblockNumber, - ); - } - - FlashblockNumberError::Unknown(hex::encode(value)) - } -} - // This will be the end of block transaction of a regular block #[derive(Debug, Clone)] pub(super) struct FlashblocksBuilderTx { @@ -116,7 +88,6 @@ impl BuilderTransactions for FlashblocksBuilderTx { info: &mut ExecutionInfo, ctx: &OpPayloadBuilderCtx, db: &mut State, - top_of_block: bool, ) -> Result, BuilderTransactionError> { let mut builder_txs = Vec::::new(); @@ -126,24 +97,14 @@ impl BuilderTransactions for FlashblocksBuilderTx { } if ctx.is_last_flashblock() { - let flashblocks_builder_tx = self.base_builder_tx.simulate_builder_tx(ctx, db)?; - if let Some(tx) = flashblocks_builder_tx.clone() { - if top_of_block { - // don't commit the builder if top of block, we only return the gas used to reserve gas for the builder tx - builder_txs.push(BuilderTransactionCtx { - gas_used: tx.gas_used, - da_size: tx.da_size, - signed_tx: None, - }); - } else { - builder_txs.push(tx); - } - } + let base_tx = self.base_builder_tx.simulate_builder_tx(ctx, db)?; + builder_txs.extend(base_tx.clone()); + if let Some(flashtestations_builder_tx) = &self.flashtestations_builder_tx { // We only include flashtestations txs in the last flashblock let mut simulation_state = self.simulate_builder_txs_state::( state_provider.clone(), - flashblocks_builder_tx.iter().collect(), + base_tx.iter().collect(), ctx, db, )?; @@ -152,7 +113,6 @@ impl BuilderTransactions for FlashblocksBuilderTx { info, ctx, &mut simulation_state, - top_of_block, )?; builder_txs.extend(flashtestations_builder_txs); } @@ -205,10 +165,27 @@ impl FlashblocksNumberBuilderTx { }; match result { - ExecutionResult::Success { gas_used, .. } => Ok(gas_used), - ExecutionResult::Revert { output, .. } => Err(BuilderTransactionError::Other( - Box::new(FlashblockNumberError::from(output)), - )), + ExecutionResult::Success { gas_used, logs, .. } => { + if log_exists( + &logs, + &IFlashblockNumber::FlashblockIncremented::SIGNATURE_HASH, + ) { + Ok(gas_used) + } else { + Err(BuilderTransactionError::Other(Box::new( + FlashblockNumberError::LogMismatch( + IFlashblockNumber::FlashblockIncremented::SIGNATURE_HASH, + ), + ))) + } + } + ExecutionResult::Revert { output, .. } => { + Err(BuilderTransactionError::Other(Box::new( + IFlashblockNumber::IFlashblockNumberErrors::abi_decode(&output) + .map(FlashblockNumberError::Revert) + .unwrap_or_else(|e| FlashblockNumberError::Unknown(hex::encode(output), e)), + ))) + } ExecutionResult::Halt { reason, .. } => Err(BuilderTransactionError::Other(Box::new( FlashblockNumberError::Halt(reason), ))), @@ -245,7 +222,6 @@ impl BuilderTransactions for FlashblocksNumberBuilderTx { info: &mut ExecutionInfo, ctx: &OpPayloadBuilderCtx, db: &mut State, - top_of_block: bool, ) -> Result, BuilderTransactionError> { let mut builder_txs = Vec::::new(); let state = StateProviderDatabase::new(state_provider.clone()); @@ -256,8 +232,8 @@ impl BuilderTransactions for FlashblocksNumberBuilderTx { .build(); if ctx.is_first_flashblock() { - let flashblocks_builder_tx = self.base_builder_tx.simulate_builder_tx(ctx, db)?; - builder_txs.extend(flashblocks_builder_tx.clone()); + // fallback block builder tx + builder_txs.extend(self.base_builder_tx.simulate_builder_tx(ctx, db)?); } else { // we increment the flashblock number for the next flashblock so we don't increment in the last flashblock if let Some(signer) = &self.signer { @@ -274,7 +250,7 @@ impl BuilderTransactions for FlashblocksNumberBuilderTx { { Ok(gas_used) => { // Due to EIP-150, 63/64 of available gas is forwarded to external calls so need to add a buffer - let flashblocks_tx = self.signed_flashblock_number_tx( + let signed_tx = self.signed_flashblock_number_tx( ctx, gas_used * 64 / 63, nonce, @@ -282,33 +258,20 @@ impl BuilderTransactions for FlashblocksNumberBuilderTx { )?; let da_size = op_alloy_flz::tx_estimated_size_fjord_bytes( - flashblocks_tx.encoded_2718().as_slice(), + signed_tx.encoded_2718().as_slice(), ); Some(BuilderTransactionCtx { gas_used, da_size, - signed_tx: if top_of_block { - Some(flashblocks_tx) - } else { - None - }, // number tx at top of flashblock + signed_tx, + is_top_of_block: true, // number tx at top of flashblock }) } Err(e) => { warn!(target: "builder_tx", error = ?e, "Flashblocks number contract tx simulation failed, defaulting to fallback builder tx"); - let builder_tx = self.base_builder_tx.simulate_builder_tx(ctx, db)?; - if let Some(tx) = &builder_tx - && top_of_block - { - // don't commit the builder if top of block, we only return the gas used to reserve gas for the builder tx - Some(BuilderTransactionCtx { - gas_used: tx.gas_used, - da_size: tx.da_size, - signed_tx: None, - }) - } else { - builder_tx - } + self.base_builder_tx + .simulate_builder_tx(ctx, db)? + .map(|tx| tx.set_top_of_block()) } }; @@ -331,7 +294,6 @@ impl BuilderTransactions for FlashblocksNumberBuilderTx { info, ctx, &mut simulation_state, - top_of_block, )?; builder_txs.extend(flashtestations_builder_txs); } diff --git a/crates/op-rbuilder/src/builders/flashblocks/payload.rs b/crates/op-rbuilder/src/builders/flashblocks/payload.rs index ae11a6da6..6a46e4c76 100644 --- a/crates/op-rbuilder/src/builders/flashblocks/payload.rs +++ b/crates/op-rbuilder/src/builders/flashblocks/payload.rs @@ -82,7 +82,7 @@ pub struct FlashblocksExtraCtx { /// Total gas left for the current flashblock target_gas_for_batch: u64, /// Total DA bytes left for the current flashblock - total_da_per_batch: Option, + target_da_for_batch: Option, /// Gas limit per flashblock gas_per_batch: u64, /// DA bytes limit per flashblock @@ -292,7 +292,7 @@ where flashblock_index: 0, target_flashblock_count: self.config.flashblocks_per_block(), target_gas_for_batch: 0, - total_da_per_batch: None, + target_da_for_batch: None, gas_per_batch: 0, da_per_batch: None, calculate_state_root, @@ -327,7 +327,7 @@ where &mut info, &ctx, &mut state, - true, + false, ) { Ok(builder_txs) => builder_txs, Err(e) => { @@ -431,7 +431,7 @@ where if let Some(da_limit) = total_da_per_batch.as_mut() { *da_limit = da_limit.saturating_sub(builder_tx_da_size); } - ctx.extra_ctx.total_da_per_batch = total_da_per_batch; + ctx.extra_ctx.target_da_for_batch = total_da_per_batch; ctx.extra_ctx.gas_per_batch = gas_per_batch; ctx.extra_ctx.da_per_batch = da_per_batch; @@ -567,7 +567,7 @@ where // Continue with flashblock building let mut target_gas_for_batch = ctx.extra_ctx.target_gas_for_batch; - let mut total_da_per_batch = ctx.extra_ctx.total_da_per_batch; + let mut target_da_per_batch = ctx.extra_ctx.target_da_for_batch; info!( target: "payload_builder", @@ -575,8 +575,9 @@ where flashblock_index = ctx.flashblock_index(), target_gas = target_gas_for_batch, gas_used = info.cumulative_gas_used, - target_da = total_da_per_batch.unwrap_or(0), + target_da = target_da_per_batch, da_used = info.cumulative_da_bytes_used, + block_gas_used = ctx.block_gas_limit(), "Building flashblock", ); let flashblock_build_start_time = Instant::now(); @@ -598,7 +599,7 @@ where target_gas_for_batch = target_gas_for_batch.saturating_sub(builder_tx_gas); // saturating sub just in case, we will log an error if da_limit too small for builder_tx_da_size - if let Some(da_limit) = total_da_per_batch.as_mut() { + if let Some(da_limit) = target_da_per_batch.as_mut() { *da_limit = da_limit.saturating_sub(builder_tx_da_size); } @@ -624,7 +625,7 @@ where state, best_txs, target_gas_for_batch.min(ctx.block_gas_limit()), - total_da_per_batch, + target_da_per_batch, )?; // Extract last transactions let new_transactions = info.executed_transactions[info.extra.last_flashblock_index..] @@ -726,7 +727,7 @@ where self.send_payload_to_engine(new_payload); // Update bundle_state for next iteration if let Some(da_limit) = ctx.extra_ctx.da_per_batch { - if let Some(da) = total_da_per_batch.as_mut() { + if let Some(da) = target_da_per_batch.as_mut() { *da += da_limit; } else { error!( @@ -736,7 +737,7 @@ where } ctx.extra_ctx.target_gas_for_batch += ctx.extra_ctx.gas_per_batch; - ctx.extra_ctx.total_da_per_batch = total_da_per_batch; + ctx.extra_ctx.target_da_for_batch = target_da_per_batch; info!( target: "payload_builder", diff --git a/crates/op-rbuilder/src/builders/standard/builder_tx.rs b/crates/op-rbuilder/src/builders/standard/builder_tx.rs index c4d154f63..c19f627d4 100644 --- a/crates/op-rbuilder/src/builders/standard/builder_tx.rs +++ b/crates/op-rbuilder/src/builders/standard/builder_tx.rs @@ -40,7 +40,6 @@ impl BuilderTransactions for StandardBuilderTx { info: &mut ExecutionInfo, ctx: &OpPayloadBuilderCtx, db: &mut State, - top_of_block: bool, ) -> Result, BuilderTransactionError> { let mut builder_txs = Vec::::new(); let standard_builder_tx = self.base_builder_tx.simulate_builder_tx(ctx, db)?; @@ -57,7 +56,6 @@ impl BuilderTransactions for StandardBuilderTx { info, ctx, &mut simulation_state, - top_of_block, )?; builder_txs.extend(flashtestations_builder_txs); } diff --git a/crates/op-rbuilder/src/builders/standard/payload.rs b/crates/op-rbuilder/src/builders/standard/payload.rs index c510a8ba9..0c0e5de07 100644 --- a/crates/op-rbuilder/src/builders/standard/payload.rs +++ b/crates/op-rbuilder/src/builders/standard/payload.rs @@ -347,8 +347,7 @@ impl OpBuilder<'_, Txs> { // 4. if mem pool transactions are requested we execute them // gas reserved for builder tx - let builder_txs = - builder_tx.simulate_builder_txs(&state_provider, &mut info, ctx, db, true)?; + let builder_txs = builder_tx.add_builder_txs(&state_provider, &mut info, ctx, db, true)?; let builder_tx_gas = builder_txs.iter().fold(0, |acc, tx| acc + tx.gas_used); let block_gas_limit = ctx.block_gas_limit().saturating_sub(builder_tx_gas); if block_gas_limit == 0 { diff --git a/crates/op-rbuilder/src/flashtestations/service.rs b/crates/op-rbuilder/src/flashtestations/service.rs index 40f126521..bd93a777c 100644 --- a/crates/op-rbuilder/src/flashtestations/service.rs +++ b/crates/op-rbuilder/src/flashtestations/service.rs @@ -102,7 +102,6 @@ impl BuilderTransactions for Flashtestation _info: &mut ExecutionInfo, _ctx: &OpPayloadBuilderCtx, _db: &mut State, - _top_of_block: bool, ) -> Result, BuilderTransactionError> { Ok(vec![]) } diff --git a/crates/op-rbuilder/src/primitives/reth/execution.rs b/crates/op-rbuilder/src/primitives/reth/execution.rs index 45acf963f..b2591c212 100644 --- a/crates/op-rbuilder/src/primitives/reth/execution.rs +++ b/crates/op-rbuilder/src/primitives/reth/execution.rs @@ -8,8 +8,10 @@ use reth_optimism_primitives::{OpReceipt, OpTransactionSigned}; #[derive(Debug, Display)] pub enum TxnExecutionResult { TransactionDALimitExceeded, - BlockDALimitExceeded, - TransactionGasLimitExceeded, + #[display("BlockDALimitExceeded: total_da_used={_0} tx_da_size={_1} block_da_limit={_2}")] + BlockDALimitExceeded(u64, u64, u64), + #[display("TransactionGasLimitExceeded: total_gas_used={_0} tx_gas_limit={_1}")] + TransactionGasLimitExceeded(u64, u64, u64), SequencerTransaction, NonceTooLow, InteropFailed, @@ -75,11 +77,19 @@ impl ExecutionInfo { if block_data_limit .is_some_and(|da_limit| self.cumulative_da_bytes_used + tx_da_size > da_limit) { - return Err(TxnExecutionResult::BlockDALimitExceeded); + return Err(TxnExecutionResult::BlockDALimitExceeded( + self.cumulative_da_bytes_used, + tx_da_size, + block_data_limit.unwrap_or_default(), + )); } if self.cumulative_gas_used + tx_gas_limit > block_gas_limit { - return Err(TxnExecutionResult::TransactionGasLimitExceeded); + return Err(TxnExecutionResult::TransactionGasLimitExceeded( + self.cumulative_gas_used, + tx_gas_limit, + block_gas_limit, + )); } Ok(()) } diff --git a/crates/op-rbuilder/src/tests/flashblocks.rs b/crates/op-rbuilder/src/tests/flashblocks.rs index 8204af75f..f3e46dae5 100644 --- a/crates/op-rbuilder/src/tests/flashblocks.rs +++ b/crates/op-rbuilder/src/tests/flashblocks.rs @@ -1,12 +1,25 @@ +use alloy_consensus::Transaction; +use alloy_eips::Decodable2718; +use alloy_primitives::{Address, TxHash, U256, address, b128, b256}; use alloy_provider::Provider; +use alloy_sol_types::SolCall; use macros::rb_test; +use op_alloy_consensus::OpTxEnvelope; use std::time::Duration; use crate::{ args::{FlashblocksArgs, OpRbuilderArgs}, - tests::{BlockTransactionsExt, BundleOpts, LocalInstance, TransactionBuilderExt}, + tests::{ + BUILDER_PRIVATE_KEY, BlockTransactionsExt, BundleOpts, ChainDriver, ChainDriverExt, + FUNDED_PRIVATE_KEY, LocalInstance, ONE_ETH, TransactionBuilderExt, + flashblocks_number_contract::FlashblocksNumber, + }, + tx_signer::Signer, }; +// If the order of deployment from the signer changes the address will change +const FLASHBLOCKS_NUMBER_ADDRESS: Address = address!("5fbdb2315678afecb367f032d93f642f64180aa3"); + #[rb_test(flashblocks, args = OpRbuilderArgs { chain_block_time: 2000, flashblocks: FlashblocksArgs { @@ -16,8 +29,7 @@ use crate::{ flashblocks_block_time: 200, flashblocks_leeway_time: 100, flashblocks_fixed: false, - flashblocks_calculate_state_root: true, - flashblocks_number_contract_address: None, + ..Default::default() }, ..Default::default() })] @@ -55,8 +67,7 @@ async fn smoke_dynamic_base(rbuilder: LocalInstance) -> eyre::Result<()> { flashblocks_block_time: 200, flashblocks_leeway_time: 100, flashblocks_fixed: false, - flashblocks_calculate_state_root: true, - flashblocks_number_contract_address: None, + ..Default::default() }, ..Default::default() })] @@ -94,8 +105,7 @@ async fn smoke_dynamic_unichain(rbuilder: LocalInstance) -> eyre::Result<()> { flashblocks_block_time: 200, flashblocks_leeway_time: 50, flashblocks_fixed: true, - flashblocks_calculate_state_root: true, - flashblocks_number_contract_address: None, + ..Default::default() }, ..Default::default() })] @@ -133,8 +143,7 @@ async fn smoke_classic_unichain(rbuilder: LocalInstance) -> eyre::Result<()> { flashblocks_block_time: 200, flashblocks_leeway_time: 50, flashblocks_fixed: true, - flashblocks_calculate_state_root: true, - flashblocks_number_contract_address: None, + ..Default::default() }, ..Default::default() })] @@ -172,8 +181,7 @@ async fn smoke_classic_base(rbuilder: LocalInstance) -> eyre::Result<()> { flashblocks_block_time: 200, flashblocks_leeway_time: 100, flashblocks_fixed: false, - flashblocks_calculate_state_root: true, - flashblocks_number_contract_address: None, + ..Default::default() }, ..Default::default() })] @@ -217,9 +225,7 @@ async fn unichain_dynamic_with_lag(rbuilder: LocalInstance) -> eyre::Result<()> flashblocks_addr: "127.0.0.1".into(), flashblocks_block_time: 200, flashblocks_leeway_time: 0, - flashblocks_fixed: false, - flashblocks_calculate_state_root: true, - flashblocks_number_contract_address: None, + ..Default::default() }, ..Default::default() })] @@ -255,10 +261,7 @@ async fn dynamic_with_full_block_lag(rbuilder: LocalInstance) -> eyre::Result<() flashblocks_port: 1239, flashblocks_addr: "127.0.0.1".into(), flashblocks_block_time: 200, - flashblocks_leeway_time: 100, - flashblocks_fixed: false, - flashblocks_calculate_state_root: true, - flashblocks_number_contract_address: None, + ..Default::default() }, ..Default::default() })] @@ -316,10 +319,7 @@ async fn test_flashblock_min_filtering(rbuilder: LocalInstance) -> eyre::Result< flashblocks_port: 1239, flashblocks_addr: "127.0.0.1".into(), flashblocks_block_time: 200, - flashblocks_leeway_time: 100, - flashblocks_fixed: false, - flashblocks_calculate_state_root: true, - flashblocks_number_contract_address: None, + ..Default::default() }, ..Default::default() })] @@ -375,8 +375,7 @@ async fn test_flashblock_max_filtering(rbuilder: LocalInstance) -> eyre::Result< flashblocks_block_time: 200, flashblocks_leeway_time: 100, flashblocks_fixed: false, - flashblocks_calculate_state_root: true, - flashblocks_number_contract_address: None, + ..Default::default() }, ..Default::default() })] @@ -422,7 +421,7 @@ async fn test_flashblock_min_max_filtering(rbuilder: LocalInstance) -> eyre::Res flashblocks_leeway_time: 100, flashblocks_fixed: false, flashblocks_calculate_state_root: false, - flashblocks_number_contract_address: None, + ..Default::default() }, ..Default::default() })] @@ -456,3 +455,209 @@ async fn test_flashblocks_no_state_root_calculation(rbuilder: LocalInstance) -> Ok(()) } + +#[rb_test(flashblocks, args = OpRbuilderArgs { + chain_block_time: 1000, + enable_revert_protection: true, + flashblocks: FlashblocksArgs { + flashblocks_number_contract_address: Some(FLASHBLOCKS_NUMBER_ADDRESS), + ..Default::default() + }, + ..Default::default() +})] +async fn test_flashblocks_number_contract_builder_tx(rbuilder: LocalInstance) -> eyre::Result<()> { + let driver = rbuilder.driver().await?; + let flashblocks_listener = rbuilder.spawn_flashblocks_listener(); + let provider = rbuilder.provider().await?; + + // Deploy flashblocks number contract which will be in flashblocks 1 + let deploy_tx = driver + .create_transaction() + .deploy_flashblock_number_contract() + .with_bundle(BundleOpts::default()) + .send() + .await?; + + // Create valid transactions for flashblocks 2-4 + let user_transactions = create_flashblock_transactions(&driver, 2..5).await?; + + // Build block with deploy tx in first flashblock, and a random valid transfer in every other flashblock + let block = driver.build_new_block_with_current_timestamp(None).await?; + + // Verify contract deployment + let receipt = provider + .get_transaction_receipt(*deploy_tx.tx_hash()) + .await? + .expect("flashblock number contract deployment not mined"); + let contract_address = receipt + .inner + .contract_address + .expect("contract receipt does not contain flashblock number contract address"); + assert_eq!( + contract_address, FLASHBLOCKS_NUMBER_ADDRESS, + "Flashblocks number contract address mismatch" + ); + + // Verify first block structure + assert_eq!(block.transactions.len(), 10); + let txs = block + .transactions + .as_transactions() + .expect("transactions not in block"); + + // Verify builder txs (should be regular since builder tx is not registered yet) + verify_builder_txs( + &txs, + &[1, 2, 4, 6, 8], + Some(Address::ZERO), + "Should have regular builder tx", + ); + + // Verify deploy tx position + assert_eq!( + txs[3].inner.inner.tx_hash(), + *deploy_tx.tx_hash(), + "Deploy tx not in correct position" + ); + + // Verify user transactions + verify_user_tx_hashes(&txs, &[5, 7, 9], &user_transactions); + + // Initialize contract + let init_tx = driver + .create_transaction() + .init_flashblock_number_contract(true) + .with_to(contract_address) + .with_bundle(BundleOpts::default()) + .send() + .await?; + + // Mine initialization + driver.build_new_block_with_current_timestamp(None).await?; + provider + .get_transaction_receipt(*init_tx.tx_hash()) + .await? + .expect("init tx not mined"); + + // Create user transactions for flashblocks 1 - 5 + let user_transactions = create_flashblock_transactions(&driver, 1..5).await?; + + // Build second block after initialization which will call the flashblock number contract + // with builder registered + let block = driver.build_new_block_with_current_timestamp(None).await?; + assert_eq!(block.transactions.len(), 10); + let txs = block + .transactions + .as_transactions() + .expect("transactions not in block"); + + // Fallback block should have regular builder tx after deposit tx + assert_eq!( + txs[1].to(), + Some(Address::ZERO), + "Fallback block should have regular builder tx" + ); + + // Other builder txs should call the contract + verify_builder_txs( + &txs, + &[2, 4, 6, 8], + Some(contract_address), + "Should call flashblocks contract", + ); + + // Verify user transactions, 3 blocks in total built + verify_user_tx_hashes(&txs, &[3, 5, 7, 9], &user_transactions); + + // Verify flashblock number incremented correctly + let contract = FlashblocksNumber::new(contract_address, provider.clone()); + let current_number = contract.getFlashblockNumber().call().await?; + assert_eq!( + current_number, + U256::from(7), + "Flashblock number not incremented correctly" + ); + + // Verify flashblocks + let flashblocks = flashblocks_listener.get_flashblocks(); + assert_eq!(flashblocks.len(), 15); + + // Verify builder tx in each flashblock + for (i, flashblock) in flashblocks.iter().enumerate() { + // In fallback blocks, builder tx is the 2nd tx (index 1) + // In regular flashblocks, builder tx is the 1st tx (index 0) + let is_fallback = i % 5 == 0; + let tx_index = if is_fallback { 1 } else { 0 }; + + let tx_bytes = flashblock.diff.transactions.get(tx_index).expect(&format!( + "Flashblock {} should have tx at index {}", + i, tx_index + )); + let tx = OpTxEnvelope::decode_2718(&mut tx_bytes.as_ref()) + .expect("failed to decode transaction"); + + let expected_to = if i < 7 || i == 10 { + Some(Address::ZERO) + } else { + Some(contract_address) + }; + + assert_eq!( + tx.to(), + expected_to, + "Flashblock {} builder tx (at index {}) should have to = {:?}", + i, + tx_index, + expected_to + ); + } + + flashblocks_listener.stop().await?; + Ok(()) +} + +// Helper to create transactions for flashblocks +async fn create_flashblock_transactions( + driver: &ChainDriver, + range: std::ops::Range, +) -> eyre::Result> { + let mut txs = Vec::new(); + for i in range { + let tx = driver + .create_transaction() + .random_valid_transfer() + .with_bundle(BundleOpts::default().with_flashblock_number_min(i)) + .send() + .await?; + txs.push(*tx.tx_hash()); + } + Ok(txs) +} + +// Helper to verify builder transactions +fn verify_builder_txs( + block_txs: &[impl Transaction], + indices: &[usize], + expected_to: Option
, + msg: &str, +) { + for &idx in indices { + assert_eq!(block_txs[idx].to(), expected_to, "{} at index {}", msg, idx); + } +} + +// Helper to verify transaction matches +fn verify_user_tx_hashes( + block_txs: &[impl AsRef], + indices: &[usize], + expected_txs: &[TxHash], +) { + for (i, &idx) in indices.iter().enumerate() { + assert_eq!( + *block_txs[idx].as_ref().tx_hash(), + expected_txs[i], + "Transaction at index {} doesn't match", + idx + ); + } +} diff --git a/crates/op-rbuilder/src/tests/framework/artifacts/contracts/BlockBuilderPolicy.json b/crates/op-rbuilder/src/tests/framework/artifacts/contracts/BlockBuilderPolicy.json new file mode 100644 index 000000000..6d95e8330 --- /dev/null +++ b/crates/op-rbuilder/src/tests/framework/artifacts/contracts/BlockBuilderPolicy.json @@ -0,0 +1,687 @@ +{ + "abi": [ + { + "type": "function", + "name": "UPGRADE_INTERFACE_VERSION", + "inputs": [], + "outputs": [ + { "name": "", "type": "string", "internalType": "string" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "VERIFY_BLOCK_BUILDER_PROOF_TYPEHASH", + "inputs": [], + "outputs": [ + { "name": "", "type": "bytes32", "internalType": "bytes32" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "addWorkloadToPolicy", + "inputs": [ + { + "name": "workloadId", + "type": "bytes32", + "internalType": "WorkloadId" + }, + { + "name": "commitHash", + "type": "string", + "internalType": "string" + }, + { + "name": "sourceLocators", + "type": "string[]", + "internalType": "string[]" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "computeStructHash", + "inputs": [ + { "name": "version", "type": "uint8", "internalType": "uint8" }, + { + "name": "blockContentHash", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "nonce", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { "name": "", "type": "bytes32", "internalType": "bytes32" } + ], + "stateMutability": "pure" + }, + { + "type": "function", + "name": "domainSeparator", + "inputs": [], + "outputs": [ + { "name": "", "type": "bytes32", "internalType": "bytes32" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "eip712Domain", + "inputs": [], + "outputs": [ + { + "name": "fields", + "type": "bytes1", + "internalType": "bytes1" + }, + { "name": "name", "type": "string", "internalType": "string" }, + { + "name": "version", + "type": "string", + "internalType": "string" + }, + { + "name": "chainId", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "verifyingContract", + "type": "address", + "internalType": "address" + }, + { + "name": "salt", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "extensions", + "type": "uint256[]", + "internalType": "uint256[]" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getHashedTypeDataV4", + "inputs": [ + { + "name": "structHash", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { "name": "", "type": "bytes32", "internalType": "bytes32" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getWorkloadMetadata", + "inputs": [ + { + "name": "workloadId", + "type": "bytes32", + "internalType": "WorkloadId" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct IBlockBuilderPolicy.WorkloadMetadata", + "components": [ + { + "name": "commitHash", + "type": "string", + "internalType": "string" + }, + { + "name": "sourceLocators", + "type": "string[]", + "internalType": "string[]" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "initialize", + "inputs": [ + { + "name": "_initialOwner", + "type": "address", + "internalType": "address" + }, + { + "name": "_registry", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "isAllowedPolicy", + "inputs": [ + { + "name": "teeAddress", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { "name": "allowed", "type": "bool", "internalType": "bool" }, + { "name": "", "type": "bytes32", "internalType": "WorkloadId" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "nonces", + "inputs": [ + { + "name": "teeAddress", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "permitNonce", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "owner", + "inputs": [], + "outputs": [ + { "name": "", "type": "address", "internalType": "address" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "permitVerifyBlockBuilderProof", + "inputs": [ + { "name": "version", "type": "uint8", "internalType": "uint8" }, + { + "name": "blockContentHash", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "nonce", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "eip712Sig", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "proxiableUUID", + "inputs": [], + "outputs": [ + { "name": "", "type": "bytes32", "internalType": "bytes32" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "registry", + "inputs": [], + "outputs": [ + { "name": "", "type": "address", "internalType": "address" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "removeWorkloadFromPolicy", + "inputs": [ + { + "name": "workloadId", + "type": "bytes32", + "internalType": "WorkloadId" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "renounceOwnership", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferOwnership", + "inputs": [ + { + "name": "newOwner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeToAndCall", + "inputs": [ + { + "name": "newImplementation", + "type": "address", + "internalType": "address" + }, + { "name": "data", "type": "bytes", "internalType": "bytes" } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "verifyBlockBuilderProof", + "inputs": [ + { "name": "version", "type": "uint8", "internalType": "uint8" }, + { + "name": "blockContentHash", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "workloadIdForTDRegistration", + "inputs": [ + { + "name": "registration", + "type": "tuple", + "internalType": "struct IFlashtestationRegistry.RegisteredTEE", + "components": [ + { + "name": "isValid", + "type": "bool", + "internalType": "bool" + }, + { + "name": "rawQuote", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "parsedReportBody", + "type": "tuple", + "internalType": "struct TD10ReportBody", + "components": [ + { + "name": "teeTcbSvn", + "type": "bytes16", + "internalType": "bytes16" + }, + { + "name": "mrSeam", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "mrsignerSeam", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "seamAttributes", + "type": "bytes8", + "internalType": "bytes8" + }, + { + "name": "tdAttributes", + "type": "bytes8", + "internalType": "bytes8" + }, + { + "name": "xFAM", + "type": "bytes8", + "internalType": "bytes8" + }, + { + "name": "mrTd", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "mrConfigId", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "mrOwner", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "mrOwnerConfig", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "rtMr0", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "rtMr1", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "rtMr2", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "rtMr3", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "reportData", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "name": "extendedRegistrationData", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "quoteHash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + } + ], + "outputs": [ + { "name": "", "type": "bytes32", "internalType": "WorkloadId" } + ], + "stateMutability": "pure" + }, + { + "type": "event", + "name": "BlockBuilderProofVerified", + "inputs": [ + { + "name": "caller", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "workloadId", + "type": "bytes32", + "indexed": false, + "internalType": "bytes32" + }, + { + "name": "version", + "type": "uint8", + "indexed": false, + "internalType": "uint8" + }, + { + "name": "blockContentHash", + "type": "bytes32", + "indexed": false, + "internalType": "bytes32" + }, + { + "name": "commitHash", + "type": "string", + "indexed": false, + "internalType": "string" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "EIP712DomainChanged", + "inputs": [], + "anonymous": false + }, + { + "type": "event", + "name": "Initialized", + "inputs": [ + { + "name": "version", + "type": "uint64", + "indexed": false, + "internalType": "uint64" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "OwnershipTransferred", + "inputs": [ + { + "name": "previousOwner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newOwner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RegistrySet", + "inputs": [ + { + "name": "registry", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Upgraded", + "inputs": [ + { + "name": "implementation", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "WorkloadAddedToPolicy", + "inputs": [ + { + "name": "workloadId", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "WorkloadRemovedFromPolicy", + "inputs": [ + { + "name": "workloadId", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "AddressEmptyCode", + "inputs": [ + { + "name": "target", + "type": "address", + "internalType": "address" + } + ] + }, + { "type": "error", "name": "ECDSAInvalidSignature", "inputs": [] }, + { + "type": "error", + "name": "ECDSAInvalidSignatureLength", + "inputs": [ + { + "name": "length", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "ECDSAInvalidSignatureS", + "inputs": [ + { "name": "s", "type": "bytes32", "internalType": "bytes32" } + ] + }, + { + "type": "error", + "name": "ERC1967InvalidImplementation", + "inputs": [ + { + "name": "implementation", + "type": "address", + "internalType": "address" + } + ] + }, + { "type": "error", "name": "ERC1967NonPayable", "inputs": [] }, + { "type": "error", "name": "EmptyCommitHash", "inputs": [] }, + { "type": "error", "name": "EmptySourceLocators", "inputs": [] }, + { "type": "error", "name": "FailedCall", "inputs": [] }, + { "type": "error", "name": "InvalidInitialization", "inputs": [] }, + { + "type": "error", + "name": "InvalidNonce", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "provided", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { "type": "error", "name": "InvalidRegistry", "inputs": [] }, + { "type": "error", "name": "NotInitializing", "inputs": [] }, + { + "type": "error", + "name": "OwnableInvalidOwner", + "inputs": [ + { + "name": "owner", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "OwnableUnauthorizedAccount", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "UUPSUnauthorizedCallContext", + "inputs": [] + }, + { + "type": "error", + "name": "UUPSUnsupportedProxiableUUID", + "inputs": [ + { "name": "slot", "type": "bytes32", "internalType": "bytes32" } + ] + }, + { + "type": "error", + "name": "UnauthorizedBlockBuilder", + "inputs": [ + { + "name": "caller", + "type": "address", + "internalType": "address" + } + ] + }, + { "type": "error", "name": "WorkloadAlreadyInPolicy", "inputs": [] }, + { "type": "error", "name": "WorkloadNotInPolicy", "inputs": [] } + ], + "bytecode": { + "object": "0x60a0806040523460295730608052613263908161002e8239608051818181610a3801526110790152f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c80632dd8abfe14611e4c578063485cc955146116b05780634d37fc7a146113365780634f1ef286146110105780634f3a415a14610ab057806352d1902d146109f35780635c40e542146109095780636931164e146108cd578063715018a6146107f3578063730169231461079b5780637b1039991461074a5780637dec71a9146106f95780637ecebe001461069657806384b0196e146104f15780638da5cb5b14610481578063abd45d21146102fc578063ad3cb1cc1461027b578063b33d59da14610237578063d2753561146101e8578063f2fde38b1461019f5763f698da2514610100575f80fd5b3461019b575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b57602061013861310e565b610140613178565b60405190838201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a0815261019060c082612063565b519020604051908152f35b5f80fd5b3461019b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b576101e66101d9611feb565b6101e1612d2c565b612b6a565b005b3461019b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b576040610229610224611feb565b6127d1565b825191151582526020820152f35b3461019b5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b576101e6610271611fad565b6024359033612c57565b3461019b575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b576102f86040516102ba604082612063565b600581527f352e302e30000000000000000000000000000000000000000000000000000000602082015260405191829160208352602083019061215f565b0390f35b3461019b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b576060602060405161033b81612047565b82815201526004355f525f60205260405f2060016040519161035c83612047565b61036581612695565b835201805461037381612349565b916103816040519384612063565b81835260208301905f5260205f205f915b838310610464576103c1868660208201908152604051928392602084525160406020850152606084019061215f565b9051907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838203016040840152815180825260208201916020808360051b8301019401925f915b8383106104155786860387f35b919395509193602080610452837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08660019603018752895161215f565b97019301930190928695949293610408565b60016020819261047385612695565b815201920192019190610392565b3461019b575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b57602073ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b3461019b575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b577fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10054158061066d575b1561060f576105b36105586124b1565b6105606125c2565b60206105c1604051926105738385612063565b5f84525f3681376040519586957f0f00000000000000000000000000000000000000000000000000000000000000875260e08588015260e087019061215f565b90858203604087015261215f565b4660608501523060808501525f60a085015283810360c08501528180845192838152019301915f5b8281106105f857505050500390f35b8351855286955093810193928101926001016105e9565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4549503731323a20556e696e697469616c697a656400000000000000000000006044820152fd5b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1015415610548565b3461019b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b5773ffffffffffffffffffffffffffffffffffffffff6106e2611feb565b165f526002602052602060405f2054604051908152f35b3461019b5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b576020610742610735611fad565b6044359060243590612463565b604051908152f35b3461019b575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b3461019b575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b5760206040517f93b3c192de39a93da71b94fb9fadb8e913f752a2e9ea950a33266a81fcbf2ffc8152f35b3461019b575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b57610829612d2c565b5f73ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300547fffffffffffffffffffffffff000000000000000000000000000000000000000081167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461019b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b5760206107426004356123c6565b3461019b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b57600435610943612d2c565b805f525f60205261095760405f20546122f8565b156109cb57805f525f602052600160405f2061097281612377565b018054905f8155816109a6575b827f56c387a9be1bf0e0e4f852c577a225db98e8253ad401d1b4ea73926f27d6af095f80a2005b5f5260205f20908101905b8181101561097f57806109c5600192612377565b016109b1565b7f22faf042000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461019b575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b5773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163003610a885760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b7fe07c8dba000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461019b5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b5760043560243567ffffffffffffffff811161019b57610b02903690600401611fbd565b919060443567ffffffffffffffff811161019b573660238201121561019b5780600401359167ffffffffffffffff831161019b5760248360051b8301019036821161019b57610b4f612d2c565b8515610fe8578315610fc057845f525f602052610b6f60405f20546122f8565b610f9857610b8b9060405196610b8488612047565b36916120de565b8552610b9683612349565b92610ba46040519485612063565b83526024820191602084015b828410610f57575050505060208301908152815f525f60205260405f20925192835167ffffffffffffffff8111610e2057610beb82546122f8565b601f8111610f27575b506020601f8211600114610e85579080610c469260019596975f92610e7a575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b81555b019051805190680100000000000000008211610e20578254828455808310610e4d575b50602001915f5260205f20915f905b828210610ca957847fcbb92e241e191fed6d0b0da0a918c7dcf595e77d868e2e3bf9e6b0b91589c7ad5f80a2005b805180519067ffffffffffffffff8211610e2057610cc786546122f8565b601f8111610de5575b50602090601f8311600114610d3f5792610d25836001959460209487965f92610d345750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b87555b01940191019092610c7b565b015190508b80610c14565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0831691875f52815f20925f5b818110610dcd5750936020936001969387969383889510610d96575b505050811b018755610d28565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558a8080610d89565b92936020600181928786015181550195019301610d6d565b610e1090875f5260205f20601f850160051c81019160208610610e16575b601f0160051c0190612361565b87610cd0565b9091508190610e03565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b835f528260205f2091820191015b818110610e685750610c6c565b80610e74600192612377565b01610e5b565b015190508780610c14565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0821695835f52815f20965f5b818110610f0f5750916001959697918487959410610ed8575b505050811b018155610c49565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055868080610ecb565b83830151895560019098019760209384019301610eb2565b610f5190835f5260205f20601f840160051c81019160208510610e1657601f0160051c0190612361565b85610bf4565b833567ffffffffffffffff811161019b5782013660438201121561019b57602091610f8d839236906044602482013591016120de565b815201930192610bb0565b7f72477348000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f6890d9d4000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f8423f262000000000000000000000000000000000000000000000000000000005f5260045ffd5b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b57611042611feb565b60243567ffffffffffffffff811161019b57611062903690600401612114565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168030149081156112f4575b50610a88576110b1612d2c565b73ffffffffffffffffffffffffffffffffffffffff8216916040517f52d1902d000000000000000000000000000000000000000000000000000000008152602081600481875afa5f91816112c0575b5061113157837f4c9c8ce3000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8592036112955750813b1561126a57807fffffffffffffffffffffffff00000000000000000000000000000000000000007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416177f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a2815115611239575f808360206101e695519101845af43d15611231573d91611215836120a4565b926112236040519485612063565b83523d5f602085013e6131bd565b6060916131bd565b50503461124257005b7fb398979f000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4c9c8ce3000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7faa1d49a4000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b9091506020813d6020116112ec575b816112dc60209383612063565b8101031261019b57519085611100565b3d91506112cf565b905073ffffffffffffffffffffffffffffffffffffffff7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54161415836110a4565b3461019b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b5760043567ffffffffffffffff811161019b5760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc823603011261019b57604051906113b08261200e565b8060040135801515810361019b578252602481013567ffffffffffffffff811161019b576113e49060043691840101612114565b6020830152604481013567ffffffffffffffff811161019b5781016101e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc823603011261019b57604051906114398261202a565b60048101357fffffffffffffffffffffffffffffffff000000000000000000000000000000008116810361019b578252602481013567ffffffffffffffff811161019b5761148d9060043691840101612114565b6020830152604481013567ffffffffffffffff811161019b576114b69060043691840101612114565b60408301526114c760648201612132565b60608301526114d860848201612132565b60808301526114e960a48201612132565b60a083015260c481013567ffffffffffffffff811161019b576115129060043691840101612114565b60c083015260e481013567ffffffffffffffff811161019b5761153b9060043691840101612114565b60e083015261010481013567ffffffffffffffff811161019b576115659060043691840101612114565b61010083015261012481013567ffffffffffffffff811161019b576115909060043691840101612114565b61012083015261014481013567ffffffffffffffff811161019b576115bb9060043691840101612114565b61014083015261016481013567ffffffffffffffff811161019b576115e69060043691840101612114565b61016083015261018481013567ffffffffffffffff811161019b576116119060043691840101612114565b6101808301526101a481013567ffffffffffffffff811161019b5761163c9060043691840101612114565b6101a08301526101c48101359067ffffffffffffffff821161019b5760046116679236920101612114565b6101c0820152604083015260648101359167ffffffffffffffff831161019b5760846107429261169f60209560043691840101612114565b6060840152013560808201526121a2565b3461019b5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b576116e7611feb565b60243573ffffffffffffffffffffffffffffffffffffffff811680910361019b577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c16159267ffffffffffffffff821680159081611e44575b6001149081611e3a575b159081611e31575b50611e0957818460017fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006117c19516177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055611db4575b506117b9613028565b6101e1613028565b6117c9613028565b6040918251926117d98185612063565b601284527f426c6f636b4275696c646572506f6c696379000000000000000000000000000060208501528051936118108286612063565b600185527f31000000000000000000000000000000000000000000000000000000000000006020860152611842613028565b61184a613028565b80519067ffffffffffffffff8211610e20576118867fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102546122f8565b601f8111611d47575b50602090601f8311600114611c67576118dc92915f9183610e7a5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102555b835167ffffffffffffffff8111610e205761193a7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d103546122f8565b601f8111611bfa575b50602094601f8211600114611b1c576119939293949582915f92611b115750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d103555b5f7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100555f7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d101558215611ae957827fffffffffffffffffffffffff0000000000000000000000000000000000000000600154161760015551917f27fe5f0c1c3b1ed427cc63d0f05759ffdecf9aec9e18d31ef366fc8a6cb5dc3b5f80a2611a5857005b60207fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2917fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005560018152a1005b7f11a1e697000000000000000000000000000000000000000000000000000000005f5260045ffd5b015190508680610c14565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08216957fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1035f52805f20915f5b888110611be257508360019596979810611bab575b505050811b017fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d103556119b6565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055858080611b7e565b91926020600181928685015181550194019201611b69565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1035f52611c61907f5f9ce34815f8e11431c7bb75a8e6886a91478f7ffc1dbb0a98dc240fddd76b75601f840160051c81019160208510610e1657601f0160051c0190612361565b85611943565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08316917fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1025f52815f20925f5b818110611d2f5750908460019594939210611cf8575b505050811b017fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102556118ff565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055868080611ccb565b92936020600181928786015181550195019301611cb5565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1025f52611dae907f42ad5d3e1f2e6e70edcf6d991b8a3023d3fca8047a131592f9edb9fd9b89d57d601f850160051c81019160208610610e1657601f0160051c0190612361565b8661188f565b7fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055846117b0565b7ff92ee8a9000000000000000000000000000000000000000000000000000000005f5260045ffd5b90501585611759565b303b159150611751565b859150611747565b3461019b5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b57611e83611fad565b602435604435916064359267ffffffffffffffff841161019b57611ed7611ed1611eb4611ee0963690600401611fbd565b9190611ec9611ec4868989612463565b6123c6565b9236916120de565b90612d98565b90959195612dd2565b73ffffffffffffffffffffffffffffffffffffffff841690815f52600260205260405f2054808203611f7f5750505f52600260205260405f20928354937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8514611f525760016101e695019055612c57565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7f06427aeb000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b6004359060ff8216820361019b57565b9181601f8401121561019b5782359167ffffffffffffffff831161019b576020838186019501011161019b57565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361019b57565b60a0810190811067ffffffffffffffff821117610e2057604052565b6101e0810190811067ffffffffffffffff821117610e2057604052565b6040810190811067ffffffffffffffff821117610e2057604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610e2057604052565b67ffffffffffffffff8111610e2057601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b9291926120ea826120a4565b916120f86040519384612063565b82948184528183011161019b578281602093845f960137010152565b9080601f8301121561019b5781602061212f933591016120de565b90565b35907fffffffffffffffff0000000000000000000000000000000000000000000000008216820361019b57565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b6040015160c081015190610140810151610160820151916101808101516101a082015160e08301519060a08401517fffffffffffffffff0000000000000000000000000000000000000000000000001678030000000000000000000000000000000000000000000000001893608001517fffffffff2fffffff00000000000000000000000000000000000000000000000016926040519687966020880199805160208192018c5e880160208101915f83528051926020849201905e016020015f815281516020819301825e015f815281516020819301825e015f815281516020819301825e015f815281516020819301825e01917fffffffffffffffff0000000000000000000000000000000000000000000000001682526008820152037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0810182526010016122f29082612063565b51902090565b90600182811c9216801561233f575b602083101461231257565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b91607f1691612307565b67ffffffffffffffff8111610e205760051b60200190565b81811061236c575050565b5f8155600101612361565b61238181546122f8565b908161238b575050565b81601f5f931160011461239d5750555b565b818352602083206123b991601f0160051c810190600101612361565b8082528160208120915555565b6042906123d161310e565b6123d9613178565b6040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a0815261242a60c082612063565b51902090604051917f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201522090565b916040519160ff60208401947f93b3c192de39a93da71b94fb9fadb8e913f752a2e9ea950a33266a81fcbf2ffc865216604084015260608301526080820152608081526122f260a082612063565b604051905f827fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10254916124e3836122f8565b80835292600181169081156125855750600114612507575b61239b92500383612063565b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1025f90815290917f42ad5d3e1f2e6e70edcf6d991b8a3023d3fca8047a131592f9edb9fd9b89d57d5b81831061256957505090602061239b928201016124fb565b6020919350806001915483858901015201910190918492612551565b6020925061239b9491507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001682840152151560051b8201016124fb565b604051905f827fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10354916125f4836122f8565b808352926001811690811561258557506001146126175761239b92500383612063565b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1035f90815290917f5f9ce34815f8e11431c7bb75a8e6886a91478f7ffc1dbb0a98dc240fddd76b755b81831061267957505090602061239b928201016124fb565b6020919350806001915483858901015201910190918492612661565b9060405191825f8254926126a8846122f8565b808452936001811690811561271157506001146126cd575b5061239b92500383612063565b90505f9291925260205f20905f915b8183106126f557505090602061239b928201015f6126c0565b60209193508060019154838589010152019101909184926126dc565b6020935061239b9592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201015f6126c0565b5190811515820361019b57565b81601f8201121561019b57805190612775826120a4565b926127836040519485612063565b8284526020838301011161019b57815f9260208093018386015e8301015290565b51907fffffffffffffffff0000000000000000000000000000000000000000000000008216820361019b57565b5f73ffffffffffffffffffffffffffffffffffffffff602481600154169360405194859384927f727310620000000000000000000000000000000000000000000000000000000084521660048301525afa908115612b5f575f9161286c575b5080511561286557612841906121a2565b805f525f60205261285560405f20546122f8565b61286057505f905f90565b600191565b505f905f90565b90503d805f833e61287d8183612063565b81019060408183031261019b5761289381612751565b5060208101519067ffffffffffffffff821161019b57019060a08282031261019b57604051916128c28361200e565b6128cb81612751565b8352602081015167ffffffffffffffff811161019b57826128ed91830161275e565b6020840152604081015167ffffffffffffffff811161019b5781016101e08184031261019b57604051906129208261202a565b80517fffffffffffffffffffffffffffffffff000000000000000000000000000000008116810361019b578252602081015167ffffffffffffffff811161019b578461296d91830161275e565b6020830152604081015167ffffffffffffffff811161019b578461299291830161275e565b60408301526129a3606082016127a4565b60608301526129b4608082016127a4565b60808301526129c560a082016127a4565b60a083015260c081015167ffffffffffffffff811161019b57846129ea91830161275e565b60c083015260e081015167ffffffffffffffff811161019b5784612a0f91830161275e565b60e083015261010081015167ffffffffffffffff811161019b5784612a3591830161275e565b61010083015261012081015167ffffffffffffffff811161019b5784612a5c91830161275e565b61012083015261014081015167ffffffffffffffff811161019b5784612a8391830161275e565b61014083015261016081015167ffffffffffffffff811161019b5784612aaa91830161275e565b61016083015261018081015167ffffffffffffffff811161019b5784612ad191830161275e565b6101808301526101a081015167ffffffffffffffff811161019b5784612af891830161275e565b6101a08301526101c08101519067ffffffffffffffff821161019b57612b209185910161275e565b6101c08201526040840152606081015167ffffffffffffffff811161019b57608092612b4d91830161275e565b6060840152015160808201525f612830565b6040513d5f823e3d90fd5b73ffffffffffffffffffffffffffffffffffffffff168015612c2b5773ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054827fffffffffffffffffffffffff00000000000000000000000000000000000000008216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b7f1e4fbdf7000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b91612c6183612eaa565b929015612cea57827f3fa039a23466a52e08acb25376ac7d81de184fa6549ffffb2fc920c47cb623ed949260ff612ce59373ffffffffffffffffffffffffffffffffffffffff965f525f602052612cba60405f20612695565b936040519788971687526020870152166040850152606084015260a0608084015260a083019061215f565b0390a1565b73ffffffffffffffffffffffffffffffffffffffff847f4c547670000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b73ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054163303612d6c57565b7f118cdaa7000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b8151919060418303612dc857612dc19250602082015190606060408401519301515f1a9061307f565b9192909190565b50505f9160029190565b6004811015612e7d5780612de4575050565b60018103612e14577ff645eedf000000000000000000000000000000000000000000000000000000005f5260045ffd5b60028103612e4857507ffce698f7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b600314612e525750565b7fd78bce0c000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b73ffffffffffffffffffffffffffffffffffffffff600154166040517fa8af4ff500000000000000000000000000000000000000000000000000000000815260408160248173ffffffffffffffffffffffffffffffffffffffff8716958660048301525afa908115612b5f575f905f92612fe7575b5015612fde57815f52600360205260405f209160405193612f3f85612047565b60018454948587520154806020870152838515159182612fd4575b505015612f82575050505f525f602052612f7760405f20546122f8565b156128655751600191565b909250612f91919493506127d1565b93819291612fa0575b50509190565b60019060405192612fb084612047565b868452602084019182525f52600360205260405f2092518355519101555f80612f9a565b149050835f612f5a565b5050505f905f90565b9150506040813d604011613020575b8161300360409383612063565b8101031261019b57602061301682612751565b910151905f612f1f565b3d9150612ff6565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561305757565b7fd7e6bcf8000000000000000000000000000000000000000000000000000000005f5260045ffd5b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411613103579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa15612b5f575f5173ffffffffffffffffffffffffffffffffffffffff8116156130f957905f905f90565b505f906001905f90565b5050505f9160039190565b6131166124b1565b8051908115613126576020012090565b50507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1005480156131535790565b507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47090565b6131806125c2565b8051908115613190576020012090565b50507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1015480156131535790565b906131fa57508051156131d257805190602001fd5b7fd6bda275000000000000000000000000000000000000000000000000000000005f5260045ffd5b8151158061324d575b61320b575090565b73ffffffffffffffffffffffffffffffffffffffff907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b50803b1561320356fea164736f6c634300081c000a", + "sourceMap": "1951:12842:96:-:0;;;;;;;1171:4:51;1163:13;;1951:12842:96;;;;;;1163:13:51;1951:12842:96;;;;;;;;;;;;;;", + "linkReferences": {} + } +} diff --git a/crates/op-rbuilder/src/tests/framework/artifacts/contracts/FlashblocksNumberContract.json b/crates/op-rbuilder/src/tests/framework/artifacts/contracts/FlashblocksNumberContract.json new file mode 100644 index 000000000..1a3b1e6c7 --- /dev/null +++ b/crates/op-rbuilder/src/tests/framework/artifacts/contracts/FlashblocksNumberContract.json @@ -0,0 +1,450 @@ +{ + "abi": [ + { + "type": "function", + "name": "PERMIT_INCREMENT_TYPEHASH", + "inputs": [], + "outputs": [ + { "name": "", "type": "bytes32", "internalType": "bytes32" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "UPGRADE_INTERFACE_VERSION", + "inputs": [], + "outputs": [ + { "name": "", "type": "string", "internalType": "string" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "addBuilder", + "inputs": [ + { + "name": "builder", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "computeStructHash", + "inputs": [ + { + "name": "currentFlashblockNumber", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { "name": "", "type": "bytes32", "internalType": "bytes32" } + ], + "stateMutability": "pure" + }, + { + "type": "function", + "name": "eip712Domain", + "inputs": [], + "outputs": [ + { + "name": "fields", + "type": "bytes1", + "internalType": "bytes1" + }, + { "name": "name", "type": "string", "internalType": "string" }, + { + "name": "version", + "type": "string", + "internalType": "string" + }, + { + "name": "chainId", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "verifyingContract", + "type": "address", + "internalType": "address" + }, + { + "name": "salt", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "extensions", + "type": "uint256[]", + "internalType": "uint256[]" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "flashblockNumber", + "inputs": [], + "outputs": [ + { "name": "", "type": "uint256", "internalType": "uint256" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getFlashblockNumber", + "inputs": [], + "outputs": [ + { "name": "", "type": "uint256", "internalType": "uint256" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "hashTypedDataV4", + "inputs": [ + { + "name": "structHash", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { "name": "", "type": "bytes32", "internalType": "bytes32" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "incrementFlashblockNumber", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "initialize", + "inputs": [ + { + "name": "_owner", + "type": "address", + "internalType": "address" + }, + { + "name": "_initialBuilders", + "type": "address[]", + "internalType": "address[]" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "isBuilder", + "inputs": [ + { "name": "", "type": "address", "internalType": "address" } + ], + "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "owner", + "inputs": [], + "outputs": [ + { "name": "", "type": "address", "internalType": "address" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "permitIncrementFlashblockNumber", + "inputs": [ + { + "name": "currentFlashblockNumber", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "signature", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "proxiableUUID", + "inputs": [], + "outputs": [ + { "name": "", "type": "bytes32", "internalType": "bytes32" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "removeBuilder", + "inputs": [ + { + "name": "builder", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "renounceOwnership", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferOwnership", + "inputs": [ + { + "name": "newOwner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeToAndCall", + "inputs": [ + { + "name": "newImplementation", + "type": "address", + "internalType": "address" + }, + { "name": "data", "type": "bytes", "internalType": "bytes" } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "event", + "name": "BuilderAdded", + "inputs": [ + { + "name": "builder", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "BuilderRemoved", + "inputs": [ + { + "name": "builder", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "EIP712DomainChanged", + "inputs": [], + "anonymous": false + }, + { + "type": "event", + "name": "FlashblockIncremented", + "inputs": [ + { + "name": "newFlashblockIndex", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Initialized", + "inputs": [ + { + "name": "version", + "type": "uint64", + "indexed": false, + "internalType": "uint64" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "OwnershipTransferred", + "inputs": [ + { + "name": "previousOwner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newOwner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Upgraded", + "inputs": [ + { + "name": "implementation", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "AddressEmptyCode", + "inputs": [ + { + "name": "target", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "AddressIsAlreadyABuilder", + "inputs": [ + { "name": "addr", "type": "address", "internalType": "address" } + ] + }, + { + "type": "error", + "name": "BuilderDoesNotExist", + "inputs": [ + { "name": "addr", "type": "address", "internalType": "address" } + ] + }, + { "type": "error", "name": "ECDSAInvalidSignature", "inputs": [] }, + { + "type": "error", + "name": "ECDSAInvalidSignatureLength", + "inputs": [ + { + "name": "length", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "ECDSAInvalidSignatureS", + "inputs": [ + { "name": "s", "type": "bytes32", "internalType": "bytes32" } + ] + }, + { + "type": "error", + "name": "ERC1967InvalidImplementation", + "inputs": [ + { + "name": "implementation", + "type": "address", + "internalType": "address" + } + ] + }, + { "type": "error", "name": "ERC1967NonPayable", "inputs": [] }, + { "type": "error", "name": "FailedCall", "inputs": [] }, + { "type": "error", "name": "InvalidInitialization", "inputs": [] }, + { + "type": "error", + "name": "MismatchedFlashblockNumber", + "inputs": [ + { + "name": "expectedFlashblockNumber", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actualFlashblockNumber", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "NonBuilderAddress", + "inputs": [ + { "name": "addr", "type": "address", "internalType": "address" } + ] + }, + { "type": "error", "name": "NotInitializing", "inputs": [] }, + { + "type": "error", + "name": "OwnableInvalidOwner", + "inputs": [ + { + "name": "owner", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "OwnableUnauthorizedAccount", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "UUPSUnauthorizedCallContext", + "inputs": [] + }, + { + "type": "error", + "name": "UUPSUnsupportedProxiableUUID", + "inputs": [ + { "name": "slot", "type": "bytes32", "internalType": "bytes32" } + ] + } + ], + "bytecode": { + "object": "0x60a0806040523460295730608052611f7d908161002e8239608051818181611013015261114c0152f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c806325f5ffa41461147c5780633fd553e8146114455780634980f288146114095780634f1ef286146110e35780634f66ee131461108b57806352d1902d14610fce578063715018a614610ef457806384b0196e14610d4f5780638da5cb5b14610cdf578063946d920414610439578063a0a78ce01461025d578063ad3cb1cc146103b8578063b6b6b47514610350578063c91d762514610297578063e5b37c5d1461025d578063e7e3a27114610219578063ec9693861461012c5763f2fde38b146100df575f80fd5b346101285760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285761012661011961156b565b6101216118a2565b6117b5565b005b5f80fd5b346101285760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285773ffffffffffffffffffffffffffffffffffffffff61017861156b565b6101806118a2565b16805f52600160205260ff60405f205416156101ee57805f52600160205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690557fc5a4a43135540d5e0967677a1ed86bf147f7c0e7dd757a109f4cff74c945f92e5f80a2005b7f677fda95000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b346101285760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610128576020610255600435611770565b604051908152f35b34610128575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285760205f54604051908152f35b346101285760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285760043560243567ffffffffffffffff8111610128576102e9903690600401611609565b905f548082036103215761012661031c6103138561030e61030987611770565b611692565b611c7c565b90929192611cb6565b61190e565b907f53b6b59a000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b346101285760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285773ffffffffffffffffffffffffffffffffffffffff61039c61156b565b165f526001602052602060ff60405f2054166040519015158152f35b34610128575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610128576104356040516103f760408261158e565b600581527f352e302e30000000000000000000000000000000000000000000000000000000602082015260405191829160208352602083019061164f565b0390f35b346101285760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285761047061156b565b6024359067ffffffffffffffff821161012857366023830112156101285781600401359167ffffffffffffffff8311610a76578260051b9060208201936104ba604051958661158e565b8452602460208501928201019036821161012857602401915b818310610cb2575050507ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c16159167ffffffffffffffff821680159081610caa575b6001149081610ca0575b159081610c97575b50610c6f57818360017fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006105969516177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055610c1a575b5061058e611c25565b610121611c25565b61059e611c25565b6040908151926105ae838561158e565b601084527f466c617368626c6f636b4e756d6265720000000000000000000000000000000060208501528251936105e5848661158e565b600185527f31000000000000000000000000000000000000000000000000000000000000006020860152610617611c25565b61061f611c25565b80519067ffffffffffffffff8211610a7657819061065d7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102546119ee565b601f8111610b8d575b50602090601f8311600114610aae575f92610aa3575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c1916177fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102555b835167ffffffffffffffff8111610a76576107097fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d103546119ee565b601f81116109f4575b50602094601f8211600114610916579481929394955f9261090b575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c1916177fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d103555b5f7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100555f7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d101555f5b8151811015610871578073ffffffffffffffffffffffffffffffffffffffff6107f36001938561172f565b51165f5281602052845f20827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff610845828561172f565b51167fc2dabef8a63ab48fcf728bbe8864a3fe01a9e19addc6ce314abd5b6f9a1dce665f80a2016107c8565b505061087957005b60207fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2917fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00555160018152a1005b01519050858061072e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08216957fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1035f52805f20915f5b8881106109dc575083600195969798106109a5575b505050811b017fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10355610780565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055858080610978565b91926020600181928685015181550194019201610963565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1035f527f5f9ce34815f8e11431c7bb75a8e6886a91478f7ffc1dbb0a98dc240fddd76b75601f830160051c81019160208410610a6c575b601f0160051c01905b818110610a615750610712565b5f8155600101610a54565b9091508190610a4b565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b01519050868061067c565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016917fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1025f52815f20925f5b818110610b755750908460019594939210610b3e575b505050811b017fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102556106ce565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055868080610b11565b92936020600181928786015181550195019301610afb565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1025f529091507f42ad5d3e1f2e6e70edcf6d991b8a3023d3fca8047a131592f9edb9fd9b89d57d601f840160051c81019160208510610c10575b90601f859493920160051c01905b818110610c025750610666565b5f8155849350600101610bf5565b9091508190610be7565b7fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005584610585565b7ff92ee8a9000000000000000000000000000000000000000000000000000000005f5260045ffd5b9050158561052e565b303b159150610526565b84915061051c565b823573ffffffffffffffffffffffffffffffffffffffff81168103610128578152602092830192016104d3565b34610128575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012857602073ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b34610128575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610128577fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100541580610ecb575b15610e6d57610e11610db6611a3f565b610dbe611b52565b6020610e1f60405192610dd1838561158e565b5f84525f3681376040519586957f0f00000000000000000000000000000000000000000000000000000000000000875260e08588015260e087019061164f565b90858203604087015261164f565b4660608501523060808501525f60a085015283810360c08501528180845192838152019301915f5b828110610e5657505050500390f35b835185528695509381019392810192600101610e47565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4549503731323a20556e696e697469616c697a656400000000000000000000006044820152fd5b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1015415610da6565b34610128575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012857610f2a6118a2565b5f73ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300547fffffffffffffffffffffffff000000000000000000000000000000000000000081167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610128575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630036110635760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b7fe07c8dba000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610128575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285760206040517f51de50fd99b637d778db8fe7a8a1966ddae5530dd6e4d8f693ffb315c812a24d8152f35b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285761111561156b565b60243567ffffffffffffffff811161012857611135903690600401611609565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168030149081156113c7575b50611063576111846118a2565b73ffffffffffffffffffffffffffffffffffffffff8216916040517f52d1902d000000000000000000000000000000000000000000000000000000008152602081600481875afa5f9181611393575b5061120457837f4c9c8ce3000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8592036113685750813b1561133d57807fffffffffffffffffffffffff00000000000000000000000000000000000000007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416177f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a281511561130c575f8083602061012695519101845af43d15611304573d916112e8836115cf565b926112f6604051948561158e565b83523d5f602085013e611ed7565b606091611ed7565b50503461131557005b7fb398979f000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4c9c8ce3000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7faa1d49a4000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b9091506020813d6020116113bf575b816113af6020938361158e565b81010312610128575190856111d3565b3d91506113a2565b905073ffffffffffffffffffffffffffffffffffffffff7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416141583611177565b346101285760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610128576020610255600435611692565b34610128575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610128576101263361190e565b346101285760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285773ffffffffffffffffffffffffffffffffffffffff6114c861156b565b6114d06118a2565b16805f52600160205260ff60405f20541661154057805f52600160205260405f2060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008254161790557fc2dabef8a63ab48fcf728bbe8864a3fe01a9e19addc6ce314abd5b6f9a1dce665f80a2005b7fc0b0858c000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361012857565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610a7657604052565b67ffffffffffffffff8111610a7657601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b81601f8201121561012857803590611620826115cf565b9261162e604051948561158e565b8284526020838301011161012857815f926020809301838601378301015290565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b60429061169d611e28565b6116a5611e92565b6040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a081526116f660c08261158e565b51902090604051917f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201522090565b80518210156117435760209160051b010190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b60405160208101917f51de50fd99b637d778db8fe7a8a1966ddae5530dd6e4d8f693ffb315c812a24d83526040820152604081526117af60608261158e565b51902090565b73ffffffffffffffffffffffffffffffffffffffff1680156118765773ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054827fffffffffffffffffffffffff00000000000000000000000000000000000000008216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b7f1e4fbdf7000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b73ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300541633036118e257565b7f118cdaa7000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b73ffffffffffffffffffffffffffffffffffffffff16805f52600160205260ff60405f205416156119c357505f547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461199657602060017ffaddd0b06e793a583e92393ad3f98637e560462ee98db1f2888f141124ee64ca9201805f55604051908152a1565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7fdd9dbe80000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b90600182811c92168015611a35575b6020831014611a0857565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b91607f16916119fd565b604051905f827fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1025491611a71836119ee565b8083529260018116908115611b155750600114611a97575b611a959250038361158e565b565b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1025f90815290917f42ad5d3e1f2e6e70edcf6d991b8a3023d3fca8047a131592f9edb9fd9b89d57d5b818310611af9575050906020611a9592820101611a89565b6020919350806001915483858901015201910190918492611ae1565b60209250611a959491507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001682840152151560051b820101611a89565b604051905f827fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1035491611b84836119ee565b8083529260018116908115611b155750600114611ba757611a959250038361158e565b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1035f90815290917f5f9ce34815f8e11431c7bb75a8e6886a91478f7ffc1dbb0a98dc240fddd76b755b818310611c09575050906020611a9592820101611a89565b6020919350806001915483858901015201910190918492611bf1565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c1615611c5457565b7fd7e6bcf8000000000000000000000000000000000000000000000000000000005f5260045ffd5b8151919060418303611cac57611ca59250602082015190606060408401519301515f1a90611d8e565b9192909190565b50505f9160029190565b6004811015611d615780611cc8575050565b60018103611cf8577ff645eedf000000000000000000000000000000000000000000000000000000005f5260045ffd5b60028103611d2c57507ffce698f7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b600314611d365750565b7fd78bce0c000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411611e1d579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa15611e12575f5173ffffffffffffffffffffffffffffffffffffffff811615611e0857905f905f90565b505f906001905f90565b6040513d5f823e3d90fd5b5050505f9160039190565b611e30611a3f565b8051908115611e40576020012090565b50507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100548015611e6d5790565b507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47090565b611e9a611b52565b8051908115611eaa576020012090565b50507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d101548015611e6d5790565b90611f145750805115611eec57602081519101fd5b7fd6bda275000000000000000000000000000000000000000000000000000000005f5260045ffd5b81511580611f67575b611f25575090565b73ffffffffffffffffffffffffffffffffffffffff907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b50803b15611f1d56fea164736f6c634300081c000a", + "sourceMap": "1449:6259:60:-:0;;;;;;;1171:4:22;1163:13;;1449:6259:60;;;;;;1163:13:22;1449:6259:60;;;;;;;;;;;;;;", + "linkReferences": {} + } +} diff --git a/crates/op-rbuilder/src/tests/framework/artifacts/contracts/FlashtestationRegistry.json b/crates/op-rbuilder/src/tests/framework/artifacts/contracts/FlashtestationRegistry.json new file mode 100644 index 000000000..d823e0c37 --- /dev/null +++ b/crates/op-rbuilder/src/tests/framework/artifacts/contracts/FlashtestationRegistry.json @@ -0,0 +1,641 @@ +{ + "abi": [ + { + "type": "function", + "name": "MAX_BYTES_SIZE", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "REGISTER_TYPEHASH", + "inputs": [], + "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "TD_REPORTDATA_LENGTH", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "UPGRADE_INTERFACE_VERSION", + "inputs": [], + "outputs": [{ "name": "", "type": "string", "internalType": "string" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "attestationContract", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract IAttestation" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "computeStructHash", + "inputs": [ + { "name": "rawQuote", "type": "bytes", "internalType": "bytes" }, + { + "name": "extendedRegistrationData", + "type": "bytes", + "internalType": "bytes" + }, + { "name": "nonce", "type": "uint256", "internalType": "uint256" }, + { "name": "deadline", "type": "uint256", "internalType": "uint256" } + ], + "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }], + "stateMutability": "pure" + }, + { + "type": "function", + "name": "domainSeparator", + "inputs": [], + "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "eip712Domain", + "inputs": [], + "outputs": [ + { "name": "fields", "type": "bytes1", "internalType": "bytes1" }, + { "name": "name", "type": "string", "internalType": "string" }, + { "name": "version", "type": "string", "internalType": "string" }, + { "name": "chainId", "type": "uint256", "internalType": "uint256" }, + { + "name": "verifyingContract", + "type": "address", + "internalType": "address" + }, + { "name": "salt", "type": "bytes32", "internalType": "bytes32" }, + { + "name": "extensions", + "type": "uint256[]", + "internalType": "uint256[]" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getRegistration", + "inputs": [ + { "name": "teeAddress", "type": "address", "internalType": "address" } + ], + "outputs": [ + { "name": "", "type": "bool", "internalType": "bool" }, + { + "name": "", + "type": "tuple", + "internalType": "struct IFlashtestationRegistry.RegisteredTEE", + "components": [ + { "name": "isValid", "type": "bool", "internalType": "bool" }, + { "name": "rawQuote", "type": "bytes", "internalType": "bytes" }, + { + "name": "parsedReportBody", + "type": "tuple", + "internalType": "struct TD10ReportBody", + "components": [ + { + "name": "teeTcbSvn", + "type": "bytes16", + "internalType": "bytes16" + }, + { "name": "mrSeam", "type": "bytes", "internalType": "bytes" }, + { + "name": "mrsignerSeam", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "seamAttributes", + "type": "bytes8", + "internalType": "bytes8" + }, + { + "name": "tdAttributes", + "type": "bytes8", + "internalType": "bytes8" + }, + { "name": "xFAM", "type": "bytes8", "internalType": "bytes8" }, + { "name": "mrTd", "type": "bytes", "internalType": "bytes" }, + { + "name": "mrConfigId", + "type": "bytes", + "internalType": "bytes" + }, + { "name": "mrOwner", "type": "bytes", "internalType": "bytes" }, + { + "name": "mrOwnerConfig", + "type": "bytes", + "internalType": "bytes" + }, + { "name": "rtMr0", "type": "bytes", "internalType": "bytes" }, + { "name": "rtMr1", "type": "bytes", "internalType": "bytes" }, + { "name": "rtMr2", "type": "bytes", "internalType": "bytes" }, + { "name": "rtMr3", "type": "bytes", "internalType": "bytes" }, + { + "name": "reportData", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "name": "extendedRegistrationData", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "quoteHash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getRegistrationStatus", + "inputs": [ + { "name": "teeAddress", "type": "address", "internalType": "address" } + ], + "outputs": [ + { "name": "isValid", "type": "bool", "internalType": "bool" }, + { "name": "quoteHash", "type": "bytes32", "internalType": "bytes32" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "hashTypedDataV4", + "inputs": [ + { "name": "structHash", "type": "bytes32", "internalType": "bytes32" } + ], + "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "initialize", + "inputs": [ + { "name": "owner", "type": "address", "internalType": "address" }, + { + "name": "_attestationContract", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "invalidateAttestation", + "inputs": [ + { "name": "teeAddress", "type": "address", "internalType": "address" } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "invalidatePreviousSignature", + "inputs": [ + { "name": "_nonce", "type": "uint256", "internalType": "uint256" } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "nonces", + "inputs": [ + { "name": "teeAddress", "type": "address", "internalType": "address" } + ], + "outputs": [ + { "name": "permitNonce", "type": "uint256", "internalType": "uint256" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "owner", + "inputs": [], + "outputs": [{ "name": "", "type": "address", "internalType": "address" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "permitRegisterTEEService", + "inputs": [ + { "name": "rawQuote", "type": "bytes", "internalType": "bytes" }, + { + "name": "extendedRegistrationData", + "type": "bytes", + "internalType": "bytes" + }, + { "name": "nonce", "type": "uint256", "internalType": "uint256" }, + { "name": "deadline", "type": "uint256", "internalType": "uint256" }, + { "name": "signature", "type": "bytes", "internalType": "bytes" } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "proxiableUUID", + "inputs": [], + "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "registerTEEService", + "inputs": [ + { "name": "rawQuote", "type": "bytes", "internalType": "bytes" }, + { + "name": "extendedRegistrationData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "registeredTEEs", + "inputs": [ + { "name": "teeAddress", "type": "address", "internalType": "address" } + ], + "outputs": [ + { "name": "isValid", "type": "bool", "internalType": "bool" }, + { "name": "rawQuote", "type": "bytes", "internalType": "bytes" }, + { + "name": "parsedReportBody", + "type": "tuple", + "internalType": "struct TD10ReportBody", + "components": [ + { + "name": "teeTcbSvn", + "type": "bytes16", + "internalType": "bytes16" + }, + { "name": "mrSeam", "type": "bytes", "internalType": "bytes" }, + { + "name": "mrsignerSeam", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "seamAttributes", + "type": "bytes8", + "internalType": "bytes8" + }, + { + "name": "tdAttributes", + "type": "bytes8", + "internalType": "bytes8" + }, + { "name": "xFAM", "type": "bytes8", "internalType": "bytes8" }, + { "name": "mrTd", "type": "bytes", "internalType": "bytes" }, + { "name": "mrConfigId", "type": "bytes", "internalType": "bytes" }, + { "name": "mrOwner", "type": "bytes", "internalType": "bytes" }, + { + "name": "mrOwnerConfig", + "type": "bytes", + "internalType": "bytes" + }, + { "name": "rtMr0", "type": "bytes", "internalType": "bytes" }, + { "name": "rtMr1", "type": "bytes", "internalType": "bytes" }, + { "name": "rtMr2", "type": "bytes", "internalType": "bytes" }, + { "name": "rtMr3", "type": "bytes", "internalType": "bytes" }, + { "name": "reportData", "type": "bytes", "internalType": "bytes" } + ] + }, + { + "name": "extendedRegistrationData", + "type": "bytes", + "internalType": "bytes" + }, + { "name": "quoteHash", "type": "bytes32", "internalType": "bytes32" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "renounceOwnership", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferOwnership", + "inputs": [ + { "name": "newOwner", "type": "address", "internalType": "address" } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeToAndCall", + "inputs": [ + { + "name": "newImplementation", + "type": "address", + "internalType": "address" + }, + { "name": "data", "type": "bytes", "internalType": "bytes" } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "event", + "name": "EIP712DomainChanged", + "inputs": [], + "anonymous": false + }, + { + "type": "event", + "name": "Initialized", + "inputs": [ + { + "name": "version", + "type": "uint64", + "indexed": false, + "internalType": "uint64" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "OwnershipTransferred", + "inputs": [ + { + "name": "previousOwner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newOwner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "PreviousSignatureInvalidated", + "inputs": [ + { + "name": "teeAddress", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "invalidatedNonce", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "TEEServiceInvalidated", + "inputs": [ + { + "name": "teeAddress", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "TEEServiceRegistered", + "inputs": [ + { + "name": "teeAddress", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "rawQuote", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + }, + { + "name": "alreadyExists", + "type": "bool", + "indexed": false, + "internalType": "bool" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Upgraded", + "inputs": [ + { + "name": "implementation", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "AddressEmptyCode", + "inputs": [ + { "name": "target", "type": "address", "internalType": "address" } + ] + }, + { + "type": "error", + "name": "ByteSizeExceeded", + "inputs": [ + { "name": "size", "type": "uint256", "internalType": "uint256" } + ] + }, + { "type": "error", "name": "ECDSAInvalidSignature", "inputs": [] }, + { + "type": "error", + "name": "ECDSAInvalidSignatureLength", + "inputs": [ + { "name": "length", "type": "uint256", "internalType": "uint256" } + ] + }, + { + "type": "error", + "name": "ECDSAInvalidSignatureS", + "inputs": [{ "name": "s", "type": "bytes32", "internalType": "bytes32" }] + }, + { + "type": "error", + "name": "ERC1967InvalidImplementation", + "inputs": [ + { + "name": "implementation", + "type": "address", + "internalType": "address" + } + ] + }, + { "type": "error", "name": "ERC1967NonPayable", "inputs": [] }, + { + "type": "error", + "name": "ExpiredSignature", + "inputs": [ + { "name": "deadline", "type": "uint256", "internalType": "uint256" } + ] + }, + { "type": "error", "name": "FailedCall", "inputs": [] }, + { "type": "error", "name": "InvalidAttestationContract", "inputs": [] }, + { "type": "error", "name": "InvalidInitialization", "inputs": [] }, + { + "type": "error", + "name": "InvalidNonce", + "inputs": [ + { "name": "expected", "type": "uint256", "internalType": "uint256" }, + { "name": "provided", "type": "uint256", "internalType": "uint256" } + ] + }, + { + "type": "error", + "name": "InvalidQuote", + "inputs": [{ "name": "output", "type": "bytes", "internalType": "bytes" }] + }, + { + "type": "error", + "name": "InvalidQuoteLength", + "inputs": [ + { "name": "length", "type": "uint256", "internalType": "uint256" } + ] + }, + { + "type": "error", + "name": "InvalidRegistrationDataHash", + "inputs": [ + { "name": "expected", "type": "bytes32", "internalType": "bytes32" }, + { "name": "received", "type": "bytes32", "internalType": "bytes32" } + ] + }, + { + "type": "error", + "name": "InvalidReportDataLength", + "inputs": [ + { "name": "length", "type": "uint256", "internalType": "uint256" } + ] + }, + { + "type": "error", + "name": "InvalidTEEType", + "inputs": [ + { "name": "teeType", "type": "bytes4", "internalType": "bytes4" } + ] + }, + { + "type": "error", + "name": "InvalidTEEVersion", + "inputs": [ + { "name": "version", "type": "uint16", "internalType": "uint16" } + ] + }, + { "type": "error", "name": "NotInitializing", "inputs": [] }, + { + "type": "error", + "name": "OwnableInvalidOwner", + "inputs": [ + { "name": "owner", "type": "address", "internalType": "address" } + ] + }, + { + "type": "error", + "name": "OwnableUnauthorizedAccount", + "inputs": [ + { "name": "account", "type": "address", "internalType": "address" } + ] + }, + { "type": "error", "name": "ReentrancyGuardReentrantCall", "inputs": [] }, + { + "type": "error", + "name": "SignerMustMatchTEEAddress", + "inputs": [ + { "name": "signer", "type": "address", "internalType": "address" }, + { "name": "teeAddress", "type": "address", "internalType": "address" } + ] + }, + { + "type": "error", + "name": "TEEIsStillValid", + "inputs": [ + { "name": "teeAddress", "type": "address", "internalType": "address" } + ] + }, + { + "type": "error", + "name": "TEEServiceAlreadyInvalid", + "inputs": [ + { "name": "teeAddress", "type": "address", "internalType": "address" } + ] + }, + { + "type": "error", + "name": "TEEServiceAlreadyRegistered", + "inputs": [ + { "name": "teeAddress", "type": "address", "internalType": "address" } + ] + }, + { + "type": "error", + "name": "TEEServiceNotRegistered", + "inputs": [ + { "name": "teeAddress", "type": "address", "internalType": "address" } + ] + }, + { "type": "error", "name": "UUPSUnauthorizedCallContext", "inputs": [] }, + { + "type": "error", + "name": "UUPSUnsupportedProxiableUUID", + "inputs": [ + { "name": "slot", "type": "bytes32", "internalType": "bytes32" } + ] + } + ], + "bytecode": { + "object": "0x60a0806040523460295730608052614e62908161002e8239608051818181610a320152610c3e0152f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c80630634434a146101845780630ac3302b1461017f57806322ba2bbf1461017a578063485cc955146101755780634980f288146101705780634f1ef2861461016b57806352d1902d146101665780636a5306a314610161578063715018a61461015c57806372731062146101575780637ecebe001461015257806384b0196e1461014d578063878111121461014857806387be6d4e146101435780638da5cb5b1461013e578063a8af4ff514610139578063aaae748e14610134578063ad3cb1cc1461012f578063e41689521461012a578063f2fde38b14610125578063f698da2514610120578063f745cb301461011b5763f9b68b3114610116575f80fd5b611ac7565b611a11565b61163a565b6115f3565b6115ba565b61153d565b611503565b611492565b611422565b6113d2565b611340565b611221565b611110565b61105d565b610ce6565b610c8e565b610bf9565b6109b7565b61083e565b6105bd565b6102e9565b610248565b6101bb565b9181601f840112156101b75782359167ffffffffffffffff83116101b757602083818601950101116101b757565b5f80fd5b346101b75760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b75760043567ffffffffffffffff81116101b75761020a903690600401610189565b906024359067ffffffffffffffff82116101b757602092610232610240933690600401610189565b906044359260643594611c82565b604051908152f35b60a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b75760043567ffffffffffffffff81116101b757610292903690600401610189565b60243567ffffffffffffffff81116101b7576102b2903690600401610189565b6084359391606435916044359167ffffffffffffffff87116101b7576102df6102e7973690600401610189565b969095611d01565b005b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b75760043567ffffffffffffffff81116101b757610333903690600401610189565b60243567ffffffffffffffff81116101b757610353903690600401610189565b91909261035e612781565b61037861036c368484610981565b5161500081111561281a565b61038661036c368587610981565b6103c06103a75f5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b5f60405180927f38d8480a00000000000000000000000000000000000000000000000000000000825281806103f988886004840161288b565b039134905af1908115610572575f905f9261054b575b508161041a9161289c565b61042390613349565b6101c081018051516104399060348110156128e5565b5161044390613526565b73ffffffffffffffffffffffffffffffffffffffff821696906104698333808b14612918565b610474368884610981565b805190602001208181149161048892612969565b610493368686610981565b80519060200120906104a582846136e1565b966104ae610926565b60018152946104be368989610981565b6020870152604086015236906104d392610981565b606084015260808301526105059073ffffffffffffffffffffffffffffffffffffffff165f52600160205260405f2090565b9061050f91612dce565b60405192839261051f9284612f62565b037f206fdb1a74851a8542447b8b6704db24a36b906a7297cc23c2b984dc357b997891a26102e76127f5565b61041a925061056c91503d805f833e61056481836108e5565b8101906126a7565b9161040f565b61272c565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036101b757565b6024359073ffffffffffffffffffffffffffffffffffffffff821682036101b757565b346101b75760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b7576105f4610577565b6105fc61059a565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054919067ffffffffffffffff61064360ff604086901c16159467ffffffffffffffff1690565b1680159081610836575b600114908161082c575b159081610823575b506107fb576106e091836106d760017fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000007ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005416177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055565b61078057612071565b6106e657005b6107517fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055565b604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1005b6107f6680100000000000000007fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005416177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055565b612071565b7ff92ee8a9000000000000000000000000000000000000000000000000000000005f5260045ffd5b9050155f61065f565b303b159150610657565b84915061064d565b346101b75760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b75760206102406004356123af565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60a0810190811067ffffffffffffffff8211176108c357604052565b61087a565b6101e0810190811067ffffffffffffffff8211176108c357604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176108c357604052565b6040519061093560a0836108e5565b565b604051906109356101e0836108e5565b67ffffffffffffffff81116108c357601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b92919261098d82610947565b9161099b60405193846108e5565b8294818452818301116101b7578281602093845f960137010152565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b7576109e9610577565b60243567ffffffffffffffff81116101b757366023820112156101b757610a1a903690602481600401359101610981565b9073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016803014908115610bb7575b50610b8f57610a6a612f92565b604051917f52d1902d00000000000000000000000000000000000000000000000000000000835260208360048173ffffffffffffffffffffffffffffffffffffffff86165afa5f9381610b5e575b50610aff577f4c9c8ce3000000000000000000000000000000000000000000000000000000005f5273ffffffffffffffffffffffffffffffffffffffff821660045260245ffd5b907f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8303610b31576102e79250613964565b7faa1d49a4000000000000000000000000000000000000000000000000000000005f52600483905260245ffd5b610b8191945060203d602011610b88575b610b7981836108e5565b810190612f83565b925f610ab8565b503d610b6f565b7fe07c8dba000000000000000000000000000000000000000000000000000000005f5260045ffd5b905073ffffffffffffffffffffffffffffffffffffffff7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541614155f610a5d565b346101b7575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b75773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163003610b8f5760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b346101b7575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b75760206040517f95b0f36aa3383d49f247995a06db7a3bd7d07a2e7fe943cfdfc72b826979736a8152f35b346101b7575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b757610d1c612f92565b5f73ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300547fffffffffffffffffffffffff000000000000000000000000000000000000000081167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b816101c0610fa0610f8c610f78610f64610f50610f3c610f28610f16610e80610e6d610fb29d6101e060208f8190610e5d8582517fffffffffffffffffffffffffffffffff00000000000000000000000000000000169052565b01519201526101e08d0190610dc0565b60408d01518c6040818403910152610dc0565b60608c8101517fffffffffffffffff00000000000000000000000000000000000000000000000016908c015260808c8101517fffffffffffffffff00000000000000000000000000000000000000000000000016908c015260a08c8101517fffffffffffffffff00000000000000000000000000000000000000000000000016908c015260c08c01518b820360c08d0152610dc0565b60e08b01518a820360e08c0152610dc0565b6101008a01518982036101008b0152610dc0565b6101208901518882036101208a0152610dc0565b610140880151878203610140890152610dc0565b610160870151868203610160880152610dc0565b610180860151858203610180870152610dc0565b6101a08501518482036101a0860152610dc0565b920151906101c0818403910152610dc0565b90565b90151581526040602082015281511515604082015260c06080611054611020610fed602087015160a0606088015260e0870190610dc0565b60408701517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08783030185880152610e03565b60608601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08683030160a0870152610dc0565b93015191015290565b346101b75760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b75773ffffffffffffffffffffffffffffffffffffffff6110a9610577565b5f60806040516110b8816108a7565b828152606060208201526110ca61244c565b6040820152606080820152015216805f52600160205260ff60405f205416905f5260016020526110fc60405f206124b9565b9061110c60405192839283610fb5565b0390f35b346101b75760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b75773ffffffffffffffffffffffffffffffffffffffff61115c610577565b165f526002602052602060405f2054604051908152f35b92939073ffffffffffffffffffffffffffffffffffffffff926111c76111d5927f0f00000000000000000000000000000000000000000000000000000000000000875260e0602088015260e0870190610dc0565b908582036040870152610dc0565b9360608401521660808201525f60a082015260c0818303910152602080835192838152019201905f5b81811061120b5750505090565b82518452602093840193909201916001016111fe565b346101b7575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b7577fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100541580611317575b156112b957611285612ffe565b61128d61310d565b9061110c60405161129f6020826108e5565b5f8082523660208301376040519384933091469186611173565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4549503731323a20556e696e697469616c697a656400000000000000000000006044820152fd5b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1015415611278565b346101b75760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b757600435335f52600260205261138c60405f20549182808214611fac565b335f52600260205260405f206113a28154612010565b90556040519081527faba960b001cf41ae7d1278e08bf0afa5081bfad043326cfe1e1d5ee266c9ac5260203392a2005b346101b7575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b757602073ffffffffffffffffffffffffffffffffffffffff5f5416604051908152f35b346101b7575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b757602073ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b346101b75760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b75773ffffffffffffffffffffffffffffffffffffffff6114de610577565b165f5260016020526040805f20601060ff825416910154825191151582526020820152f35b346101b7575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b75760206040516150008152f35b346101b7575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b75761110c60405161157c6040826108e5565b600581527f352e302e300000000000000000000000000000000000000000000000000000006020820152604051918291602083526020830190610dc0565b346101b7575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b757602060405160348152f35b346101b75760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b7576102e761162d610577565b611635612f92565b612526565b346101b7575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b757611670614cc3565b611678614d2d565b6040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a081526116c960c0826108e5565b519020604051908152602090f35b90600182811c9216801561171e575b60208310146116f157565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b91607f16916116e6565b5f9291815491611737836116d7565b808352926001811690811561178c575060011461175357505050565b5f9081526020812093945091925b838310611772575060209250010190565b600181602092949394548385870101520191019190611761565b905060209495507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091509291921683830152151560051b010190565b906109356117dc9260405193848092611728565b03836108e5565b906119c1600c6117f1610937565b93611826611800825460801b90565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000168652565b611832600182016117c8565b6020860152611843600282016117c8565b604086015261192d61190460038301546118896118608260c01b90565b7fffffffffffffffff0000000000000000000000000000000000000000000000001660608a0152565b6118dc608082901b7fffffffffffffffff000000000000000000000000000000000000000000000000167fffffffffffffffff0000000000000000000000000000000000000000000000001660808a0152565b60401b7fffffffffffffffff0000000000000000000000000000000000000000000000001690565b7fffffffffffffffff0000000000000000000000000000000000000000000000001660a0870152565b611939600482016117c8565b60c086015261194a600582016117c8565b60e086015261195b600682016117c8565b61010086015261196d600782016117c8565b61012086015261197f600882016117c8565b610140860152611991600982016117c8565b6101608601526119a3600a82016117c8565b6101808601526119b5600b82016117c8565b6101a0860152016117c8565b6101c0830152565b959493906080936119f0611a0c946119fe9315158a5260a060208b015260a08a0190610dc0565b9088820360408a0152610e03565b908682036060880152610dc0565b930152565b346101b75760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b75773ffffffffffffffffffffffffffffffffffffffff611a5d610577565b165f52600160205260405f2060ff81541661110c60405192611a8d84611a868160018501611728565b03856108e5565b611a99600282016117e3565b90601060405191611ab883611ab181600f8501611728565b03846108e5565b015491604051958695866119c9565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101b757611bb2611afc610577565b611b04612781565b5f611b35611b308373ffffffffffffffffffffffffffffffffffffffff165f52600160205260405f2090565b6124b9565b611b5a83611b556020840193611b4f838651511515612613565b51151590565b61265d565b611b7b6103a7835473ffffffffffffffffffffffffffffffffffffffff1690565b90519060405180809681947f38d8480a0000000000000000000000000000000000000000000000000000000083526004830161271b565b039134905af180156105725781611be79173ffffffffffffffffffffffffffffffffffffffff945f91611c67575b5015612737565b611c3a611c128273ffffffffffffffffffffffffffffffffffffffff165f52600160205260405f2090565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008154169055565b167f5bb0bbb0993a623e10dd3579bf5b9403deba943e0bfe950b740d60209c9135ef5f80a26102e76127f5565b611c7b91503d805f833e61056481836108e5565b505f611be0565b611c9590611ca493929694963691610981565b60208151910120943691610981565b60208151910120916040519260208401947f95b0f36aa3383d49f247995a06db7a3bd7d07a2e7fe943cfdfc72b826979736a865260408501526060840152608083015260a082015260a08152611cfb60c0826108e5565b51902090565b9396611d3e90611d388598611d30611d2b8a8d899a611d479a8a9e9a8e611d26612781565b611c82565b6123af565b923691610981565b906131de565b9093919361324f565b611d7773ffffffffffffffffffffffffffffffffffffffff831697885f52600260205260405f2054808214611fac565b804211611f815750855f52600260205260405f20611d958154612010565b9055611da561036c368686610981565b611db361036c368785610981565b611dd46103a75f5473ffffffffffffffffffffffffffffffffffffffff1690565b5f60405180927f38d8480a0000000000000000000000000000000000000000000000000000000082528180611e0d8a8a6004840161288b565b039134905af1908115610572575f905f92611f62575b5081611e2e9161289c565b611e3790613349565b916101c08301805151603481101590611e4f916128e5565b51611e5990613526565b90928373ffffffffffffffffffffffffffffffffffffffff8116809a1491611e8092612918565b611e8b368884610981565b8051906020012081811491611e9f92612969565b611eaa368686610981565b8051906020012090611ebc82846136e1565b96611ec5610926565b6001815294611ed5368989610981565b602087015260408601523690611eea92610981565b60608401526080830152611f1c9073ffffffffffffffffffffffffffffffffffffffff165f52600160205260405f2090565b90611f2691612dce565b604051928392611f369284612f62565b037f206fdb1a74851a8542447b8b6704db24a36b906a7297cc23c2b984dc357b997891a26109356127f5565b611e2e9250611f7b91503d805f833e61056481836108e5565b91611e23565b7fbd2a913c000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b15611fb5575050565b7f06427aeb000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461203d5760010190565b611fe3565b1561204957565b7f72cd95d7000000000000000000000000000000000000000000000000000000005f5260045ffd5b6120889092919261208061373f565b61163561373f565b60409182519261209881856108e5565b601684527f466c617368746573746174696f6e52656769737472790000000000000000000060208501526120ce815191826108e5565b600181527f3100000000000000000000000000000000000000000000000000000000000000602082015261210061373f565b61210861373f565b835167ffffffffffffffff81116108c35761214c816121477fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102546116d7565b6129b6565b6020601f821160011461229457916121b7826121de9373ffffffffffffffffffffffffffffffffffffffff969561093598995f92612289575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10255613796565b6122065f7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10055565b61222e5f7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10155565b61223661373f565b61223e61373f565b1661224a811515612042565b73ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffff00000000000000000000000000000000000000005f5416175f55565b015190505f80612185565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1025f527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08216957f42ad5d3e1f2e6e70edcf6d991b8a3023d3fca8047a131592f9edb9fd9b89d57d965f5b818110612397575092610935969773ffffffffffffffffffffffffffffffffffffffff969593600193836121de9710612360575b505050811b017fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10255613796565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690555f8080612333565b838301518955600190980197602093840193016122ff565b6042906123ba614cc3565b6123c2614d2d565b6040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a0815261241360c0826108e5565b51902090604051917f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201522090565b60405190612459826108c8565b60606101c0835f81528260208201528260408201525f838201525f60808201525f60a08201528260c08201528260e08201528261010082015282610120820152826101408201528261016082015282610180820152826101a08201520152565b906040516124c6816108a7565b60806010829460ff815416151584526040516124f0816124e98160018601611728565b03826108e5565b6020850152612501600282016117e3565b604085015260405161251a816124e981600f8601611728565b60608501520154910152565b73ffffffffffffffffffffffffffffffffffffffff1680156125e75773ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054827fffffffffffffffffffffffff00000000000000000000000000000000000000008216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b7f1e4fbdf7000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b1561261b5750565b73ffffffffffffffffffffffffffffffffffffffff907fbb527454000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b156126655750565b73ffffffffffffffffffffffffffffffffffffffff907f138c0ee8000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b91906040838203126101b757825180151581036101b7579260208101519067ffffffffffffffff82116101b7570181601f820112156101b7578051906126ec82610947565b926126fa60405194856108e5565b828452602083830101116101b757815f9260208093018386015e8301015290565b906020610fb2928181520190610dc0565b6040513d5f823e3d90fd5b1561273f5750565b73ffffffffffffffffffffffffffffffffffffffff907f927b3443000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c6127cd5760017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d565b156128225750565b7f9e24c2f6000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b916020610fb293818152019161284d565b156128a45750565b6128e1906040519182917f64d10cb10000000000000000000000000000000000000000000000000000000083526020600484018181520190610dc0565b0390fd5b156128ed5750565b7f4fe16298000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b15612921575050565b9073ffffffffffffffffffffffffffffffffffffffff80927f38e0a7e5000000000000000000000000000000000000000000000000000000005f52166004521660245260445ffd5b15612972575050565b7fcc14da59000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b8181106129ab575050565b5f81556001016129a0565b90601f82116129c3575050565b610935917fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1025f5260205f20906020601f840160051c83019310612a0e575b601f0160051c01906129a0565b9091508190612a01565b9190601f8111612a2757505050565b610935925f5260205f20906020601f840160051c83019310612a0e57601f0160051c01906129a0565b919091825167ffffffffffffffff81116108c357612a7881612a7284546116d7565b84612a18565b6020601f8211600114612ac9578190612ac59394955f926122895750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b9055565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0821690612afa845f5260205f2090565b915f5b818110612b5357509583600195969710612b1c575b505050811b019055565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690555f8080612b12565b9192602060018192868b015181550194019201612afd565b600c6101c061093593612bcf612ba182517fffffffffffffffffffffffffffffffff000000000000000000000000000000001690565b859060801c7fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055565b612be0602082015160018601612a50565b612bf1604082015160028601612a50565b612d3760038501612c56612c2860608501517fffffffffffffffff0000000000000000000000000000000000000000000000001690565b829060c01c7fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000825416179055565b612cc7612c8660808501517fffffffffffffffff0000000000000000000000000000000000000000000000001690565b82547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff1660809190911c6fffffffffffffffff000000000000000016178255565b60a08301517fffffffffffffffff0000000000000000000000000000000000000000000000001681547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1660409190911c77ffffffffffffffff0000000000000000000000000000000016179055565b612d4860c082015160048601612a50565b612d5960e082015160058601612a50565b612d6b61010082015160068601612a50565b612d7d61012082015160078601612a50565b612d8f61014082015160088601612a50565b612da161016082015160098601612a50565b612db3610180820151600a8601612a50565b612dc56101a0820151600b8601612a50565b01519101612a50565b90612e0781511515839060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b60018201602082015180519067ffffffffffffffff82116108c357612e3682612e3085546116d7565b85612a18565b602090601f8311600114612eb557826010959360809593612e89935f926122895750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90555b612e9d604082015160028601612b6b565b612eae6060820151600f8601612a50565b0151910155565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0831691612ee7855f5260205f2090565b925f5b818110612f4a5750926001928592601098966080989610612f13575b505050811b019055612e8c565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690555f8080612f06565b92936020600181928786015181550195019301612eea565b91602091612f7b9195949560408552604085019161284d565b931515910152565b908160209103126101b7575190565b73ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054163303612fd257565b7f118cdaa7000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b6040517fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10254815f61302e836116d7565b80835292600181169081156130d05750600114613052575b610fb2925003826108e5565b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1025f90815290917f42ad5d3e1f2e6e70edcf6d991b8a3023d3fca8047a131592f9edb9fd9b89d57d5b8183106130b4575050906020610fb292820101613046565b602091935080600191548385880101520191019091839261309c565b60209250610fb29491507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001682840152151560051b820101613046565b6040517fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10354815f61313d836116d7565b80835292600181169081156130d0575060011461316057610fb2925003826108e5565b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1035f90815290917f5f9ce34815f8e11431c7bb75a8e6886a91478f7ffc1dbb0a98dc240fddd76b755b8183106131c2575050906020610fb292820101613046565b60209193508060019154838588010152019101909183926131aa565b815191906041830361320e576132079250602082015190606060408401519301515f1a90613a95565b9192909190565b50505f9160029190565b6004111561322257565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b61325881613218565b80613261575050565b61326a81613218565b6001810361329a577ff645eedf000000000000000000000000000000000000000000000000000000005f5260045ffd5b6132a381613218565b600281036132d757507ffce698f7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b806132e3600392613218565b146132eb5750565b7fd78bce0c000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b1561331e5750565b7fd915602a000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b61335161244c565b5080516002116101b7576133656002610947565b61337260405191826108e5565b600281526133806002610947565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602082019201368337816020840160025b60208110156134d857806134b957507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905b51825182169119161790525190517fffff00000000000000000000000000000000000000000000000000000000000081169160028110613484575b505060f01c6004810361345957506134548161343e610fb293613b24565b805161344f90610255811015613316565b613cc9565b614af4565b7f940a5ec6000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7fffff0000000000000000000000000000000000000000000000000000000000009250829060020360031b1b16165f80613420565b6134cd6134c86134d292614d72565b614dad565b614d80565b906133e5565b9091825181526020810180911161203d57916020810180911161203d57907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101908111156133b357611fe3565b80516014116101b7576135396014610947565b9161354760405193846108e5565b601483526135556014610947565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060208501910136823760149381602085015b60208710156136945761360994959680155f1461367f57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905b51825182169119161790525190517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008116916014811061364a575b505060601c92613dd1565b60208151910151906020811061361d575090565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060200360031b1b1690565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009250829060140360031b1b16165f806135fe565b6134cd6134c861368e92614d72565b906135c3565b90815181526020810180911161203d57906020810180911161203d57957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810190811161203d5795613588565b73ffffffffffffffffffffffffffffffffffffffff16805f526001602052601060405f2001548092146137145750151590565b7ffb5bab5b000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561376e57565b7fd7e6bcf8000000000000000000000000000000000000000000000000000000005f5260045ffd5b90815167ffffffffffffffff81116108c3576137fc816137d67fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d103546116d7565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d103612a18565b602092601f821160011461386d57613849929382915f926122895750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10355565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1035f527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08216937f5f9ce34815f8e11431c7bb75a8e6886a91478f7ffc1dbb0a98dc240fddd76b75915f5b86811061394c5750836001959610613915575b505050811b017fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10355565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690555f80806138eb565b919260206001819286850151815501940192016138d8565b90813b15613a535773ffffffffffffffffffffffffffffffffffffffff8216807fffffffffffffffffffffffff00000000000000000000000000000000000000007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416177f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a2805115613a2257613a1f91614c7f565b50565b505034613a2b57565b7fb398979f000000000000000000000000000000000000000000000000000000005f5260045ffd5b73ffffffffffffffffffffffffffffffffffffffff827f4c9c8ce3000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411613b19579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa15610572575f5173ffffffffffffffffffffffffffffffffffffffff811615613b0f57905f905f90565b505f906001905f90565b5050505f9160039190565b9081516006116101b757613b386004610947565b613b4560405191826108e5565b60048152613b536004610947565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060208201920136833760226004940182905b6020861015613c7c577fffffffff00000000000000000000000000000000000000000000000000000000949580155f14613c6757507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905b51825182169119161790525190518281169160048110613c52575b5050167f81000000000000000000000000000000000000000000000000000000000000008103613c275750565b7fea75591a000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b839250829060040360031b1b16165f80613bfa565b6134cd6134c8613c7692614d72565b90613bdf565b90815181526020810180911161203d57906020810180911161203d57947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810190811161203d5794613b87565b8051610255116101b757613cde610248610947565b90613cec60405192836108e5565b6102488252613cfc610248610947565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060208401910136823790602d016102485b6020811015613d835780613d6e57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905b518251821691191617905290565b6134cd6134c8613d7d92614d72565b90613d60565b9091825181526020810180911161203d57916020810180911161203d57907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810190811115613d2e57611fe3565b80516034116101b757613de46020610947565b90613df260405192836108e5565b60208252613e006020610947565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06020840191013682379060340160205b6020811015613e475780613d6e57509192915050565b9091825181526020810180911161203d57916020810180911161203d57907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810190811115613e3157611fe3565b80516010116101b757613ea86010610947565b90613eb660405192836108e5565b60108252613ec46010610947565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06020840191013682379060200160105b6020811015613f0b5780613d6e57509192915050565b9091825181526020810180911161203d57916020810180911161203d57907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810190811115613ef557611fe3565b80516040116101b757613f6c6030610947565b90613f7a60405192836108e5565b60308252613f886030610947565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602084019101368237603080920190915b6020811015613fd05780613d6e57509192915050565b9091825181526020810180911161203d57916020810180911161203d57907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810190811115613fba57611fe3565b80516070116101b7576140316030610947565b9061403f60405192836108e5565b6030825261404d6030610947565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06020840191013682379060600160305b60208110156140945780613d6e57509192915050565b9091825181526020810180911161203d57916020810180911161203d57907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019081111561407e57611fe3565b80516078116101b7576140f56008610947565b9061410360405192836108e5565b600882526141116008610947565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06020840191013682379060900160085b60208110156141585780613d6e57509192915050565b9091825181526020810180911161203d57916020810180911161203d57907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019081111561414257611fe3565b80516080116101b7576141b96008610947565b906141c760405192836108e5565b600882526141d56008610947565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06020840191013682379060980160085b602081101561421c5780613d6e57509192915050565b9091825181526020810180911161203d57916020810180911161203d57907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019081111561420657611fe3565b80516088116101b75761427d6008610947565b9061428b60405192836108e5565b600882526142996008610947565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06020840191013682379060a00160085b60208110156142e05780613d6e57509192915050565b9091825181526020810180911161203d57916020810180911161203d57907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101908111156142ca57611fe3565b805160b8116101b7576143416030610947565b9061434f60405192836108e5565b6030825261435d6030610947565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06020840191013682379060a80160305b60208110156143a45780613d6e57509192915050565b9091825181526020810180911161203d57916020810180911161203d57907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019081111561438e57611fe3565b805160e8116101b7576144056030610947565b9061441360405192836108e5565b603082526144216030610947565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06020840191013682379060d80160305b60208110156144685780613d6e57509192915050565b9091825181526020810180911161203d57916020810180911161203d57907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019081111561445257611fe3565b8051610118116101b7576144ca6030610947565b906144d860405192836108e5565b603082526144e66030610947565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602084019101368237906101080160305b602081101561452e5780613d6e57509192915050565b9091825181526020810180911161203d57916020810180911161203d57907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019081111561451857611fe3565b8051610148116101b7576145906030610947565b9061459e60405192836108e5565b603082526145ac6030610947565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602084019101368237906101380160305b60208110156145f45780613d6e57509192915050565b9091825181526020810180911161203d57916020810180911161203d57907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101908111156145de57611fe3565b8051610178116101b7576146566030610947565b9061466460405192836108e5565b603082526146726030610947565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602084019101368237906101680160305b60208110156146ba5780613d6e57509192915050565b9091825181526020810180911161203d57916020810180911161203d57907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101908111156146a457611fe3565b80516101a8116101b75761471c6030610947565b9061472a60405192836108e5565b603082526147386030610947565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602084019101368237906101980160305b60208110156147805780613d6e57509192915050565b9091825181526020810180911161203d57916020810180911161203d57907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019081111561476a57611fe3565b80516101d8116101b7576147e26030610947565b906147f060405192836108e5565b603082526147fe6030610947565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602084019101368237906101c80160305b60208110156148465780613d6e57509192915050565b9091825181526020810180911161203d57916020810180911161203d57907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019081111561483057611fe3565b8051610208116101b7576148a86030610947565b906148b660405192836108e5565b603082526148c46030610947565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602084019101368237906101f80160305b602081101561490c5780613d6e57509192915050565b9091825181526020810180911161203d57916020810180911161203d57907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101908111156148f657611fe3565b8051610248116101b75761496e6040610947565b9061497c60405192836108e5565b6040825261498a6040610947565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602084019101368237906102280160405b60208110156149d25780613d6e57509192915050565b9091825181526020810180911161203d57916020810180911161203d57907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101908111156149bc57611fe3565b90602082519201517fffffffffffffffffffffffffffffffff0000000000000000000000000000000081169260108110614a58575050565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000929350829060100360031b1b161690565b90602082519201517fffffffffffffffff00000000000000000000000000000000000000000000000081169260088110614ac2575050565b7fffffffffffffffff000000000000000000000000000000000000000000000000929350829060080360031b1b161690565b906119c1614b0061244c565b92614b3b614b15614b1083613e95565b614a20565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000168552565b614b4481613f59565b6020850152614b528161401e565b6040850152614b94614b6b614b66836140e2565b614a8a565b7fffffffffffffffff000000000000000000000000000000000000000000000000166060860152565b614bcc614ba3614b66836141a6565b7fffffffffffffffff000000000000000000000000000000000000000000000000166080860152565b614c04614bdb614b668361426a565b7fffffffffffffffff0000000000000000000000000000000000000000000000001660a0860152565b614c0d8161432e565b60c0850152614c1b816143f2565b60e0850152614c29816144b6565b610100850152614c388161457c565b610120850152614c4781614642565b610140850152614c5681614708565b610160850152614c65816147ce565b610180850152614c7481614894565b6101a085015261495a565b5f80610fb293602081519101845af43d15614cbb573d91614c9f83610947565b92614cad60405194856108e5565b83523d5f602085013e614dbc565b606091614dbc565b614ccb612ffe565b8051908115614cdb576020012090565b50507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100548015614d085790565b507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47090565b614d3561310d565b8051908115614d45576020012090565b50507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d101548015614d085790565b602003906020821161203d57565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161203d57565b601f811161203d576101000a90565b90614df95750805115614dd157805190602001fd5b7fd6bda275000000000000000000000000000000000000000000000000000000005f5260045ffd5b81511580614e4c575b614e0a575090565b73ffffffffffffffffffffffffffffffffffffffff907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b50803b15614e0256fea164736f6c634300081c000a", + "sourceMap": "1080:11972:97:-:0;;;;;;;1171:4:51;1163:13;;1080:11972:97;;;;;;1163:13:51;1080:11972:97;;;;;;;;;;;;;;", + "linkReferences": {} + } +} diff --git a/crates/op-rbuilder/src/tests/framework/artifacts/contracts/MockAutomataDcapAttestationFee.json b/crates/op-rbuilder/src/tests/framework/artifacts/contracts/MockAutomataDcapAttestationFee.json new file mode 100644 index 000000000..1ccf04a53 --- /dev/null +++ b/crates/op-rbuilder/src/tests/framework/artifacts/contracts/MockAutomataDcapAttestationFee.json @@ -0,0 +1,86 @@ +{ + "abi": [ + { + "type": "function", + "name": "baseFee", + "inputs": [], + "outputs": [ + { "name": "", "type": "uint256", "internalType": "uint256" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "quoteResults", + "inputs": [ + { "name": "", "type": "bytes", "internalType": "bytes" } + ], + "outputs": [ + { "name": "success", "type": "bool", "internalType": "bool" }, + { "name": "output", "type": "bytes", "internalType": "bytes" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "setBaseFee", + "inputs": [ + { + "name": "_baseFee", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setQuoteResult", + "inputs": [ + { + "name": "rawQuote", + "type": "bytes", + "internalType": "bytes" + }, + { "name": "_success", "type": "bool", "internalType": "bool" }, + { "name": "_output", "type": "bytes", "internalType": "bytes" } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "verifyAndAttestOnChain", + "inputs": [ + { "name": "rawQuote", "type": "bytes", "internalType": "bytes" } + ], + "outputs": [ + { "name": "", "type": "bool", "internalType": "bool" }, + { "name": "", "type": "bytes", "internalType": "bytes" } + ], + "stateMutability": "payable" + }, + { + "type": "error", + "name": "InsufficientFee", + "inputs": [ + { + "name": "required", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "provided", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ], + "bytecode": { + "object": "0x608080604052346015576106fa908161001a8239f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c806338d8480a146103b957806346860698146103825780636ef25c3a1461034757806389e7a16d146102b957639321d73e14610050575f80fd5b346102b55760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102b55760043567ffffffffffffffff81116102b55761009f90369060040161048d565b6024358015158091036102b5576044359167ffffffffffffffff83116102b55760206100d1600194369060040161056a565b94604051936100df8561050d565b845281840195865282604051938492833781015f8152030190209051151560ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00835416911617815501905190815167ffffffffffffffff81116102885761014782546105de565b601f8111610243575b50602092601f82116001146101aa57928192935f9261019f575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790555f80f35b015190505f8061016a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0821693835f52805f20915f5b86811061022b57508360019596106101f4575b505050811b019055005b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690555f80806101ea565b919260206001819286850151815501940192016101d7565b825f5260205f20601f830160051c8101916020841061027e575b601f0160051c01905b8181106102735750610150565b5f8155600101610266565b909150819061025d565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f80fd5b346102b55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102b55760043567ffffffffffffffff81116102b557602061030b8192369060040161056a565b604051928184925191829101835e81015f815203019020610333600160ff835416920161062f565b90610343604051928392836104bb565b0390f35b346102b5575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102b5576020600154604051908152f35b346102b55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102b557600435600155005b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102b55760043567ffffffffffffffff81116102b55761040390369060040161048d565b9060015480341061045e575060209082604051938492833781015f8152030190206104456001604051926104368461050d565b60ff815416151584520161062f565b90816020820152511515610343604051928392836104bb565b7fa458261b000000000000000000000000000000000000000000000000000000005f526004523460245260445ffd5b9181601f840112156102b55782359167ffffffffffffffff83116102b557602083818601950101116102b557565b90601f60206060947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093151585526040828601528051918291826040880152018686015e5f8582860101520116010190565b6040810190811067ffffffffffffffff82111761028857604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761028857604052565b81601f820112156102b55780359067ffffffffffffffff821161028857604051926105bd60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8601160185610529565b828452602083830101116102b557815f926020809301838601378301015290565b90600182811c92168015610625575b60208310146105f857565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b91607f16916105ed565b9060405191825f825492610642846105de565b80845293600181169081156106ad5750600114610669575b5061066792500383610529565b565b90505f9291925260205f20905f915b818310610691575050906020610667928201015f61065a565b6020919350806001915483858901015201910190918492610678565b602093506106679592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201015f61065a56fea164736f6c634300081c000a", + "sourceMap": "865:844:109:-:0;;;;;;;;;;;;;;;;;", + "linkReferences": {} + } +} diff --git a/crates/op-rbuilder/src/tests/framework/artifacts/quote-output.bin b/crates/op-rbuilder/src/tests/framework/artifacts/quote-output.bin new file mode 100644 index 000000000..84b2c09b7 Binary files /dev/null and b/crates/op-rbuilder/src/tests/framework/artifacts/quote-output.bin differ diff --git a/crates/op-rbuilder/src/tests/framework/artifacts/test-quote.bin b/crates/op-rbuilder/src/tests/framework/artifacts/test-quote.bin new file mode 100644 index 000000000..057f9ed2d Binary files /dev/null and b/crates/op-rbuilder/src/tests/framework/artifacts/test-quote.bin differ diff --git a/crates/op-rbuilder/src/tests/framework/contracts.rs b/crates/op-rbuilder/src/tests/framework/contracts.rs new file mode 100644 index 000000000..5f9b24493 --- /dev/null +++ b/crates/op-rbuilder/src/tests/framework/contracts.rs @@ -0,0 +1,43 @@ +pub mod flashtestation_registry { + use crate::tests::framework::contracts::block_builder_policy::BlockBuilderPolicy::TD10ReportBody; + use alloy_sol_types::sol; + + sol!( + // https://github.com/flashbots/flashtestations/tree/7cc7f68492fe672a823dd2dead649793aac1f216 + #[sol(rpc, abi)] + FlashtestationRegistry, + "src/tests/framework/artifacts/contracts/FlashtestationRegistry.json", + ); +} + +pub mod block_builder_policy { + use crate::tests::framework::contracts::block_builder_policy::BlockBuilderPolicy::TD10ReportBody; + use alloy_sol_types::sol; + + sol!( + // https://github.com/flashbots/flashtestations/tree/7cc7f68492fe672a823dd2dead649793aac1f216 + #[sol(rpc, abi)] + BlockBuilderPolicy, + "src/tests/framework/artifacts/contracts/BlockBuilderPolicy.json", + ); +} + +pub mod flashblocks_number_contract { + use alloy_sol_types::sol; + sol!( + // https://github.com/Uniswap/flashblocks_number_contract/tree/c21ca0aedc3ff4d1eecf20cd55abeb984080bc78 + #[sol(rpc, abi)] + FlashblocksNumber, + "src/tests/framework/artifacts/contracts/FlashblocksNumberContract.json", + ); +} + +pub mod mock_dcap_attestation { + use alloy_sol_types::sol; + sol!( + // https://github.com/flashbots/flashtestations/tree/7cc7f68492fe672a823dd2dead649793aac1f216 + #[sol(rpc, abi)] + MockAutomataDcapAttestationFee, + "src/tests/framework/artifacts/contracts/MockAutomataDcapAttestationFee.json", + ); +} diff --git a/crates/op-rbuilder/src/tests/framework/driver.rs b/crates/op-rbuilder/src/tests/framework/driver.rs index 5f273c1c1..6e9f83f76 100644 --- a/crates/op-rbuilder/src/tests/framework/driver.rs +++ b/crates/op-rbuilder/src/tests/framework/driver.rs @@ -14,12 +14,10 @@ use rollup_boost::OpExecutionPayloadEnvelope; use super::{EngineApi, Ipc, LocalInstance, TransactionBuilder}; use crate::{ args::OpRbuilderArgs, - tests::{ExternalNode, Protocol}, + tests::{ExternalNode, Protocol, framework::DEFAULT_GAS_LIMIT}, tx_signer::Signer, }; -const DEFAULT_GAS_LIMIT: u64 = 10_000_000; - /// The ChainDriver is a type that allows driving the op builder node to build new blocks manually /// by calling the `build_new_block` method. It uses the Engine API to interact with the node /// and the provider to fetch blocks and transactions. diff --git a/crates/op-rbuilder/src/tests/framework/instance.rs b/crates/op-rbuilder/src/tests/framework/instance.rs index 7a9ba14b4..7721ae2b0 100644 --- a/crates/op-rbuilder/src/tests/framework/instance.rs +++ b/crates/op-rbuilder/src/tests/framework/instance.rs @@ -4,8 +4,8 @@ use crate::{ primitives::reth::engine_api_builder::OpEngineApiBuilder, revert_protection::{EthApiExtServer, RevertProtectionExt}, tests::{ - EngineApi, Ipc, TransactionPoolObserver, create_test_db, - framework::{BUILDER_PRIVATE_KEY, driver::ChainDriver}, + EngineApi, Ipc, TransactionPoolObserver, builder_signer, create_test_db, + framework::driver::ChainDriver, }, tx::FBPooledTransaction, tx_signer::Signer, @@ -88,14 +88,7 @@ impl LocalInstance { let (txpool_ready_tx, txpool_ready_rx) = oneshot::channel::>(); - let signer = args.builder_signer.unwrap_or_else(|| { - Signer::try_from_secret( - BUILDER_PRIVATE_KEY - .parse() - .expect("Invalid builder private key"), - ) - .expect("Failed to create signer from private key") - }); + let signer = args.builder_signer.unwrap_or(builder_signer()); args.builder_signer = Some(signer); args.rollup_args.enable_tx_conditional = true; diff --git a/crates/op-rbuilder/src/tests/framework/mod.rs b/crates/op-rbuilder/src/tests/framework/mod.rs index d9c7bf1fb..4e3171fb9 100644 --- a/crates/op-rbuilder/src/tests/framework/mod.rs +++ b/crates/op-rbuilder/src/tests/framework/mod.rs @@ -1,4 +1,5 @@ mod apis; +mod contracts; mod driver; mod external; mod instance; @@ -6,17 +7,20 @@ mod txs; mod utils; pub use apis::*; +pub use contracts::*; pub use driver::*; pub use external::*; pub use instance::*; pub use txs::*; pub use utils::*; -const BUILDER_PRIVATE_KEY: &str = +pub const BUILDER_PRIVATE_KEY: &str = "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"; -const FUNDED_PRIVATE_KEYS: &[&str] = - &["0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"]; +pub const FUNDED_PRIVATE_KEY: &str = + "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; + +pub const DEFAULT_GAS_LIMIT: u64 = 10_000_000; pub const DEFAULT_JWT_TOKEN: &str = "688f5d737bad920bdfb2fc2f488d6b6209eebda1dae949a8de91398d932c517a"; diff --git a/crates/op-rbuilder/src/tests/framework/txs.rs b/crates/op-rbuilder/src/tests/framework/txs.rs index 7c91892ad..e8133b05e 100644 --- a/crates/op-rbuilder/src/tests/framework/txs.rs +++ b/crates/op-rbuilder/src/tests/framework/txs.rs @@ -1,5 +1,6 @@ use crate::{ primitives::bundle::{Bundle, BundleResult}, + tests::funded_signer, tx::FBPooledTransaction, tx_signer::Signer, }; @@ -21,8 +22,6 @@ use tracing::debug; use alloy_eips::eip1559::MIN_PROTOCOL_BASE_FEE; -use super::FUNDED_PRIVATE_KEYS; - #[derive(Clone, Copy, Default)] pub struct BundleOpts { block_number_min: Option, @@ -74,7 +73,6 @@ pub struct TransactionBuilder { tx: TxEip1559, bundle_opts: Option, with_reverted_hash: bool, - key: Option, } impl TransactionBuilder { @@ -91,7 +89,6 @@ impl TransactionBuilder { }, bundle_opts: None, with_reverted_hash: false, - key: None, } } @@ -105,11 +102,6 @@ impl TransactionBuilder { self } - pub fn with_key(mut self, key: u64) -> Self { - self.key = Some(key); - self - } - pub fn with_value(mut self, value: u128) -> Self { self.tx.value = U256::from(value); self @@ -166,14 +158,7 @@ impl TransactionBuilder { } pub async fn build(mut self) -> Recovered { - let signer = self.signer.unwrap_or_else(|| { - Signer::try_from_secret( - FUNDED_PRIVATE_KEYS[self.key.unwrap_or(0) as usize] - .parse() - .expect("invalid hardcoded builder private key"), - ) - .expect("Failed to create signer from hardcoded private key") - }); + let signer = self.signer.unwrap_or(funded_signer()); let nonce = match self.nonce { Some(nonce) => nonce, diff --git a/crates/op-rbuilder/src/tests/framework/utils.rs b/crates/op-rbuilder/src/tests/framework/utils.rs index a71361d2e..764b3fa31 100644 --- a/crates/op-rbuilder/src/tests/framework/utils.rs +++ b/crates/op-rbuilder/src/tests/framework/utils.rs @@ -1,10 +1,16 @@ use crate::{ - tests::{ONE_ETH, Protocol, framework::driver::ChainDriver}, + tests::{ + BUILDER_PRIVATE_KEY, Protocol, block_builder_policy::BlockBuilderPolicy, + flashblocks_number_contract::FlashblocksNumber, + flashtestation_registry::FlashtestationRegistry, framework::driver::ChainDriver, + mock_dcap_attestation::MockAutomataDcapAttestationFee, + }, tx_signer::Signer, }; use alloy_eips::Encodable2718; use alloy_primitives::{Address, B256, BlockHash, TxHash, TxKind, U256, hex}; use alloy_rpc_types_eth::{Block, BlockTransactionHashes}; +use alloy_sol_types::SolCall; use core::future::Future; use op_alloy_consensus::{OpTypedTransaction, TxDeposit}; use op_alloy_rpc_types::Transaction; @@ -17,12 +23,22 @@ use reth_node_core::{args::DatadirArgs, dirs::DataDirPath, node_config::NodeConf use reth_optimism_chainspec::OpChainSpec; use std::{net::TcpListener, sync::Arc}; -use super::{FUNDED_PRIVATE_KEYS, TransactionBuilder}; +use super::{FUNDED_PRIVATE_KEY, TransactionBuilder}; pub trait TransactionBuilderExt { fn random_valid_transfer(self) -> Self; fn random_reverting_transaction(self) -> Self; fn random_big_transaction(self) -> Self; + // flashblocks number methods + fn deploy_flashblock_number_contract(self) -> Self; + fn init_flashblock_number_contract(self, register_builder: bool) -> Self; + // flashtestations methods + fn deploy_flashtestation_registry_contract(self) -> Self; + fn init_flashtestation_registry_contract(self, dcap_address: Address) -> Self; + fn deploy_builder_policy_contract(self) -> Self; + fn init_builder_policy_contract(self, registry_address: Address) -> Self; + fn deploy_mock_dcap_contract(self) -> Self; + fn add_mock_quote(self) -> Self; } impl TransactionBuilderExt for TransactionBuilder { @@ -41,10 +57,87 @@ impl TransactionBuilderExt for TransactionBuilder { self.with_create() .with_input(hex!("6c63ffffffff60005260046000f36000526002600d60136000f5").into()) } + + fn deploy_flashblock_number_contract(self) -> Self { + self.with_create() + .with_input(FlashblocksNumber::BYTECODE.clone()) + .with_gas_limit(2_000_000) // deployment costs ~1.6 million gas + } + + fn init_flashblock_number_contract(self, register_builder: bool) -> Self { + let builder_signer = builder_signer(); + let owner = funded_signer(); + + let init_data = FlashblocksNumber::initializeCall { + _owner: owner.address, + _initialBuilders: if register_builder { + vec![builder_signer.address] + } else { + vec![] + }, + } + .abi_encode(); + + self.with_input(init_data.into()) + } + + fn deploy_flashtestation_registry_contract(self) -> Self { + self.with_create() + .with_input(FlashtestationRegistry::BYTECODE.clone()) + .with_gas_limit(1_000_000) + } + + fn init_flashtestation_registry_contract(self, dcap_address: Address) -> Self { + let owner = funded_signer(); + + let init_data = FlashtestationRegistry::initializeCall { + owner: owner.address, + _attestationContract: dcap_address, + } + .abi_encode(); + + self.with_input(init_data.into()) + } + + fn deploy_builder_policy_contract(self) -> Self { + self.with_create() + .with_input(BlockBuilderPolicy::BYTECODE.clone()) + .with_gas_limit(1_000_000) + } + + fn init_builder_policy_contract(self, registry_address: Address) -> Self { + let owner = funded_signer(); + + let init_data = BlockBuilderPolicy::initializeCall { + _initialOwner: owner.address, + _registry: registry_address, + } + .abi_encode(); + + self.with_input(init_data.into()) + } + + fn deploy_mock_dcap_contract(self) -> Self { + self.with_create() + .with_input(MockAutomataDcapAttestationFee::BYTECODE.clone()) + .with_gas_limit(1_000_000) + } + + fn add_mock_quote(self) -> Self { + let quote = MockAutomataDcapAttestationFee::setQuoteResultCall { + // quote from http://ns31695324.ip-141-94-163.eu:10080/attest for builder key + rawQuote: include_bytes!("./artifacts/test-quote.bin").into(), + _success: true, + // response from verifyAndAttestOnChain from the real automata dcap contract on + // unichain sepolia 0x95175096a9B74165BE0ac84260cc14Fc1c0EF5FF + _output: include_bytes!("./artifacts/quote-output.bin").into(), + } + .abi_encode(); + self.with_input(quote.into()).with_gas_limit(500_000) + } } pub trait ChainDriverExt { - fn fund_default_accounts(&self) -> impl Future>; fn fund_many( &self, addresses: Vec
, @@ -52,11 +145,6 @@ pub trait ChainDriverExt { ) -> impl Future>; fn fund(&self, address: Address, amount: u128) -> impl Future>; - fn first_funded_address(&self) -> Address { - FUNDED_PRIVATE_KEYS[0] - .parse() - .expect("Invalid funded private key") - } fn fund_accounts( &self, @@ -81,14 +169,6 @@ pub trait ChainDriverExt { } impl ChainDriverExt for ChainDriver

{ - async fn fund_default_accounts(&self) -> eyre::Result<()> { - for key in FUNDED_PRIVATE_KEYS { - let signer: Signer = key.parse()?; - self.fund(signer.address, ONE_ETH).await?; - } - Ok(()) - } - async fn fund_many(&self, addresses: Vec

, amount: u128) -> eyre::Result { let mut txs = Vec::with_capacity(addresses.len()); @@ -239,3 +319,21 @@ pub fn get_available_port() -> u16 { .expect("Failed to get local address") .port() } + +pub fn builder_signer() -> Signer { + Signer::try_from_secret( + BUILDER_PRIVATE_KEY + .parse() + .expect("invalid hardcoded builder private key"), + ) + .expect("Failed to create signer from hardcoded builder private key") +} + +pub fn funded_signer() -> Signer { + Signer::try_from_secret( + FUNDED_PRIVATE_KEY + .parse() + .expect("invalid hardcoded funded private key"), + ) + .expect("Failed to create signer from hardcoded funded private key") +}