Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Fix buggy non-nested tuples #48

Merged
merged 4 commits into from
Jul 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion ethers-contract/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,10 @@ where
function: &Function,
args: T,
) -> Result<ContractCall<P, S, D>, Error> {
let tokens = args.into_tokens();

// create the calldata
let data = function.encode_input(&args.into_tokens())?;
let data = function.encode_input(&tokens)?;

// create the tx object
let tx = TransactionRequest {
Expand Down
8 changes: 8 additions & 0 deletions ethers-contract/tests/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ mod eth_tests {
.unwrap();
assert_eq!(init_address, Address::zero());
assert_eq!(init_value, "initial value");

// methods with multiple args also work
let _tx_hash = contract
.method::<_, H256>("setValues", ("hi".to_owned(), "bye".to_owned()))
.unwrap()
.send()
.await
.unwrap();
}

#[tokio::test]
Expand Down
7 changes: 7 additions & 0 deletions ethers-contract/tests/contract.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ contract SimpleStorage {

address public lastSender;
string _value;
string _otherValue;

constructor(string memory value) public {
emit ValueChanged(msg.sender, address(0), _value, value);
Expand All @@ -21,4 +22,10 @@ contract SimpleStorage {
_value = value;
lastSender = msg.sender;
}

function setValues(string memory value, string memory value2) public {
_value = value;
_otherValue = value2;
lastSender = msg.sender;
}
}
39 changes: 36 additions & 3 deletions ethers-core/src/abi/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ pub trait Tokenize {

impl<'a> Tokenize for &'a [Token] {
fn into_tokens(self) -> Vec<Token> {
self.to_vec()
flatten_tokens(self.to_vec())
}
}

impl<T: Tokenizable> Tokenize for T {
fn into_tokens(self) -> Vec<Token> {
vec![self.into_token()]
flatten_tokens(vec![self.into_token()])
}
}

Expand Down Expand Up @@ -476,9 +476,25 @@ impl_fixed_types!(256);
impl_fixed_types!(512);
impl_fixed_types!(1024);

/// Helper for flattening non-nested tokens into their inner
/// types, e.g. (A, B, C ) would get tokenized to Tuple([A, B, C])
/// when in fact we need [A, B, C].
fn flatten_tokens(tokens: Vec<Token>) -> Vec<Token> {
if tokens.len() == 1 {
// flatten the tokens if required
// and there is no nesting
match tokens[0].clone() {
Token::Tuple(inner) => inner,
other => vec![other],
}
} else {
tokens
}
}

#[cfg(test)]
mod tests {
use super::{Detokenize, Tokenizable};
use super::*;
use crate::types::{Address, U256};
use ethabi::Token;

Expand Down Expand Up @@ -511,6 +527,23 @@ mod tests {
let _vec_of_tuple_5: Vec<(Address, Vec<Vec<u8>>, String, U256, bool)> = output();
}

#[test]
fn nested_tokenization() {
let x = (1u64, (2u64, 3u64));
let tokens = x.into_tokens();
assert_eq!(
tokens,
vec![
Token::Uint(1.into()),
Token::Tuple(vec![Token::Uint(2.into()), Token::Uint(3.into())])
]
);

let x = (1u64, 2u64);
let tokens = x.into_tokens();
assert_eq!(tokens, vec![Token::Uint(1.into()), Token::Uint(2.into()),]);
}

#[test]
fn should_decode_array_of_fixed_bytes() {
// byte[8][]
Expand Down