Skip to content

Commit

Permalink
fix(sol-type-parser): normalize u?int to u?int256 (#397)
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes authored Nov 2, 2023
1 parent 919a338 commit 9877bb2
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 10 deletions.
2 changes: 1 addition & 1 deletion crates/json-abi/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ mod tests {
parse_sig::<true>("toString(uint number)(string s)"),
Ok((
"toString".into(),
vec![param2("uint", "number")],
vec![param2("uint256", "number")],
vec![param2("string", "s")],
false
))
Expand Down
38 changes: 29 additions & 9 deletions crates/sol-type-parser/src/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ use winnow::{trace::trace, PResult, Parser};
/// A root type, with no array suffixes. Corresponds to a single, non-sequence
/// type. This is the most basic type specifier.
///
/// Note that this type might modify the input string, so [`span()`](Self::span)
/// must not be assumed to be the same as the input string.
///
/// # Examples
///
/// ```
Expand All @@ -20,10 +23,12 @@ use winnow::{trace::trace, PResult, Parser};
///
/// // No tuples
/// assert!(RootType::parse("(uint256,uint256)").is_err());
///
/// // Input string might get modified
/// assert_eq!(RootType::parse("uint")?.span(), "uint256");
/// # Ok::<_, alloy_sol_type_parser::Error>(())
/// ```
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct RootType<'a>(&'a str);

impl<'a> TryFrom<&'a str> for RootType<'a> {
Expand Down Expand Up @@ -64,26 +69,28 @@ impl<'a> RootType<'a> {
/// Parse a root type from a string.
#[inline]
pub fn parse(input: &'a str) -> Result<Self> {
if is_valid_identifier(input) {
Ok(Self(input))
} else {
Err(Error::invalid_type_string(input))
}
Self::parser.parse(input).map_err(Error::parser)
}

/// [`winnow`] parser for this type.
pub fn parser(input: &mut &'a str) -> PResult<Self> {
trace("RootType", |input: &mut &'a str| {
identifier(input).map(|mut ident| {
identifier(input).map(|ident| {
// Workaround for enums in library function params or returns.
// See: https://github.com/alloy-rs/core/pull/386
// See ethabi workaround: https://github.com/rust-ethereum/ethabi/blob/b1710adc18f5b771d2d2519c87248b1ba9430778/ethabi/src/param_type/reader.rs#L162-L167
if input.starts_with('.') {
*input = &input[1..];
let _ = identifier(input);
ident = "uint8";
return Self("uint8");
}

// Normalize the `u?int` aliases to the canonical `u?int256`
match ident {
"uint" => Self("uint256"),
"int" => Self("int256"),
_ => Self(ident),
}
Self(ident)
})
})
.parse_next(input)
Expand Down Expand Up @@ -127,3 +134,16 @@ impl<'a> RootType<'a> {
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn modified_input() {
assert_eq!(RootType::parse("Contract.Enum"), Ok(RootType("uint8")));

assert_eq!(RootType::parse("int"), Ok(RootType("int256")));
assert_eq!(RootType::parse("uint"), Ok(RootType("uint256")));
}
}
17 changes: 17 additions & 0 deletions crates/sol-type-parser/src/type_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,15 @@ mod test {

#[test]
fn parse_test() {
assert_eq!(
TypeSpecifier::parse("uint"),
Ok(TypeSpecifier {
span: "uint",
stem: TypeStem::parse("uint256").unwrap(),
sizes: vec![],
})
);

assert_eq!(
TypeSpecifier::parse("uint256"),
Ok(TypeSpecifier {
Expand Down Expand Up @@ -256,6 +265,14 @@ mod test {

#[test]
fn try_basic_solidity() {
assert_eq!(
TypeSpecifier::parse("uint").unwrap().try_basic_solidity(),
Ok(())
);
assert_eq!(
TypeSpecifier::parse("int").unwrap().try_basic_solidity(),
Ok(())
);
assert_eq!(
TypeSpecifier::parse("uint256")
.unwrap()
Expand Down

0 comments on commit 9877bb2

Please sign in to comment.