Skip to content

Commit

Permalink
Add RemovedPrecompilesAt util for filtering removed precompiles (#1551)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
pLabarta and RomarQ authored Dec 23, 2024
1 parent ac6b6d0 commit ba663fe
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 1 deletion.
63 changes: 63 additions & 0 deletions precompiles/src/precompile_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ impl<T> From<DiscriminantResult<T>> for IsPrecompileResult {
pub enum PrecompileKind {
Single(H160),
Prefixed(Vec<u8>),
Multiple(Vec<H160>),
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -833,6 +834,68 @@ impl<A> IsActivePrecompile for RevertPrecompile<A> {
}
}

/// Precompiles that were removed from a precompile set.
/// Still considered precompiles but are inactive and always revert.
pub struct RemovedPrecompilesAt<A>(PhantomData<A>);
impl<A> PrecompileSetFragment for RemovedPrecompilesAt<A>
where
A: Get<Vec<H160>>,
{
#[inline(always)]
fn new() -> Self {
Self(PhantomData)
}

#[inline(always)]
fn execute<R: pallet_evm::Config>(
&self,
handle: &mut impl PrecompileHandle,
) -> Option<PrecompileResult> {
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<H160> {
A::get()
}

fn summarize_checks(&self) -> Vec<PrecompileCheckSummary> {
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<A> IsActivePrecompile for RemovedPrecompilesAt<A>
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<A>(PhantomData<A>);
Expand Down
16 changes: 15 additions & 1 deletion precompiles/src/solidity/codec/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl Kind for StringKind {
/// The `bytes/string` type of Solidity.
/// It is different from `Vec<u8>` 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<K, S> {
data: Vec<u8>,
_phantom: PhantomData<(K, S)>,
Expand All @@ -68,6 +68,20 @@ impl<K: Kind, S: Get<u32>> Clone for BoundedBytesString<K, S> {
}
}

impl<K1, S1, K2, S2> PartialEq<BoundedBytesString<K2, S2>> for BoundedBytesString<K1, S1> {
fn eq(&self, other: &BoundedBytesString<K2, S2>) -> bool {
self.data.eq(&other.data)
}
}

impl<K, S> Eq for BoundedBytesString<K, S> {}

impl<K, S> Default for BoundedBytesString<K, S> {
fn default() -> Self {
Vec::default().into()
}
}

impl<K, S: Get<u32>> BoundedBytesString<K, S> {
pub fn as_bytes(&self) -> &[u8] {
&self.data
Expand Down
19 changes: 19 additions & 0 deletions precompiles/src/solidity/codec/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,3 +380,22 @@ impl<T, S> From<BoundedVec<T, S>> for Vec<T> {
value.inner
}
}

impl<T, S> Default for BoundedVec<T, S> {
fn default() -> Self {
Self {
inner: Default::default(),
_phantom: PhantomData,
}
}
}

impl<T, S> BoundedVec<T, S> {
pub fn len(&self) -> usize {
self.inner.len()
}

pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
}

0 comments on commit ba663fe

Please sign in to comment.