Skip to content

Commit eb9c753

Browse files
committed
feat(host-rpc): add RpcAliasOracle and RpcAliasOracleFactory
1 parent f4d7204 commit eb9c753

2 files changed

Lines changed: 64 additions & 0 deletions

File tree

crates/host-rpc/src/alias.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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+
}

crates/host-rpc/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,6 @@ pub use notifier::RpcHostNotifier;
3131
mod segment;
3232
pub use segment::{RpcBlock, RpcChainSegment};
3333
mod metrics;
34+
35+
mod alias;
36+
pub use alias::{RpcAliasOracle, RpcAliasOracleFactory};

0 commit comments

Comments
 (0)