From 099f937c8e9cde94944169a690ed3905bfb4e16a Mon Sep 17 00:00:00 2001 From: Daniel Perez Date: Sun, 15 Sep 2024 21:25:12 +0100 Subject: [PATCH] Change FixBytes internal encoding --- CHANGELOG.md | 6 ++++++ src/interpreter/types.rs | 39 ++++++++++++++++++++++----------------- src/interpreter/value.rs | 12 +++++++----- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5229fdd..4e7cf49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Not released + +### Other changes + +* Encode `FixedBytes` as with zero padding on the left instead of the right + ## v0.1.3 (2024-08-15) ### Features diff --git a/src/interpreter/types.rs b/src/interpreter/types.rs index 74a4b91..3d7632a 100644 --- a/src/interpreter/types.rs +++ b/src/interpreter/types.rs @@ -467,11 +467,11 @@ impl Type { (Type::Int(size), Value::Uint(v, _)) => { Value::Int((*v).try_into()?, *size).validate_int() } - (Type::FixBytes(bytes_num), Value::Uint(v, bits_num)) + (t @ Type::FixBytes(bytes_num), Value::Uint(v, bits_num)) if *bytes_num * 8 == *bits_num => { let bytes = B256::from_slice(&v.to_be_bytes_vec()); - Ok(Value::FixBytes(bytes, *bytes_num)) + t.cast(&Value::FixBytes(bytes, 32)) } (Type::Uint(bits_num), Value::FixBytes(v, bytes_num)) if *bytes_num * 8 == *bits_num => @@ -480,9 +480,13 @@ impl Type { Ok(Value::Uint(num, *bits_num)) } (Type::FixBytes(target_bytes_num), Value::FixBytes(bytes, _)) => { - let mut new_bytes = bytes.0.to_vec(); - new_bytes.resize(*target_bytes_num, 0); // "erase" all bytes after target_bytes_num - new_bytes.resize(32, 0); // pad with zero to be able to create a B256 + let mut new_bytes = bytes.to_vec(); + if *target_bytes_num < 32 { + let to_fill = 32 - *target_bytes_num; + let filler = vec![0; to_fill]; + new_bytes[..to_fill].copy_from_slice(&filler); + } + new_bytes[..bytes.0.len()].copy_from_slice(&bytes.0); Ok(Value::FixBytes( B256::from_slice(&new_bytes), *target_bytes_num, @@ -491,10 +495,14 @@ impl Type { (Type::Transaction, Value::FixBytes(v, 32)) => Ok(Value::Transaction(*v)), (Type::Bytes, Value::Str(v)) => Ok(Value::Bytes(v.as_bytes().to_vec())), (type_ @ Type::FixBytes(_), Value::Str(_)) => type_.cast(&Type::Bytes.cast(value)?), + (Type::Bytes, Value::FixBytes(v, _)) => Ok(Value::Bytes(v.0.to_vec())), (Type::FixBytes(size), Value::Bytes(v)) => { - let mut new_vector = v.clone(); - new_vector.resize(*size, 0); - Ok(Value::FixBytes(B256::from_slice(&new_vector), *size)) + let mut new_bytes = v.clone(); + if new_bytes.len() > *size { + new_bytes = new_bytes[new_bytes.len() - *size..].to_vec(); + } + new_bytes.resize(32, 0); + Ok(Value::FixBytes(B256::from_slice(&new_bytes), *size)) } (Type::NamedTuple(name, types_), Value::Tuple(values)) => { let mut new_values = IndexMap::new(); @@ -678,16 +686,13 @@ mod tests { #[test] fn cast_bytes() { - let signature = - Value::from_hex("0x70a08231b98ef4ca268c9cc3f6b4590e4bfec28280db06bb5d45e689f2a360be") + let b256_value = + Value::from_hex("0x00000000000000000000000000000000000000000000000000000000281dd5af") .unwrap(); - let selector = Value::from_hex("0x70a08231").unwrap(); - assert_eq!(Type::FixBytes(4).cast(&signature).unwrap(), selector); - let padded_selector = "0x70a0823100000000000000000000000000000000000000000000000000000000"; - assert_eq!( - Type::FixBytes(32).cast(&selector).unwrap(), - Value::from_hex(padded_selector).unwrap() - ); + println!("{:?}", b256_value); + let b4_value = Value::from_hex("0x281dd5af").unwrap(); + assert_eq!(Type::FixBytes(4).cast(&b256_value).unwrap(), b4_value); + assert_eq!(Type::FixBytes(32).cast(&b4_value).unwrap(), b256_value); } #[test] diff --git a/src/interpreter/value.rs b/src/interpreter/value.rs index 12a40f4..53d1537 100644 --- a/src/interpreter/value.rs +++ b/src/interpreter/value.rs @@ -71,7 +71,7 @@ impl Display for Value { Value::Addr(a) => write!(f, "{}", a.to_checksum(None)), Value::Str(s) => write!(f, "\"{}\"", s), Value::FixBytes(w, s) => { - let bytes = w[..*s].to_vec(); + let bytes = w[32 - *s..].to_vec(); write!(f, "0x{}", hex::encode(bytes)) } Value::Bytes(bytes) => write!(f, "0x{}", hex::encode(bytes)), @@ -292,8 +292,9 @@ impl FromHex for Value { } else if hex.as_ref().len() == 42 { Value::Addr(Address::from_hex(hex)?) } else if hex.as_ref().len() <= 66 { - let mut bytes = Vec::from_hex(&hex.as_ref()[2..])?; - bytes.resize(32, 0); + let data = Vec::from_hex(&hex.as_ref()[2..])?; + let mut bytes = vec![0; 32]; + bytes[32 - data.len()..].copy_from_slice(&data); Value::FixBytes(B256::from_slice(&bytes), (hex.as_ref().len() - 2) / 2) } else { Value::Bytes(Vec::from_hex(&hex.as_ref()[2..])?) @@ -748,8 +749,9 @@ mod tests { assert_eq!(value, Value::Addr(addr)); let value = Value::from_hex("0xdeadbeef").unwrap(); - let mut bytes = Vec::from_hex("deadbeef").unwrap(); - bytes.resize(32, 0); + let bytes = + Vec::from_hex("00000000000000000000000000000000000000000000000000000000deadbeef") + .unwrap(); let fix_bytes = B256::from_slice(&bytes); assert_eq!(value, Value::FixBytes(fix_bytes, 4)); }