|
| 1 | +use alloy::{ |
| 2 | + eips::eip7702::constants::EIP7702_DELEGATION_DESIGNATOR, primitives::Address, |
| 3 | + providers::Provider, |
| 4 | +}; |
| 5 | +use signet_block_processor::{AliasOracle, AliasOracleFactory}; |
| 6 | + |
| 7 | +/// An [`AliasOracle`] backed by an alloy RPC [`Provider`]. |
| 8 | +/// |
| 9 | +/// Checks whether an address has non-delegation bytecode by fetching the |
| 10 | +/// code at the address via `eth_getCode`. Addresses with no code or with |
| 11 | +/// EIP-7702 delegation code are not aliased; addresses with any other |
| 12 | +/// bytecode are. |
| 13 | +#[derive(Debug, Clone)] |
| 14 | +pub struct RpcAliasOracle<P> { |
| 15 | + provider: P, |
| 16 | +} |
| 17 | + |
| 18 | +impl<P: Provider + Clone + 'static> AliasOracle for RpcAliasOracle<P> { |
| 19 | + async fn should_alias(&self, address: Address) -> eyre::Result<bool> { |
| 20 | + let code = self.provider.get_code_at(address).await?; |
| 21 | + // No code — not a contract. |
| 22 | + if code.is_empty() { |
| 23 | + return Ok(false); |
| 24 | + } |
| 25 | + // EIP-7702 delegation — do not alias. |
| 26 | + if code.starts_with(&EIP7702_DELEGATION_DESIGNATOR) { |
| 27 | + return Ok(false); |
| 28 | + } |
| 29 | + // Non-delegation contract — alias it. |
| 30 | + Ok(true) |
| 31 | + } |
| 32 | +} |
| 33 | + |
| 34 | +/// An [`AliasOracleFactory`] backed by an alloy RPC [`Provider`]. |
| 35 | +/// |
| 36 | +/// Creates [`RpcAliasOracle`] instances that query the host chain at |
| 37 | +/// `latest`. This is safe because alias status is stable across blocks: |
| 38 | +/// an EOA cannot become a non-delegation contract without a birthday |
| 39 | +/// attack (c.f. EIP-3607), and EIP-7702 delegations are excluded by the |
| 40 | +/// delegation designator check. Even in the (computationally infeasible |
| 41 | +/// ~2^80) birthday attack scenario, the result is a benign |
| 42 | +/// false-positive (over-aliasing), never a dangerous false-negative. |
| 43 | +#[derive(Debug, Clone)] |
| 44 | +pub struct RpcAliasOracleFactory<P> { |
| 45 | + provider: P, |
| 46 | +} |
| 47 | + |
| 48 | +impl<P> RpcAliasOracleFactory<P> { |
| 49 | + /// Create a new [`RpcAliasOracleFactory`] from an alloy provider. |
| 50 | + pub const fn new(provider: P) -> Self { |
| 51 | + Self { provider } |
| 52 | + } |
| 53 | +} |
| 54 | + |
| 55 | +impl<P: Provider + Clone + 'static> AliasOracleFactory for RpcAliasOracleFactory<P> { |
| 56 | + type Oracle = RpcAliasOracle<P>; |
| 57 | + |
| 58 | + fn create(&self) -> eyre::Result<Self::Oracle> { |
| 59 | + Ok(RpcAliasOracle { provider: self.provider.clone() }) |
| 60 | + } |
| 61 | +} |
0 commit comments