Skip to content
This repository has been archived by the owner on Oct 11, 2024. It is now read-only.

Commit

Permalink
fix: Optimism execution (bluealloy#789)
Browse files Browse the repository at this point in the history
* use l2 base fee

* use optimism handler when activated

* fix panic for eth execution with optimism flag

* use is_none

* address review comments
  • Loading branch information
Wollac authored and clabby committed Oct 15, 2023
1 parent 23cbac4 commit 173f28f
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 56 deletions.
44 changes: 21 additions & 23 deletions crates/revm/src/evm_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,34 +194,23 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact<DB::Error>
let tx_data = env.tx.data.clone();
let tx_gas_limit = env.tx.gas_limit;

// the L1-cost fee is only computed for Optimism non-deposit transactions.
#[cfg(feature = "optimism")]
let tx_l1_cost = {
let is_deposit = env.tx.optimism.source_hash.is_some();

let tx_l1_cost = if env.cfg.optimism && env.tx.optimism.source_hash.is_none() {
let l1_block_info =
optimism::L1BlockInfo::try_fetch(self.data.db, self.data.env.cfg.optimism)
.map_err(EVMError::Database)?;

// Perform this calculation optimistically to avoid cloning the enveloped tx.
let tx_l1_cost = l1_block_info.as_ref().map(|l1_block_info| {
env.tx
.optimism
.enveloped_tx
.as_ref()
.map(|enveloped_tx| {
l1_block_info.calculate_tx_l1_cost::<GSPEC>(enveloped_tx, is_deposit)
})
.unwrap_or(U256::ZERO)
});
// storage l1 block info for later use.
self.data.l1_block_info = l1_block_info;
optimism::L1BlockInfo::try_fetch(self.data.db).map_err(EVMError::Database)?;

//
let Some(tx_l1_cost) = tx_l1_cost else {
panic!("[OPTIMISM] L1 Block Info could not be loaded from the DB.")
let Some(enveloped_tx) = &env.tx.optimism.enveloped_tx else {
panic!("[OPTIMISM] Failed to load enveloped transaction.");
};
let tx_l1_cost = l1_block_info.calculate_tx_l1_cost::<GSPEC>(enveloped_tx);

// storage l1 block info for later use.
self.data.l1_block_info = Some(l1_block_info);

tx_l1_cost
} else {
U256::ZERO
};

let initial_gas_spend = initial_tx_gas::<GSPEC>(
Expand Down Expand Up @@ -402,6 +391,15 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB,
precompiles: Precompiles,
) -> Self {
let journaled_state = JournaledState::new(precompiles.len(), GSPEC::SPEC_ID);
#[cfg(feature = "optimism")]
let handler = if env.cfg.optimism {
Handler::optimism::<GSPEC>()
} else {
Handler::mainnet::<GSPEC>()
};
#[cfg(not(feature = "optimism"))]
let handler = Handler::mainnet::<GSPEC>();

Self {
data: EVMData {
env,
Expand All @@ -413,7 +411,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB,
l1_block_info: None,
},
inspector,
handler: Handler::mainnet::<GSPEC>(),
handler,
_phantomdata: PhantomData {},
}
}
Expand Down
9 changes: 6 additions & 3 deletions crates/revm/src/handler/optimism.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ pub fn reward_beneficiary<SPEC: Spec, DB: Database>(
panic!("[OPTIMISM] Failed to load enveloped transaction.");
};

let l1_cost = l1_block_info.calculate_tx_l1_cost::<SPEC>(enveloped_tx, is_deposit);
let l1_cost = l1_block_info.calculate_tx_l1_cost::<SPEC>(enveloped_tx);

// Send the L1 cost of the transaction to the L1 Fee Vault.
let Ok((l1_fee_vault_account, _)) = data
Expand All @@ -132,8 +132,11 @@ pub fn reward_beneficiary<SPEC: Spec, DB: Database>(
panic!("[OPTIMISM] Failed to load Base Fee Vault account");
};
base_fee_vault_account.mark_touch();
base_fee_vault_account.info.balance +=
l1_block_info.l1_base_fee.mul(U256::from(gas.spend()));
base_fee_vault_account.info.balance += data
.env
.block
.basefee
.mul(U256::from(gas.spend() - gas_refund));
}
Ok(())
}
Expand Down
54 changes: 24 additions & 30 deletions crates/revm/src/optimism.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,17 @@ pub struct L1BlockInfo {
}

impl L1BlockInfo {
pub fn try_fetch<DB: Database>(
db: &mut DB,
is_optimism: bool,
) -> Result<Option<L1BlockInfo>, DB::Error> {
is_optimism
.then(|| {
let l1_base_fee = db.storage(L1_BLOCK_CONTRACT, L1_BASE_FEE_SLOT)?;
let l1_fee_overhead = db.storage(L1_BLOCK_CONTRACT, L1_OVERHEAD_SLOT)?;
let l1_fee_scalar = db.storage(L1_BLOCK_CONTRACT, L1_SCALAR_SLOT)?;

Ok(L1BlockInfo {
l1_base_fee,
l1_fee_overhead,
l1_fee_scalar,
})
})
.map_or(Ok(None), |v| v.map(Some))
/// Try to fetch the L1 block info from the database.
pub fn try_fetch<DB: Database>(db: &mut DB) -> Result<L1BlockInfo, DB::Error> {
let l1_base_fee = db.storage(L1_BLOCK_CONTRACT, L1_BASE_FEE_SLOT)?;
let l1_fee_overhead = db.storage(L1_BLOCK_CONTRACT, L1_OVERHEAD_SLOT)?;
let l1_fee_scalar = db.storage(L1_BLOCK_CONTRACT, L1_SCALAR_SLOT)?;

Ok(L1BlockInfo {
l1_base_fee,
l1_fee_overhead,
l1_fee_scalar,
})
}

/// Calculate the data gas for posting the transaction on L1. Calldata costs 16 gas per non-zero
Expand All @@ -83,19 +77,18 @@ impl L1BlockInfo {
}

/// Calculate the gas cost of a transaction based on L1 block data posted on L2
pub fn calculate_tx_l1_cost<SPEC: Spec>(&self, input: &Bytes, is_deposit: bool) -> U256 {
let rollup_data_gas_cost = self.data_gas::<SPEC>(input);

if is_deposit || rollup_data_gas_cost == U256::ZERO {
pub fn calculate_tx_l1_cost<SPEC: Spec>(&self, input: &Bytes) -> U256 {
// If the input is not a deposit transaction, the default value is zero.
if input.is_empty() || input.first() == Some(&0x7F) {
return U256::ZERO;
}

let rollup_data_gas_cost = self.data_gas::<SPEC>(input);
rollup_data_gas_cost
.saturating_add(self.l1_fee_overhead)
.saturating_mul(self.l1_base_fee)
.saturating_mul(self.l1_fee_scalar)
.checked_div(U256::from(1_000_000))
.unwrap_or_default()
/ U256::from(1_000_000)
}
}

Expand Down Expand Up @@ -160,17 +153,18 @@ mod tests {
l1_fee_scalar: U256::from(1_000),
};

// The gas cost here should be zero since the tx is a deposit
let input = bytes!("FACADE");
let gas_cost = l1_block_info.calculate_tx_l1_cost::<BedrockSpec>(&input, true);
assert_eq!(gas_cost, U256::ZERO);

let gas_cost = l1_block_info.calculate_tx_l1_cost::<RegolithSpec>(&input, false);
let gas_cost = l1_block_info.calculate_tx_l1_cost::<RegolithSpec>(&input);
assert_eq!(gas_cost, U256::from(1048));

// Zero rollup data gas cost should result in zero for non-deposits
// Zero rollup data gas cost should result in zero
let input = bytes!("");
let gas_cost = l1_block_info.calculate_tx_l1_cost::<RegolithSpec>(&input, false);
let gas_cost = l1_block_info.calculate_tx_l1_cost::<RegolithSpec>(&input);
assert_eq!(gas_cost, U256::ZERO);

// Deposit transactions with the EIP-2718 type of 0x7F should result in zero
let input = bytes!("7FFACADE");
let gas_cost = l1_block_info.calculate_tx_l1_cost::<RegolithSpec>(&input);
assert_eq!(gas_cost, U256::ZERO);
}
}

0 comments on commit 173f28f

Please sign in to comment.