use alloy_evm::InvalidTxError;
use revm::state::AccountInfo;
use crate::MegaTransactionOutcome;
#[derive(Debug, Clone, derive_more::Deref, derive_more::DerefMut)]
pub struct BlockMegaTransactionOutcome<T> {
pub tx: T,
pub tx_size: u64,
pub da_size: u64,
pub depositor: Option<AccountInfo>,
#[deref]
#[deref_mut]
pub inner: MegaTransactionOutcome,
}
#[derive(Debug, Clone, thiserror::Error)]
pub enum MegaTxLimitExceededError {
#[error("Transaction gas limit exceeded: tx_gas_limit={tx_gas_limit} > limit={limit}")]
TransactionGasLimit {
tx_gas_limit: u64,
limit: u64,
},
#[error("Transaction encode size limit exceeded: tx_size={tx_size} > limit={limit}")]
TransactionEncodeSizeLimit {
tx_size: u64,
limit: u64,
},
#[error(
"Transaction data availability size limit exceeded: da_size={da_size} > limit={limit}"
)]
DataAvailabilitySizeLimit {
da_size: u64,
limit: u64,
},
}
impl MegaTxLimitExceededError {
pub fn usage(&self) -> u64 {
match self {
Self::TransactionGasLimit { tx_gas_limit, .. } => *tx_gas_limit,
Self::TransactionEncodeSizeLimit { tx_size, .. } => *tx_size,
Self::DataAvailabilitySizeLimit { da_size, .. } => *da_size,
}
}
pub fn limit(&self) -> u64 {
match self {
Self::TransactionGasLimit { limit, .. } |
Self::TransactionEncodeSizeLimit { limit, .. } |
Self::DataAvailabilitySizeLimit { limit, .. } => *limit,
}
}
}
impl InvalidTxError for MegaTxLimitExceededError {
fn is_nonce_too_low(&self) -> bool {
false
}
}
#[derive(Debug, Clone, thiserror::Error)]
pub enum MegaBlockLimitExceededError {
#[error("Block transactions data limit reached: block_used={block_used} >= limit={limit}")]
TransactionDataLimit {
block_used: u64,
limit: u64,
},
#[error("Block KV update limit reached: block_used={block_used} >= limit={limit}")]
KVUpdateLimit {
block_used: u64,
limit: u64,
},
#[error("Block compute gas limit reached: block_used={block_used} >= limit={limit}")]
ComputeGasLimit {
block_used: u64,
limit: u64,
},
#[error("Block transactions encode size limit exceeded: block_used={block_used} + tx_used={tx_used} > limit={limit}")]
TransactionEncodeSizeLimit {
block_used: u64,
tx_used: u64,
limit: u64,
},
#[error("Block data availability size limit exceeded: block_used={block_used} + tx_used={tx_used} > limit={limit}")]
DataAvailabilitySizeLimit {
block_used: u64,
tx_used: u64,
limit: u64,
},
#[error("Block state growth limit reached: block_used={block_used} >= limit={limit}")]
StateGrowthLimit {
block_used: u64,
limit: u64,
},
}
impl MegaBlockLimitExceededError {
pub fn block_used(&self) -> u64 {
match self {
Self::TransactionDataLimit { block_used, .. } |
Self::KVUpdateLimit { block_used, .. } |
Self::ComputeGasLimit { block_used, .. } |
Self::TransactionEncodeSizeLimit { block_used, .. } |
Self::DataAvailabilitySizeLimit { block_used, .. } |
Self::StateGrowthLimit { block_used, .. } => *block_used,
}
}
pub fn limit(&self) -> u64 {
match self {
Self::TransactionDataLimit { limit, .. } |
Self::KVUpdateLimit { limit, .. } |
Self::ComputeGasLimit { limit, .. } |
Self::TransactionEncodeSizeLimit { limit, .. } |
Self::DataAvailabilitySizeLimit { limit, .. } |
Self::StateGrowthLimit { limit, .. } => *limit,
}
}
}
impl InvalidTxError for MegaBlockLimitExceededError {
fn is_nonce_too_low(&self) -> bool {
false
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_transaction_limit_error_reports_usage_and_limit() {
let cases = [
(MegaTxLimitExceededError::TransactionGasLimit { tx_gas_limit: 31, limit: 30 }, 31, 30),
(
MegaTxLimitExceededError::TransactionEncodeSizeLimit { tx_size: 101, limit: 100 },
101,
100,
),
(
MegaTxLimitExceededError::DataAvailabilitySizeLimit { da_size: 11, limit: 10 },
11,
10,
),
];
for (error, expected_usage, expected_limit) in cases {
assert_eq!(error.usage(), expected_usage);
assert_eq!(error.limit(), expected_limit);
assert!(!error.is_nonce_too_low());
}
}
#[test]
fn test_block_limit_error_reports_block_usage_and_limit() {
let cases = [
(MegaBlockLimitExceededError::TransactionDataLimit { block_used: 1, limit: 10 }, 1, 10),
(MegaBlockLimitExceededError::KVUpdateLimit { block_used: 2, limit: 11 }, 2, 11),
(MegaBlockLimitExceededError::ComputeGasLimit { block_used: 3, limit: 12 }, 3, 12),
(
MegaBlockLimitExceededError::TransactionEncodeSizeLimit {
block_used: 4,
tx_used: 1,
limit: 13,
},
4,
13,
),
(
MegaBlockLimitExceededError::DataAvailabilitySizeLimit {
block_used: 5,
tx_used: 1,
limit: 14,
},
5,
14,
),
(MegaBlockLimitExceededError::StateGrowthLimit { block_used: 6, limit: 15 }, 6, 15),
];
for (error, expected_block_used, expected_limit) in cases {
assert_eq!(error.block_used(), expected_block_used);
assert_eq!(error.limit(), expected_limit);
assert!(!error.is_nonce_too_low());
}
}
}