From 84aafbbd1f657f12cf5bdf4db9c18e70e5ad0754 Mon Sep 17 00:00:00 2001 From: Georgios Konstantopoulos Date: Thu, 12 Nov 2020 12:08:20 +0200 Subject: [PATCH] Misc Fixes (#97) * fix: use generic instead of impl Trait * fix: do not skip first 4 bytes when decoding outputs --- ethers-contract/src/base.rs | 30 ++++++++++++++++-------------- ethers-contract/src/lib.rs | 2 +- ethers-core/src/types/bytes.rs | 2 +- ethers-providers/src/lib.rs | 16 ++++++++-------- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/ethers-contract/src/base.rs b/ethers-contract/src/base.rs index b4348439..d555c64e 100644 --- a/ethers-contract/src/base.rs +++ b/ethers-contract/src/base.rs @@ -21,6 +21,9 @@ pub enum AbiError { /// Thrown when detokenizing an argument #[error(transparent)] DetokenizationError(#[from] InvalidOutputType), + + #[error("missing or wrong function selector")] + WrongSelector, } /// A reduced form of `Contract` which just takes the `abi` and produces @@ -33,7 +36,7 @@ pub struct BaseContract { /// functions in the contract ABI. This is used to avoid allocation when /// searching for matching functions by signature. // Adapted from: https://github.com/gnosis/ethcontract-rs/blob/master/src/contract.rs - pub(crate) methods: HashMap, + pub methods: HashMap, } impl From for BaseContract { @@ -68,10 +71,10 @@ impl BaseContract { /// /// If the function exists multiple times and you want to use one of the overloaded /// versions, consider using `decode_with_selector` - pub fn decode( + pub fn decode>( &self, name: &str, - bytes: impl AsRef<[u8]>, + bytes: T, ) -> Result { let function = self.abi.function(name)?; decode_fn(function, bytes, true) @@ -90,10 +93,10 @@ impl BaseContract { } /// Decodes the provided ABI encoded bytes with the selected function selector - pub fn decode_with_selector( + pub fn decode_with_selector>( &self, signature: Selector, - bytes: impl AsRef<[u8]>, + bytes: T, ) -> Result { let function = self.get_from_signature(signature)?; decode_fn(function, bytes, true) @@ -152,20 +155,19 @@ pub(crate) fn encode_fn(function: &Function, args: T) -> Result( +pub fn decode_fn>( function: &Function, - bytes: impl AsRef<[u8]>, + bytes: T, is_input: bool, ) -> Result { - let mut bytes = bytes.as_ref(); - if bytes.starts_with(&function.selector()) { - bytes = &bytes[4..]; - } - + let bytes = bytes.as_ref(); let tokens = if is_input { - function.decode_input(bytes.as_ref())? + if bytes.len() < 4 || bytes[..4] != function.selector() { + return Err(AbiError::WrongSelector); + } + function.decode_input(&bytes[4..])? } else { - function.decode_output(bytes.as_ref())? + function.decode_output(bytes)? }; Ok(D::from_tokens(tokens)?) diff --git a/ethers-contract/src/lib.rs b/ethers-contract/src/lib.rs index bf04d17c..b36e267e 100644 --- a/ethers-contract/src/lib.rs +++ b/ethers-contract/src/lib.rs @@ -17,7 +17,7 @@ mod contract; pub use contract::Contract; mod base; -pub use base::BaseContract; +pub use base::{decode_fn, BaseContract}; mod call; pub use call::ContractError; diff --git a/ethers-core/src/types/bytes.rs b/ethers-core/src/types/bytes.rs index bdd206d6..c4953456 100644 --- a/ethers-core/src/types/bytes.rs +++ b/ethers-core/src/types/bytes.rs @@ -3,7 +3,7 @@ use serde::de::{Error, Unexpected}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; /// Wrapper type around Vec to deserialize/serialize "0x" prefixed ethereum hex strings -#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize, Ord, PartialOrd)] pub struct Bytes( #[serde( serialize_with = "serialize_bytes", diff --git a/ethers-providers/src/lib.rs b/ethers-providers/src/lib.rs index fbaad912..87a452ad 100644 --- a/ethers-providers/src/lib.rs +++ b/ethers-providers/src/lib.rs @@ -380,7 +380,7 @@ pub trait Middleware: Sync + Send + Debug { req: TransactionRequest, trace_type: Vec, block: Option, - ) -> Result { + ) -> Result { self.inner() .trace_call(req, trace_type, block) .await @@ -392,7 +392,7 @@ pub trait Middleware: Sync + Send + Debug { &self, data: Bytes, trace_type: Vec, - ) -> Result { + ) -> Result { self.inner() .trace_raw_transaction(data, trace_type) .await @@ -404,7 +404,7 @@ pub trait Middleware: Sync + Send + Debug { &self, hash: H256, trace_type: Vec, - ) -> Result { + ) -> Result { self.inner() .trace_replay_transaction(hash, trace_type) .await @@ -416,7 +416,7 @@ pub trait Middleware: Sync + Send + Debug { &self, block: BlockNumber, trace_type: Vec, - ) -> Result, ProviderError> { + ) -> Result, Self::Error> { self.inner() .trace_replay_block_transactions(block, trace_type) .await @@ -424,12 +424,12 @@ pub trait Middleware: Sync + Send + Debug { } /// Returns traces created at given block - async fn trace_block(&self, block: BlockNumber) -> Result, ProviderError> { + async fn trace_block(&self, block: BlockNumber) -> Result, Self::Error> { self.inner().trace_block(block).await.map_err(FromErr::from) } /// Return traces matching the given filter - async fn trace_filter(&self, filter: TraceFilter) -> Result, ProviderError> { + async fn trace_filter(&self, filter: TraceFilter) -> Result, Self::Error> { self.inner() .trace_filter(filter) .await @@ -441,7 +441,7 @@ pub trait Middleware: Sync + Send + Debug { &self, hash: H256, index: Vec, - ) -> Result { + ) -> Result { self.inner() .trace_get(hash, index) .await @@ -449,7 +449,7 @@ pub trait Middleware: Sync + Send + Debug { } /// Returns all traces of a given transaction - async fn trace_transaction(&self, hash: H256) -> Result, ProviderError> { + async fn trace_transaction(&self, hash: H256) -> Result, Self::Error> { self.inner() .trace_transaction(hash) .await