Skip to content

Commit 2d6f9d1

Browse files
feat: parse protocol param event
1 parent 039d514 commit 2d6f9d1

4 files changed

Lines changed: 122 additions & 1 deletion

File tree

crates/evm/src/block/error.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ pub enum BlockValidationError {
8080
/// [EIP-6110]: https://eips.ethereum.org/EIPS/eip-6110
8181
#[error("failed to decode deposit requests from receipts: {_0}")]
8282
DepositRequestDecode(String),
83+
/// Error when decoding protocol param requests from receipts
84+
///
85+
#[error("failed to decode protocol param requests from receipts: {_0}")]
86+
ProtocolParamRequestDecode(String),
8387
}
8488

8589
/// `BlockExecutor` Errors

crates/evm/src/eth/block.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Ethereum block executor.
22
33
use super::{
4-
dao_fork, eip6110,
4+
dao_fork, eip6110, protocol_params,
55
receipt_builder::{AlloyReceiptBuilder, ReceiptBuilder, ReceiptBuilderCtx},
66
spec::{EthExecutorSpec, EthSpec},
77
EthEvmFactory,
@@ -165,12 +165,19 @@ where
165165
let deposit_requests =
166166
eip6110::parse_deposits_from_receipts(&self.spec, &self.receipts)?;
167167

168+
// Collect all protocol param requests
169+
let protocol_param_requests = protocol_params::parse_protocol_params_from_receipts(&self.receipts)?;
170+
168171
let mut requests = Requests::default();
169172

170173
if !deposit_requests.is_empty() {
171174
requests.push_request_with_type(eip6110::DEPOSIT_REQUEST_TYPE, deposit_requests);
172175
}
173176

177+
if !protocol_param_requests.is_empty() {
178+
requests.push_request_with_type(protocol_params::PROTOCOL_PARAM_REQUEST_TYPE, protocol_param_requests);
179+
}
180+
174181
requests.extend(self.system_caller.apply_post_execution_changes(&mut self.evm)?);
175182
requests
176183
} else {

crates/evm/src/eth/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ pub mod dao_fork;
2424
pub mod eip6110;
2525
pub mod receipt_builder;
2626
pub mod spec;
27+
pub mod protocol_params;
2728

2829
/// The Ethereum EVM context type.
2930
pub type EthEvmContext<DB> = Context<BlockEnv, TxEnv, CfgEnv, DB>;
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
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

Comments
 (0)