Skip to content

Commit a038aa8

Browse files
fix(dyn-abi): coerce JSON int values above i64::MAX for signed types (#1158)
eip712 coerce_json read signed integers only through serde_json's as_i64, while the sibling uint path uses as_u64. serde_json stores any integer in (i64::MAX, u64::MAX] as a u64, so a valid positive value for int72..int256 (e.g. 2^63 into int128) returned None and coerce_json failed, even though the same value is accepted as a JSON string and accepted by uint as a number. Add a u64 fallback mirroring uint, plus a regression test.
1 parent a5df2f9 commit a038aa8

1 file changed

Lines changed: 14 additions & 0 deletions

File tree

crates/dyn-abi/src/eip712/coerce.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ fn int(n: usize, value: &serde_json::Value) -> Option<I256> {
6161
if let Some(num) = value.as_i64() {
6262
return Some(I256::try_from(num).unwrap());
6363
}
64+
if let Some(num) = value.as_u64() {
65+
return Some(I256::try_from(num).unwrap());
66+
}
6467
value.as_str().and_then(|s| s.parse().ok())
6568
})()
6669
.and_then(|x| (x.bits() <= n as u32).then_some(x))
@@ -202,6 +205,17 @@ mod tests {
202205
assert!(ty.coerce_json(&j).is_err());
203206
}
204207

208+
#[test]
209+
fn int_coerces_json_number_above_i64_max() {
210+
// serde_json stores this as a u64 (it exceeds i64::MAX), but it is a valid
211+
// positive int128. The number form must coerce the same as the string form.
212+
let n: u64 = 9223372036854775808; // 2^63
213+
let ty = DynSolType::Int(128);
214+
let want = DynSolValue::Int("9223372036854775808".parse().unwrap(), 128);
215+
assert_eq!(ty.coerce_json(&json!(n.to_string())).unwrap(), want);
216+
assert_eq!(ty.coerce_json(&json!(n)).unwrap(), want);
217+
}
218+
205219
#[test]
206220
fn it_coerces() {
207221
let j = json!({

0 commit comments

Comments
 (0)