From ba663fe936a4815283af661c86c176bc7c5170a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?pablito=20=E3=83=86?= Date: Mon, 23 Dec 2024 06:50:18 -0300 Subject: [PATCH] Add RemovedPrecompilesAt util for filtering removed precompiles (#1551) * feat(precompile-utils): implement helper methods * add RemovedPrecompilesAt for filtering a list of removed precompiles * impl is_empty() for BoundedVec * appease clippy * appease clippy x2 --------- Co-authored-by: Rodrigo Quelhas --- precompiles/src/precompile_set.rs | 63 ++++++++++++++++++++++++ precompiles/src/solidity/codec/bytes.rs | 16 +++++- precompiles/src/solidity/codec/native.rs | 19 +++++++ 3 files changed, 97 insertions(+), 1 deletion(-) diff --git a/precompiles/src/precompile_set.rs b/precompiles/src/precompile_set.rs index 288a906197..6f54214bfb 100644 --- a/precompiles/src/precompile_set.rs +++ b/precompiles/src/precompile_set.rs @@ -129,6 +129,7 @@ impl From> for IsPrecompileResult { pub enum PrecompileKind { Single(H160), Prefixed(Vec), + Multiple(Vec), } #[derive(Debug, Clone)] @@ -833,6 +834,68 @@ impl IsActivePrecompile for RevertPrecompile { } } +/// Precompiles that were removed from a precompile set. +/// Still considered precompiles but are inactive and always revert. +pub struct RemovedPrecompilesAt(PhantomData); +impl PrecompileSetFragment for RemovedPrecompilesAt +where + A: Get>, +{ + #[inline(always)] + fn new() -> Self { + Self(PhantomData) + } + + #[inline(always)] + fn execute( + &self, + handle: &mut impl PrecompileHandle, + ) -> Option { + if A::get().contains(&handle.code_address()) { + Some(Err(revert("Removed precompile"))) + } else { + None + } + } + + #[inline(always)] + fn is_precompile(&self, address: H160, _gas: u64) -> IsPrecompileResult { + IsPrecompileResult::Answer { + is_precompile: A::get().contains(&address), + extra_cost: 0, + } + } + + #[inline(always)] + fn used_addresses(&self) -> Vec { + A::get() + } + + fn summarize_checks(&self) -> Vec { + vec![PrecompileCheckSummary { + name: None, + precompile_kind: PrecompileKind::Multiple(A::get()), + recursion_limit: Some(0), + accept_delegate_call: true, + callable_by_smart_contract: "Reverts in all cases".into(), + callable_by_precompile: "Reverts in all cases".into(), + }] + } +} + +impl IsActivePrecompile for RemovedPrecompilesAt +where + Self: PrecompileSetFragment, +{ + #[inline(always)] + fn is_active_precompile(&self, _address: H160, _gas: u64) -> IsPrecompileResult { + IsPrecompileResult::Answer { + is_precompile: false, + extra_cost: 0, + } + } +} + /// A precompile that was removed from a precompile set. /// Still considered a precompile but is inactive and always revert. pub struct RemovedPrecompileAt(PhantomData); diff --git a/precompiles/src/solidity/codec/bytes.rs b/precompiles/src/solidity/codec/bytes.rs index d237a3b8b8..26566dea00 100644 --- a/precompiles/src/solidity/codec/bytes.rs +++ b/precompiles/src/solidity/codec/bytes.rs @@ -53,7 +53,7 @@ impl Kind for StringKind { /// The `bytes/string` type of Solidity. /// It is different from `Vec` which will be serialized with padding for each `u8` element /// of the array, while `Bytes` is tightly packed. -#[derive(Debug, Eq, PartialEq)] +#[derive(Debug)] pub struct BoundedBytesString { data: Vec, _phantom: PhantomData<(K, S)>, @@ -68,6 +68,20 @@ impl> Clone for BoundedBytesString { } } +impl PartialEq> for BoundedBytesString { + fn eq(&self, other: &BoundedBytesString) -> bool { + self.data.eq(&other.data) + } +} + +impl Eq for BoundedBytesString {} + +impl Default for BoundedBytesString { + fn default() -> Self { + Vec::default().into() + } +} + impl> BoundedBytesString { pub fn as_bytes(&self) -> &[u8] { &self.data diff --git a/precompiles/src/solidity/codec/native.rs b/precompiles/src/solidity/codec/native.rs index c83eed4d46..993ea4d030 100644 --- a/precompiles/src/solidity/codec/native.rs +++ b/precompiles/src/solidity/codec/native.rs @@ -380,3 +380,22 @@ impl From> for Vec { value.inner } } + +impl Default for BoundedVec { + fn default() -> Self { + Self { + inner: Default::default(), + _phantom: PhantomData, + } + } +} + +impl BoundedVec { + pub fn len(&self) -> usize { + self.inner.len() + } + + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } +}