Skip to content

Commit

Permalink
Fix abi.decode behaviour with nested types
Browse files Browse the repository at this point in the history
  • Loading branch information
danhper committed Aug 8, 2024
1 parent 7b5402d commit 9e8937e
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 13 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
* Add `array.filter` function
* Add support for bitwise operators

### Bug fixes

* Fix `abi.decode` for nested types

### Other changes

* Drop `Receipt` type and use `NamedTuple` instead
Expand Down
50 changes: 37 additions & 13 deletions src/interpreter/builtins/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,25 @@ fn abi_decode_calldata(_env: &mut Env, receiver: &Value, args: &[Value]) -> Resu
]))
}

fn value_to_soltype(value: &Value) -> Result<DynSolType> {
match value {
Value::TypeObject(ty) => Ok(DynSolType::try_from(ty.clone())?),
Value::Tuple(values) => values
.iter()
.map(value_to_soltype)
.collect::<Result<Vec<_>>>()
.map(DynSolType::Tuple),
_ => bail!("abi.decode expects tuple of types as second argument"),
}
}

fn abi_decode(args: &[Value]) -> Result<Value> {
let decoded = match args {
[Value::Bytes(data_), Value::Tuple(values)] => {
let types = values
.iter()
.map(|v| match v {
Value::TypeObject(ty) => ty.clone().try_into(),
_ => bail!("abi.decode function expects tuple of types as argument"),
})
.collect::<Result<Vec<_>>>()?;
DynSolType::Tuple(types).abi_decode_params(data_)?
}
[Value::Bytes(data_), Value::TypeObject(ty)] => {
DynSolType::try_from(ty.clone())?.abi_decode(data_)?
[Value::Bytes(data_), value] => {
let ty = value_to_soltype(value)?;
ty.abi_decode_params(data_)?
}
_ => bail!("abi.decode function expects bytes and tuple of types as argument"),
_ => bail!("abi.decode expects bytes and tuple of types as argument"),
};
decoded.try_into()
}
Expand Down Expand Up @@ -194,4 +197,25 @@ mod tests {
.unwrap();
assert_eq!(Value::Tuple(args), decoded);
}

#[test]
fn test_abi_decode_nested_types() {
let args = vec![
Value::Bool(true),
Value::Tuple(vec![Value::from("foo"), Value::from(2u64)]),
];
let encoded = abi_encode(&args).unwrap();
let decoded = abi_decode(&[
encoded.clone(),
Value::Tuple(vec![
Value::TypeObject(Type::Bool),
Value::Tuple(vec![
Value::TypeObject(Type::String),
Value::TypeObject(Type::Uint(256)),
]),
]),
])
.unwrap();
assert_eq!(Value::Tuple(args), decoded);
}
}

0 comments on commit 9e8937e

Please sign in to comment.