|
| 1 | +//! Seismic protocol param requests parsing |
| 2 | +use crate::block::BlockValidationError; |
| 3 | +use alloc::{string::ToString, vec::Vec}; |
| 4 | +use alloy_consensus::TxReceipt; |
| 5 | +use alloy_primitives::{Address, address, Bytes, Log}; |
| 6 | +use alloy_sol_types::{sol, SolEvent}; |
| 7 | + |
| 8 | + |
| 9 | +/// Protocol parameters contract address for Seismic chains. |
| 10 | +/// |
| 11 | +/// This contract is deployed at genesis and stores network-wide protocol |
| 12 | +/// parameters that can be updated through governance or predefined schedules. |
| 13 | +/// |
| 14 | +/// The same address is used across all Seismic networks (mainnet, dev, testnet). |
| 15 | +/// Address ends with "Params" in hex: 0x506172616D73 |
| 16 | +pub const SEISMIC_PROTOCOL_PARAMS_CONTRACT: Address = |
| 17 | + address!("0000000000000000000000000000506172616D73"); |
| 18 | + |
| 19 | +/// The [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685) request type for protocol param requests. |
| 20 | +pub const PROTOCOL_PARAM_REQUEST_TYPE: u8 = 0xFF; |
| 21 | + |
| 22 | +const PROTOCOL_PARAM_MAX_BYTES_SIZE: usize = 1 + 100; |
| 23 | + |
| 24 | +sol! { |
| 25 | + #[allow(missing_docs)] |
| 26 | + event ProtocolParamEvent( |
| 27 | + uint8 param_id, |
| 28 | + bytes param |
| 29 | + ); |
| 30 | +} |
| 31 | + |
| 32 | +/// Accumulate a protocol param request from a log. containing a [`ParamEvent`]. |
| 33 | +pub fn accumulate_protocol_param_from_log(log: &Log<ProtocolParamEvent>, out: &mut Vec<u8>) { |
| 34 | + //out.reserve(PROTOCOL_PARAM_MAX_BYTES_SIZE); |
| 35 | + out.extend_from_slice(&[log.param_id]); |
| 36 | + out.extend_from_slice(log.param.as_ref()); |
| 37 | +} |
| 38 | + |
| 39 | +/// Accumulate protocol params from an iterator of logs. |
| 40 | +pub fn accumulate_protocol_params_from_logs<'a>( |
| 41 | + address: Address, |
| 42 | + logs: impl IntoIterator<Item = &'a Log>, |
| 43 | + out: &mut Vec<u8>, |
| 44 | +) -> Result<(), BlockValidationError> { |
| 45 | + logs.into_iter() |
| 46 | + // filter logs by address |
| 47 | + .filter(|log| log.address == address) |
| 48 | + // explicitly filter logs by the ParamEvent's signature hash (first topic) |
| 49 | + .filter(|log| { |
| 50 | + // 0x649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5 |
| 51 | + log.topics().first() == Some(&ProtocolParamEvent::SIGNATURE_HASH) |
| 52 | + }) |
| 53 | + .try_for_each(|log| { |
| 54 | + // We assume that the log is valid because it was emitted by the |
| 55 | + // protocol params contract. |
| 56 | + let decoded_log = |
| 57 | + ProtocolParamEvent::decode_log(log).map_err(|err: alloy_sol_types::Error| { |
| 58 | + BlockValidationError::ProtocolParamRequestDecode(err.to_string()) |
| 59 | + })?; |
| 60 | + accumulate_protocol_param_from_log(&decoded_log, out); |
| 61 | + Ok(()) |
| 62 | + }) |
| 63 | +} |
| 64 | + |
| 65 | +/// Accumulate protocol params from a receipt. Iterates over the logs in the receipt |
| 66 | +/// and accumulates the protocol param request bytestrings. |
| 67 | +pub fn accumulate_protocol_params_from_receipt( |
| 68 | + address: Address, |
| 69 | + receipt: impl TxReceipt<Log = Log>, |
| 70 | + out: &mut Vec<u8>, |
| 71 | +) -> Result<(), BlockValidationError> { |
| 72 | + accumulate_protocol_params_from_logs(address, receipt.logs(), out) |
| 73 | +} |
| 74 | + |
| 75 | +/// Accumulate protocol params from a list of receipts. Iterates over the logs in the |
| 76 | +/// receipts and accumulates the param request bytestrings. |
| 77 | +pub fn accumulate_protocol_params_from_receipts<'a, I, R>( |
| 78 | + address: Address, |
| 79 | + receipts: I, |
| 80 | + out: &mut Vec<u8>, |
| 81 | +) -> Result<(), BlockValidationError> |
| 82 | +where |
| 83 | + I: IntoIterator<Item = &'a R>, |
| 84 | + R: TxReceipt<Log = Log> + 'a, |
| 85 | +{ |
| 86 | + receipts |
| 87 | + .into_iter() |
| 88 | + .try_for_each(|receipt| accumulate_protocol_params_from_receipt(address, receipt, out)) |
| 89 | +} |
| 90 | + |
| 91 | +/// Find protocol param logs in a list of receipts, and return the concatenated |
| 92 | +/// param request bytestring. |
| 93 | +/// |
| 94 | +/// The address of the protocol params contract is taken from the chain spec. |
| 95 | +pub fn parse_protocol_params_from_receipts<'a, I, R>( |
| 96 | + receipts: I, |
| 97 | +) -> Result<Bytes, BlockValidationError> |
| 98 | +where |
| 99 | + I: IntoIterator<Item = &'a R>, |
| 100 | + R: TxReceipt<Log = Log> + 'a, |
| 101 | +{ |
| 102 | + let mut out = Vec::new(); |
| 103 | + accumulate_protocol_params_from_receipts( |
| 104 | + SEISMIC_PROTOCOL_PARAMS_CONTRACT, |
| 105 | + receipts, |
| 106 | + &mut out, |
| 107 | + )?; |
| 108 | + Ok(out.into()) |
| 109 | +} |
0 commit comments