fix(codec)!: ambiguity unit8[] and bytes (#613)
* fix: unit8 encoding * feat: use ethers::types::Bytes for solidity bytes type * feat: add const generic from impls * fix: failing tests * fix: make compatible with bytes * update changelog * make compatible with encoding changes * chore rm write to file
This commit is contained in:
parent
3a768b9c99
commit
2c30468b70
|
@ -2,6 +2,8 @@
|
|||
|
||||
## ethers-core
|
||||
|
||||
- Change types mapping for solidity `bytes` to rust `ethers::core::Bytes` and solidity `uint8[]` to rust `Vec<u8>`.
|
||||
[613](https://github.com/gakonst/ethers-rs/pull/613)
|
||||
- Fix `format_units` to return a `String` of representing a decimal point float
|
||||
such that the decimal places don't get truncated.
|
||||
[597](https://github.com/gakonst/ethers-rs/pull/597)
|
||||
|
|
|
@ -8,7 +8,7 @@ pub(crate) fn expand(kind: &ParamType) -> Result<TokenStream> {
|
|||
|
||||
match kind {
|
||||
ParamType::Address => Ok(quote! { #ethers_core::types::Address }),
|
||||
ParamType::Bytes => Ok(quote! { Vec<u8> }),
|
||||
ParamType::Bytes => Ok(quote! { #ethers_core::types::Bytes }),
|
||||
ParamType::Int(n) => match n / 8 {
|
||||
1 => Ok(quote! { i8 }),
|
||||
2 => Ok(quote! { i16 }),
|
||||
|
|
|
@ -297,7 +297,7 @@ impl<M: Middleware> Multicall<M> {
|
|||
.iter()
|
||||
.zip(&return_data)
|
||||
.map(|(call, bytes)| {
|
||||
let mut tokens: Vec<Token> = call.function.decode_output(bytes)?;
|
||||
let mut tokens: Vec<Token> = call.function.decode_output(bytes.as_ref())?;
|
||||
|
||||
Ok(match tokens.len() {
|
||||
0 => Token::Tuple(vec![]),
|
||||
|
@ -343,10 +343,10 @@ impl<M: Middleware> Multicall<M> {
|
|||
Ok(tx_hash)
|
||||
}
|
||||
|
||||
fn as_contract_call(&self) -> ContractCall<M, (U256, Vec<Vec<u8>>)> {
|
||||
fn as_contract_call(&self) -> ContractCall<M, (U256, Vec<Bytes>)> {
|
||||
// Map the Multicall struct into appropriate types for `aggregate` function
|
||||
let calls: Vec<(Address, Vec<u8>)> =
|
||||
self.calls.iter().map(|call| (call.target, call.data.to_vec())).collect();
|
||||
let calls: Vec<(Address, Bytes)> =
|
||||
self.calls.iter().map(|call| (call.target, call.data.clone())).collect();
|
||||
|
||||
// Construct the ContractCall for `aggregate` function to broadcast the transaction
|
||||
let mut contract_call = self.contract.aggregate(calls);
|
||||
|
|
|
@ -41,8 +41,8 @@ mod multicallcontract_mod {
|
|||
#[doc = "Calls the contract's `aggregate` (0x252dba42) function"]
|
||||
pub fn aggregate(
|
||||
&self,
|
||||
calls: Vec<(Address, Vec<u8>)>,
|
||||
) -> ContractCall<M, (U256, Vec<Vec<u8>>)> {
|
||||
calls: Vec<(Address, Bytes)>,
|
||||
) -> ContractCall<M, (U256, Vec<Bytes>)> {
|
||||
self.0
|
||||
.method_hash([37, 45, 186, 66], calls)
|
||||
.expect("method not found (this should never happen)")
|
||||
|
|
|
@ -9,7 +9,7 @@ mod eth_tests {
|
|||
use super::*;
|
||||
use ethers_contract::{LogMeta, Multicall};
|
||||
use ethers_core::{
|
||||
types::{transaction::eip712::Eip712, Address, BlockId, I256, U256},
|
||||
types::{transaction::eip712::Eip712, Address, BlockId, Bytes, I256, U256},
|
||||
utils::{keccak256, Ganache},
|
||||
};
|
||||
use ethers_derive_eip712::*;
|
||||
|
@ -525,7 +525,7 @@ mod eth_tests {
|
|||
struct FooBar {
|
||||
foo: I256,
|
||||
bar: U256,
|
||||
fizz: Vec<u8>,
|
||||
fizz: Bytes,
|
||||
buzz: [u8; 32],
|
||||
far: String,
|
||||
out: Address,
|
||||
|
@ -563,7 +563,7 @@ mod eth_tests {
|
|||
let foo_bar = FooBar {
|
||||
foo: I256::from(10),
|
||||
bar: U256::from(20),
|
||||
fizz: b"fizz".to_vec(),
|
||||
fizz: b"fizz".into(),
|
||||
buzz: keccak256("buzz"),
|
||||
far: String::from("space"),
|
||||
out: Address::from([0; 20]),
|
||||
|
|
|
@ -18,6 +18,6 @@ serde_json = "1.0.68"
|
|||
proc-macro2 = "1.0.29"
|
||||
|
||||
[dev-dependencies]
|
||||
ethers-contract = { version = "^0.6.0", path = "../../ethers-contract"}
|
||||
ethers-contract = { version = "^0.6.0", path = "../../ethers-contract", features = ["abigen"]}
|
||||
ethers-contract-derive = { version = "^0.6.0", path = "../../ethers-contract/ethers-contract-derive" }
|
||||
ethers-signers = { version = "^0.6.0", path = "../../ethers-signers" }
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
//!
|
||||
//! # Example Usage
|
||||
//!
|
||||
//! ```rust
|
||||
//! ```ignore
|
||||
//! use ethers_contract::EthAbiType;
|
||||
//! use ethers_derive_eip712::*;
|
||||
//! use ethers_core::types::{transaction::eip712::Eip712, H160};
|
||||
|
@ -50,7 +50,7 @@
|
|||
//! project: "radicle-reward".to_string(),
|
||||
//! };
|
||||
//!
|
||||
//! let hash = puzzle.encode_eip712()?;
|
||||
//! let hash = puzzle.encode_eip712().unwrap();
|
||||
//! ```
|
||||
//!
|
||||
//! # Limitations
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
//! This module implements extensions to the [`ethabi`](https://docs.rs/ethabi) API.
|
||||
// Adapted from [Gnosis' ethcontract](https://github.com/gnosis/ethcontract-rs/blob/master/common/src/abiext.rs)
|
||||
use crate::{types::Selector, utils::id};
|
||||
use crate::{
|
||||
types::{Bytes, Selector},
|
||||
utils::id,
|
||||
};
|
||||
|
||||
pub use ethabi::{Contract as Abi, *};
|
||||
|
||||
|
@ -117,7 +120,8 @@ macro_rules! impl_abi_type {
|
|||
}
|
||||
|
||||
impl_abi_type!(
|
||||
Vec<u8> => Bytes,
|
||||
Bytes => Bytes,
|
||||
Vec<u8> => Array(Box::new(ParamType::Uint(8))),
|
||||
Address => Address,
|
||||
bool => Bool,
|
||||
String => String,
|
||||
|
@ -231,10 +235,17 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn abi_type_works() {
|
||||
assert_eq!(ParamType::Bytes, Vec::<u8>::param_type());
|
||||
assert_eq!(ParamType::Array(Box::new(ParamType::Bytes)), Vec::<Vec<u8>>::param_type());
|
||||
assert_eq!(ParamType::Bytes, Bytes::param_type());
|
||||
assert_eq!(ParamType::Array(Box::new(ParamType::Uint(8))), Vec::<u8>::param_type());
|
||||
assert_eq!(ParamType::Array(Box::new(ParamType::Bytes)), Vec::<Bytes>::param_type());
|
||||
assert_eq!(
|
||||
ParamType::Array(Box::new(ParamType::Array(Box::new(ParamType::Bytes)))),
|
||||
ParamType::Array(Box::new(ParamType::Array(Box::new(ParamType::Uint(8))))),
|
||||
Vec::<Vec<u8>>::param_type()
|
||||
);
|
||||
assert_eq!(
|
||||
ParamType::Array(Box::new(ParamType::Array(Box::new(ParamType::Array(Box::new(
|
||||
ParamType::Uint(8)
|
||||
)))))),
|
||||
Vec::<Vec<Vec<u8>>>::param_type()
|
||||
);
|
||||
|
||||
|
@ -242,7 +253,7 @@ mod tests {
|
|||
|
||||
assert_eq!(
|
||||
ParamType::Tuple(vec![ParamType::Bytes, ParamType::Address]),
|
||||
<(Vec<u8>, Address)>::param_type()
|
||||
<(Bytes, Address)>::param_type()
|
||||
);
|
||||
|
||||
assert_eq!(ParamType::FixedBytes(32), <[u8; 32]>::param_type());
|
||||
|
|
|
@ -287,7 +287,7 @@ macro_rules! tokenizable_item {
|
|||
|
||||
tokenizable_item! {
|
||||
Token, String, Address, H256, U256, I256, U128, bool, Vec<u8>,
|
||||
i8, i16, i32, i64, i128, u16, u32, u64, u128,
|
||||
i8, i16, i32, i64, i128, u16, u32, u64, u128, Bytes,
|
||||
}
|
||||
|
||||
macro_rules! impl_tokenizable_item_tuple {
|
||||
|
@ -321,12 +321,13 @@ impl Tokenizable for Vec<u8> {
|
|||
fn from_token(token: Token) -> Result<Self, InvalidOutputType> {
|
||||
match token {
|
||||
Token::Bytes(data) => Ok(data),
|
||||
Token::Array(data) => data.into_iter().map(u8::from_token).collect(),
|
||||
Token::FixedBytes(data) => Ok(data),
|
||||
other => Err(InvalidOutputType(format!("Expected `bytes`, got {:?}", other))),
|
||||
}
|
||||
}
|
||||
fn into_token(self) -> Token {
|
||||
Token::Bytes(self)
|
||||
Token::Array(self.into_iter().map(Tokenizable::into_token).collect())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,18 @@ impl From<Vec<u8>> for Bytes {
|
|||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> From<[u8; N]> for Bytes {
|
||||
fn from(src: [u8; N]) -> Self {
|
||||
src.to_vec().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize> From<&'a [u8; N]> for Bytes {
|
||||
fn from(src: &'a [u8; N]) -> Self {
|
||||
src.to_vec().into()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn serialize_bytes<S, T>(x: T, s: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
|
|
Loading…
Reference in New Issue