Skip to content

Commit

Permalink
eth: parse uneven hex uints correctly
Browse files Browse the repository at this point in the history
"0x1" and similar failed parsing for uint8, uint16, ... because we
used `hex::decode()` which fails for uneven strings.

We instead use the `BigUint::parse_bytes()` which is more appropriate
as the hex string encodes an uint and correctly handles leading zeroes.
  • Loading branch information
benma committed Feb 4, 2024
1 parent c0c7ea3 commit acdf23e
Showing 1 changed file with 38 additions and 22 deletions.
60 changes: 38 additions & 22 deletions src/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,33 +280,32 @@ fn encode_value(typ: &MemberType, value: &Value) -> Result<Vec<u8>, String> {
Err("Expected a string for bytes type".to_string())
}
}
DataType::Uint => {
match value {
Value::String(v) => {
if v.starts_with("0x") || v.starts_with("0X") {
Ok(hex::decode(&v[2..])
.map_err(|_| format!("could not parse {} as hex", v))?)
} else {
Ok(BigUint::from_str(v)
.map_err(|e| e.to_string())?
.to_bytes_be())
}
DataType::Uint => match value {
Value::String(v) => {
if v.starts_with("0x") || v.starts_with("0X") {
Ok(BigUint::parse_bytes(&v[2..].as_bytes(), 16)
.ok_or(format!("could not parse {} as hex", v))?
.to_bytes_be())
} else {
Ok(BigUint::from_str(v)
.map_err(|e| e.to_string())?
.to_bytes_be())
}
Value::Number(n) => {
if let Some(v) = n.as_f64() {
let v64: u64 = v as _;
if (v64 as f64) != v {
Err("Number is not an uint".to_string())
} else {
Ok(BigUint::from(v64).to_bytes_be())
}
} else {
}
Value::Number(n) => {
if let Some(v) = n.as_f64() {
let v64: u64 = v as _;
if (v64 as f64) != v {
Err("Number is not an uint".to_string())
} else {
Ok(BigUint::from(v64).to_bytes_be())
}
} else {
Err("Number is not an uint".to_string())
}
_ => Err("Wrong type for uint".to_string()),
}
}
_ => Err("Wrong type for uint".to_string()),
},
DataType::Int => match value {
Value::String(v) => Ok(BigInt::from_str(v)
.map_err(|e| e.to_string())?
Expand Down Expand Up @@ -1011,6 +1010,23 @@ mod tests {
.unwrap();
assert_eq!(vec![0xb1, 0xd8, 0x4b, 0x7c], encoded);

let encoded =
encode_value(&parse_type_no_err("uint64", &HashMap::new()), &"0x1".into()).unwrap();
assert_eq!(vec![0x01], encoded);

let encoded = encode_value(
&parse_type_no_err("uint64", &HashMap::new()),
&"0x0001".into(),
)
.unwrap();
assert_eq!(vec![0x01], encoded);

assert!(encode_value(
&parse_type_no_err("uint64", &HashMap::new()),
&"0xnot correct".into(),
)
.is_err());

let encoded = encode_value(
&parse_type_no_err("int64", &HashMap::new()),
&2983742332.0.into(),
Expand Down

0 comments on commit acdf23e

Please sign in to comment.