diff --git a/src/eip1967.rs b/src/eip1967.rs index b0ec0fb..75ad4f3 100644 --- a/src/eip1967.rs +++ b/src/eip1967.rs @@ -1,10 +1,14 @@ use alloy::{ network::{Network, TransactionBuilder}, - primitives::{b256, bytes, Address, Bytes, B256, U256}, + primitives::{b256, bytes, Address, Bytes, B256}, providers::Provider, }; -use crate::{error::DetectProxyResult, ProxyType}; +use crate::{ + error::DetectProxyResult, + utils::{storage_slot_as_address, u256_to_address}, + ProxyType, +}; // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1) const EIP1967_LOGIC_SLOT: B256 = @@ -69,28 +73,3 @@ where Ok(None) } - -async fn storage_slot_as_address>( - provider: P, - address: Address, - slot: B256, -) -> DetectProxyResult> -where - N: Network, -{ - let slot = provider - .get_storage_at(address, slot.into()) - .latest() - .await?; - - if !slot.is_zero() { - return Ok(Some(u256_to_address(slot))); - } - - Ok(None) -} - -fn u256_to_address(u256: U256) -> Address { - let bytes: Bytes = u256.to_be_bytes::<32>().into(); - Address::from_slice(&bytes[12..]) -} diff --git a/src/lib.rs b/src/lib.rs index b1379c3..fb3c0ae 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,8 @@ mod eip1167; mod eip1967; mod error; +mod openzeppelin; +mod utils; use alloy::{network::Network, primitives::Address, providers::Provider}; use error::DetectProxyResult; @@ -34,7 +36,9 @@ where return Ok(Some(proxy_type)); } - //if let Some(proxy_type) = eip1967::detect_open(address, provider).await? { + if let Some(address) = openzeppelin::detect_open_zeppelin_proxy(address, provider).await? { + return Ok(Some(ProxyType::OpenZeppelin(address))); + } Ok(None) } @@ -60,6 +64,7 @@ mod tests { #[case::eip1967_direct(address!("0x8260b9eC6d472a34AD081297794d7Cc00181360a"), ProxyType::Eip1967Direct(address!("0xe4e4003afe3765aca8149a82fc064c0b125b9e5a")))] #[case::eip1967_beacon(address!("0xDd4e2eb37268B047f55fC5cAf22837F9EC08A881"), ProxyType::Eip1967Beacon(address!("0xe5c048792dcf2e4a56000c8b6a47f21df22752d1")))] #[case::eip1967_beacon(address!("0x114f1388fAB456c4bA31B1850b244Eedcd024136"), ProxyType::Eip1967Beacon(address!("0x0fa0fd98727c443dd5275774c44d27cff9d279ed")))] + #[case::openzeppelin(address!("0xC986c2d326c84752aF4cC842E033B9ae5D54ebbB"), ProxyType::OpenZeppelin(address!("0x0656368c4934e56071056da375d4a691d22161f8")))] #[tokio::test] async fn mainnet(#[case] proxy: Address, #[case] impl_: ProxyType) { let provider = ProviderBuilder::new().on_http(MAINNET_RPC.clone()); diff --git a/src/openzeppelin.rs b/src/openzeppelin.rs new file mode 100644 index 0000000..33a83fc --- /dev/null +++ b/src/openzeppelin.rs @@ -0,0 +1,25 @@ +use alloy::{ + network::Network, + primitives::{b256, Address, B256}, + providers::Provider, +}; + +use crate::{error::DetectProxyResult, utils::storage_slot_as_address}; + +const OPEN_ZEPPELIN_PREFIX: B256 = + b256!("0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3"); + +pub(crate) async fn detect_open_zeppelin_proxy>( + address: Address, + provider: P, +) -> DetectProxyResult> +where + N: Network, +{ + if let Ok(Some(addr)) = storage_slot_as_address(&provider, address, OPEN_ZEPPELIN_PREFIX).await + { + return Ok(Some(addr)); + } + + Ok(None) +} diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..c9e90ee --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,32 @@ +use alloy::{ + network::Network, + primitives::{Address, Bytes, B256, U256}, + providers::Provider, +}; + +use crate::error::DetectProxyResult; + +pub(crate) async fn storage_slot_as_address>( + provider: P, + address: Address, + slot: B256, +) -> DetectProxyResult> +where + N: Network, +{ + let slot = provider + .get_storage_at(address, slot.into()) + .latest() + .await?; + + if !slot.is_zero() { + return Ok(Some(u256_to_address(slot))); + } + + Ok(None) +} + +pub(crate) fn u256_to_address(u256: U256) -> Address { + let bytes: Bytes = u256.to_be_bytes::<32>().into(); + Address::from_slice(&bytes[12..]) +}