use alloy_primitives::hex;
use alloy_sol_types::{ContractError, GenericRevertReason};
use revm::{
interpreter::{opcode, OpCode},
primitives::SpecId,
};
#[inline]
pub(crate) fn convert_memory(data: &[u8]) -> Vec<String> {
let mut memory = Vec::with_capacity((data.len() + 31) / 32);
for idx in (0..data.len()).step_by(32) {
let len = std::cmp::min(idx + 32, data.len());
memory.push(hex::encode(&data[idx..len]));
}
memory
}
#[inline]
pub(crate) fn gas_used(spec: SpecId, spent: u64, refunded: u64) -> u64 {
let refund_quotient = if SpecId::enabled(spec, SpecId::LONDON) { 5 } else { 2 };
spent - (refunded).min(spent / refund_quotient)
}
#[inline]
pub(crate) fn maybe_revert_reason(output: &[u8]) -> Option<String> {
let reason = match GenericRevertReason::decode(output)? {
GenericRevertReason::ContractError(err) => {
match err {
ContractError::Revert(revert) => revert.reason,
err => err.to_string(),
}
}
GenericRevertReason::RawString(err) => err,
};
if reason.is_empty() {
None
} else {
Some(reason)
}
}
pub(crate) const fn stack_push_count(step_op: OpCode) -> usize {
let step_op = step_op.get();
match step_op {
opcode::PUSH0..=opcode::PUSH32 => 1,
opcode::SWAP1..=opcode::SWAP16 => (step_op - opcode::SWAP1) as usize + 2,
opcode::DUP1..=opcode::DUP16 => (step_op - opcode::DUP1) as usize + 2,
opcode::CALLDATALOAD
| opcode::SLOAD
| opcode::MLOAD
| opcode::CALLDATASIZE
| opcode::LT
| opcode::GT
| opcode::DIV
| opcode::SDIV
| opcode::SAR
| opcode::AND
| opcode::EQ
| opcode::CALLVALUE
| opcode::ISZERO
| opcode::ADD
| opcode::EXP
| opcode::CALLER
| opcode::KECCAK256
| opcode::SUB
| opcode::ADDRESS
| opcode::GAS
| opcode::MUL
| opcode::RETURNDATASIZE
| opcode::NOT
| opcode::SHR
| opcode::SHL
| opcode::EXTCODESIZE
| opcode::SLT
| opcode::OR
| opcode::NUMBER
| opcode::PC
| opcode::TIMESTAMP
| opcode::BALANCE
| opcode::SELFBALANCE
| opcode::MULMOD
| opcode::ADDMOD
| opcode::BASEFEE
| opcode::BLOCKHASH
| opcode::BYTE
| opcode::XOR
| opcode::ORIGIN
| opcode::CODESIZE
| opcode::MOD
| opcode::SIGNEXTEND
| opcode::GASLIMIT
| opcode::DIFFICULTY
| opcode::SGT
| opcode::GASPRICE
| opcode::MSIZE
| opcode::EXTCODEHASH
| opcode::SMOD
| opcode::CHAINID
| opcode::COINBASE => 1,
_ => 0,
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum TraceStyle {
Parity,
#[allow(dead_code)]
Geth,
}
impl TraceStyle {
pub(crate) const fn is_parity(self) -> bool {
matches!(self, Self::Parity)
}
}