diff --git a/ethers-core/src/abi/codec.rs b/ethers-core/src/abi/codec.rs index fef30f18..39cf4031 100644 --- a/ethers-core/src/abi/codec.rs +++ b/ethers-core/src/abi/codec.rs @@ -9,12 +9,28 @@ use crate::{ pub trait AbiEncode { /// ABI encode the type fn encode(self) -> Vec; + + /// Returns the encoded value as hex string, _with_ a `0x` prefix + fn encode_hex(self) -> String + where + Self: Sized, + { + format!("0x{}", hex::encode(self.encode())) + } } /// Trait for ABI decoding pub trait AbiDecode: Sized { /// Decodes the ABI encoded data fn decode(bytes: impl AsRef<[u8]>) -> Result; + + /// Decode hex encoded ABI encoded data + /// + /// Expects a hex encoded string, with optional `0x` prefix + fn decode_hex(data: impl AsRef) -> Result { + let bytes: Bytes = data.as_ref().parse()?; + Self::decode(bytes) + } } macro_rules! impl_abi_codec { diff --git a/ethers-core/src/abi/error.rs b/ethers-core/src/abi/error.rs index d9a1ae98..48a3dcd2 100644 --- a/ethers-core/src/abi/error.rs +++ b/ethers-core/src/abi/error.rs @@ -24,6 +24,7 @@ pub(crate) use _format_err as format_err; macro_rules! _bail { ($($tt:tt)*) => { return Err($crate::abi::error::format_err!($($tt)*)) }; } +use crate::types::ParseBytesError; pub(crate) use _bail as bail; /// ABI codec related errors @@ -39,4 +40,7 @@ pub enum AbiError { #[error("missing or wrong function selector")] WrongSelector, + + #[error(transparent)] + ParseBytesError(#[from] ParseBytesError), } diff --git a/ethers-core/src/types/mod.rs b/ethers-core/src/types/mod.rs index 6e821163..5083fbb4 100644 --- a/ethers-core/src/types/mod.rs +++ b/ethers-core/src/types/mod.rs @@ -25,7 +25,7 @@ mod i256; pub use i256::{Sign, I256}; mod bytes; -pub use self::bytes::Bytes; +pub use self::bytes::{Bytes, ParseBytesError}; mod block; pub use block::{Block, BlockId, BlockNumber};