Skip to main content

df_hyperliquid_core/client/evm/
abi.rs

1//! Solidity's ABI encoding: integers to 256 bits, addresses, booleans, `bytesN`,
2//! `bytes`, strings, arrays and nested tuples. Types are read from their
3//! human-readable form, and every value and word is checked against its type.
4
5use std::fmt;
6
7use crate::client::evm::u256::{B256, U256};
8use crate::utils::sign::keccak256;
9use crate::utils::{Address, hex};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub enum Kind {
13    Uint(u16),
14    Int(u16),
15    Address,
16    Bool,
17    String,
18    Bytes,
19    /// `bytes1` to `bytes32`.
20    Fixed(usize),
21    /// `T[]`.
22    Array(Box<Kind>),
23    /// `T[n]`.
24    Sized(Box<Kind>, usize),
25    Tuple(Vec<Param>),
26}
27
28/// One parameter: its type, and the name and `indexed` mark it was declared with.
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct Param {
31    pub name: Option<String>,
32    pub kind: Kind,
33    pub indexed: bool,
34}
35
36/// A value of some [`Kind`].
37#[derive(Debug, Clone, PartialEq, Eq)]
38pub enum Token {
39    Uint(U256),
40    /// Two's complement in 256 bits: -1 is all ones, whatever the width.
41    Int(U256),
42    Address(Address),
43    Bool(bool),
44    String(String),
45    Bytes(Vec<u8>),
46    /// The `n` bytes of a `bytesN`.
47    Fixed(Vec<u8>),
48    /// `T[]` and `T[n]`.
49    Array(Vec<Token>),
50    Tuple(Vec<Token>),
51}
52
53#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
54pub enum AbiError {
55    #[error("`{0}` is not a type this reads")]
56    Type(String),
57    #[error("`{0}` is not a signature this reads; expected name(types)")]
58    Signature(String),
59    #[error("{name} must be {wants}, and `{got}` is not")]
60    Value { name: String, wants: String, got: String },
61    #[error("expected {wants} values and there are {got}")]
62    Count { wants: usize, got: usize },
63    #[error("a {kind} cannot hold {token}")]
64    Mismatch { kind: String, token: String },
65    #[error("the data ends at byte {0}, before the shape it was declared with")]
66    Short(usize),
67    #[error("the word at byte {at} does not fit {kind}")]
68    Misfit { at: usize, kind: String },
69    #[error("the calldata is for selector {found}, not {wants}")]
70    Selector { wants: String, found: String },
71}
72
73const WORD: usize = 32;
74
75/// The most a length or offset inside the data is believed before it is refused.
76const LONGEST: usize = 1 << 20;
77
78/// How deep types may nest in a written signature.
79const DEEPEST: usize = 32;
80
81/// Words a declaration may carry beside its type and name.
82const MODIFIERS: [&str; 4] = ["memory", "calldata", "storage", "payable"];
83
84impl Kind {
85    /// One type, as written: `uint`, `bytes32`, `(address, uint64)[]`.
86    pub fn parse(text: &str) -> Result<Kind, AbiError> {
87        kind_of(text, 0).ok_or_else(|| AbiError::Type(text.trim().to_owned()))
88    }
89
90    /// Whether it is encoded behind an offset, in the tail.
91    #[must_use]
92    pub fn is_dynamic(&self) -> bool {
93        match self {
94            Kind::String | Kind::Bytes | Kind::Array(_) => true,
95            Kind::Sized(inner, _) => inner.is_dynamic(),
96            Kind::Tuple(params) => params.iter().any(|param| param.kind.is_dynamic()),
97            Kind::Uint(_) | Kind::Int(_) | Kind::Address | Kind::Bool | Kind::Fixed(_) => false,
98        }
99    }
100
101    /// Bytes this takes in the head of whatever holds it.
102    fn head(&self) -> usize {
103        if self.is_dynamic() {
104            return WORD;
105        }
106        match self {
107            Kind::Sized(inner, count) => inner.head().saturating_mul(*count),
108            Kind::Tuple(params) => params.iter().map(|param| param.kind.head()).sum(),
109            _ => WORD,
110        }
111    }
112
113    /// The canonical type, as a signature or a selector spells it.
114    #[must_use]
115    pub fn canonical(&self) -> String {
116        match self {
117            Kind::Uint(bits) => format!("uint{bits}"),
118            Kind::Int(bits) => format!("int{bits}"),
119            Kind::Address => "address".to_owned(),
120            Kind::Bool => "bool".to_owned(),
121            Kind::String => "string".to_owned(),
122            Kind::Bytes => "bytes".to_owned(),
123            Kind::Fixed(size) => format!("bytes{size}"),
124            Kind::Array(inner) => format!("{}[]", inner.canonical()),
125            Kind::Sized(inner, count) => format!("{}[{count}]", inner.canonical()),
126            Kind::Tuple(params) => tuple_type(params),
127        }
128    }
129
130    /// What a value of this kind looks like typed, for a refusal to name.
131    fn wants(&self) -> String {
132        match self {
133            Kind::Uint(bits) => format!("a whole number that fits uint{bits}"),
134            Kind::Int(bits) => format!("a whole number that fits int{bits}"),
135            Kind::Address => "a 20-byte address".to_owned(),
136            Kind::Bool => "true or false".to_owned(),
137            Kind::String => "text".to_owned(),
138            Kind::Bytes => "hex bytes".to_owned(),
139            Kind::Fixed(size) => format!("{size} hex bytes"),
140            Kind::Array(_) | Kind::Sized(..) => "a list in brackets".to_owned(),
141            Kind::Tuple(_) => "a tuple in parentheses".to_owned(),
142        }
143    }
144}
145
146impl fmt::Display for Kind {
147    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148        f.write_str(&self.canonical())
149    }
150}
151
152/// `(t1,t2,...)`: the canonical spelling of a parameter list.
153#[must_use]
154pub fn tuple_type(params: &[Param]) -> String {
155    let kinds: Vec<String> = params.iter().map(|param| param.kind.canonical()).collect();
156    format!("({})", kinds.join(","))
157}
158
159/// Reads a parameter list: `uint64, bool`, or `(uint64 bid, uint64 ask)`,
160/// which is one tuple, as viem's `parseAbiParameters` reads it.
161pub fn params(text: &str) -> Result<Vec<Param>, AbiError> {
162    params_at(text, 0).ok_or_else(|| AbiError::Type(text.trim().to_owned()))
163}
164
165fn params_at(text: &str, depth: usize) -> Option<Vec<Param>> {
166    let text = text.trim();
167    if text.is_empty() {
168        return Some(Vec::new());
169    }
170    split(text).into_iter().map(|one| param(one.trim(), depth)).collect()
171}
172
173/// A type, then any of `indexed` and the storage words, then a name.
174fn param(text: &str, depth: usize) -> Option<Param> {
175    let end = type_end(text);
176    let kind = kind_of(&text[..end], depth)?;
177    let mut name = None;
178    let mut indexed = false;
179    for word in text[end..].split_whitespace() {
180        match word {
181            "indexed" => indexed = true,
182            _ if MODIFIERS.contains(&word) => {}
183            _ if name.is_none() && is_name(word) => name = Some(word.to_owned()),
184            _ => return None,
185        }
186    }
187    Some(Param { name, kind, indexed })
188}
189
190fn is_name(word: &str) -> bool {
191    word.chars().all(|letter| letter.is_ascii_alphanumeric() || letter == '_' || letter == '$')
192}
193
194/// Where the type ends: the first space outside brackets and parentheses.
195fn type_end(text: &str) -> usize {
196    let mut depth = 0i32;
197    for (at, letter) in text.char_indices() {
198        match letter {
199            '(' | '[' => depth += 1,
200            ')' | ']' => depth -= 1,
201            _ if letter.is_whitespace() && depth == 0 => return at,
202            _ => {}
203        }
204    }
205    text.len()
206}
207
208fn depth_at(text: &str, at: usize) -> i32 {
209    text[..at].chars().fold(0, |depth, letter| match letter {
210        '(' | '[' => depth + 1,
211        ')' | ']' => depth - 1,
212        _ => depth,
213    })
214}
215
216fn kind_of(text: &str, depth: usize) -> Option<Kind> {
217    if depth > DEEPEST {
218        return None;
219    }
220    let text = text.trim();
221    if let Some(open) = text.rfind('[')
222        && text.ends_with(']')
223        && depth_at(text, open) == 0
224    {
225        let inner = kind_of(&text[..open], depth + 1)?;
226        let count = &text[open + 1..text.len() - 1];
227        return Some(match count.is_empty() {
228            true => Kind::Array(Box::new(inner)),
229            false => Kind::Sized(Box::new(inner), count.parse().ok().filter(|count| *count <= LONGEST)?),
230        });
231    }
232    if let Some(inside) = text.strip_prefix('(').and_then(|rest| rest.strip_suffix(')')) {
233        return params_at(inside, depth + 1).map(Kind::Tuple);
234    }
235    let bits = |digits: &str| -> Option<u16> {
236        match digits.is_empty() {
237            true => Some(256),
238            false => digits.parse().ok().filter(|bits| *bits > 0 && *bits <= 256 && bits % 8 == 0),
239        }
240    };
241    Some(match text {
242        "address" => Kind::Address,
243        "bool" => Kind::Bool,
244        "string" => Kind::String,
245        "bytes" => Kind::Bytes,
246        _ if text.starts_with("uint") => Kind::Uint(bits(&text[4..])?),
247        _ if text.starts_with("int") => Kind::Int(bits(&text[3..])?),
248        _ if text.starts_with("bytes") => {
249            let size: usize = text[5..].parse().ok()?;
250            (1..=32).contains(&size).then_some(Kind::Fixed(size))?
251        }
252        _ => return None,
253    })
254}
255
256/// Splits at the commas that are not inside brackets or parentheses.
257fn split(text: &str) -> Vec<&str> {
258    let mut parts = Vec::new();
259    let mut depth = 0i32;
260    let mut start = 0;
261    for (at, letter) in text.char_indices() {
262        match letter {
263            '(' | '[' => depth += 1,
264            ')' | ']' => depth -= 1,
265            ',' if depth == 0 => {
266                parts.push(&text[start..at]);
267                start = at + 1;
268            }
269            _ => {}
270        }
271    }
272    parts.push(&text[start..]);
273    parts
274}
275
276/// A function as Solidity or viem writes it: `transfer(address to, uint256
277/// amount) returns (bool)`, with or without `function` and its modifiers.
278#[derive(Debug, Clone, PartialEq, Eq)]
279pub struct Function {
280    pub name: String,
281    pub inputs: Vec<Param>,
282    pub outputs: Vec<Param>,
283}
284
285impl Function {
286    pub fn parse(text: &str) -> Result<Function, AbiError> {
287        let bad = || AbiError::Signature(text.trim().to_owned());
288        let (name, inside, rest) = signature_parts(text, "function").ok_or_else(bad)?;
289        let inputs = params(inside)?;
290        let outputs = match rest.find("returns") {
291            Some(at) => {
292                let after = rest[at + "returns".len()..].trim();
293                let inner = after.strip_prefix('(').and_then(|after| after.strip_suffix(')')).ok_or_else(bad)?;
294                params(inner)?
295            }
296            None => Vec::new(),
297        };
298        Ok(Function { name: name.to_owned(), inputs, outputs })
299    }
300
301    /// `name(t1,t2)`, what the selector hashes.
302    #[must_use]
303    pub fn signature(&self) -> String {
304        format!("{}{}", self.name, tuple_type(&self.inputs))
305    }
306
307    /// The four bytes that name the function: the start of `keccak256(signature)`.
308    #[must_use]
309    pub fn selector(&self) -> [u8; 4] {
310        let hash = keccak256(self.signature().as_bytes());
311        [hash[0], hash[1], hash[2], hash[3]]
312    }
313
314    /// The calldata of a call: the selector, then the arguments.
315    pub fn encode(&self, args: &[Token]) -> Result<Vec<u8>, AbiError> {
316        let mut out = self.selector().to_vec();
317        out.extend(encode(&self.inputs, args)?);
318        Ok(out)
319    }
320
321    /// A call's arguments back out of its calldata.
322    pub fn decode_input(&self, calldata: &[u8]) -> Result<Vec<Token>, AbiError> {
323        let found = calldata.get(..4).ok_or(AbiError::Short(calldata.len()))?;
324        if found != self.selector() {
325            return Err(AbiError::Selector {
326                wants: hex::encode_prefixed(&self.selector()),
327                found: hex::encode_prefixed(found),
328            });
329        }
330        decode(&self.inputs, &calldata[4..])
331    }
332
333    /// What the call answered, read against its declared outputs.
334    pub fn decode_output(&self, answer: &[u8]) -> Result<Vec<Token>, AbiError> {
335        decode(&self.outputs, answer)
336    }
337}
338
339/// `name`, what is inside its parentheses, and what follows them.
340fn signature_parts<'a>(text: &'a str, keyword: &str) -> Option<(&'a str, &'a str, &'a str)> {
341    let text = text.trim();
342    let text = text.strip_prefix(keyword).filter(|rest| rest.starts_with(char::is_whitespace)).unwrap_or(text).trim();
343    let open = text.find('(')?;
344    let name = text[..open].trim();
345    if name.is_empty() || !is_name(name) {
346        return None;
347    }
348    let mut depth = 0i32;
349    for (at, letter) in text[open..].char_indices() {
350        match letter {
351            '(' => depth += 1,
352            ')' => {
353                depth -= 1;
354                if depth == 0 {
355                    let close = open + at;
356                    return Some((name, &text[open + 1..close], &text[close + 1..]));
357                }
358            }
359            _ => {}
360        }
361    }
362    None
363}
364
365/// The selector of a function signature in any spelling the docs use.
366pub fn selector(signature: &str) -> Result<[u8; 4], AbiError> {
367    Function::parse(signature).map(|function| function.selector())
368}
369
370/// The first topic an event is logged under: `keccak256(name(t1,t2))`.
371pub fn event_topic(signature: &str) -> Result<B256, AbiError> {
372    let (name, inside, _) =
373        signature_parts(signature, "event").ok_or_else(|| AbiError::Signature(signature.trim().to_owned()))?;
374    let canonical = format!("{name}{}", tuple_type(&params(inside)?));
375    Ok(B256(keccak256(canonical.as_bytes())))
376}
377
378/// `abi.encode(values...)`: heads, then the tails they point into. Each value
379/// is checked against its type first.
380pub fn encode(params: &[Param], tokens: &[Token]) -> Result<Vec<u8>, AbiError> {
381    if params.len() != tokens.len() {
382        return Err(AbiError::Count { wants: params.len(), got: tokens.len() });
383    }
384    for (param, token) in params.iter().zip(tokens) {
385        if !fits(&param.kind, token) {
386            return Err(AbiError::Mismatch { kind: param.kind.canonical(), token: token.describe() });
387        }
388    }
389    let kinds: Vec<&Kind> = params.iter().map(|param| &param.kind).collect();
390    Ok(sequence(&kinds, tokens))
391}
392
393/// Whether `token` is a value of `kind`, its integers within their width.
394fn fits(kind: &Kind, token: &Token) -> bool {
395    match (kind, token) {
396        (Kind::Uint(bits), Token::Uint(value)) => value.bits() <= u32::from(*bits),
397        (Kind::Int(bits), Token::Int(value)) => sign_extended(&value.to_be_bytes(), *bits),
398        (Kind::Address, Token::Address(_))
399        | (Kind::Bool, Token::Bool(_))
400        | (Kind::String, Token::String(_))
401        | (Kind::Bytes, Token::Bytes(_)) => true,
402        (Kind::Fixed(size), Token::Fixed(bytes)) => bytes.len() == *size,
403        (Kind::Array(inner), Token::Array(items)) => items.iter().all(|item| fits(inner, item)),
404        (Kind::Sized(inner, count), Token::Array(items)) => {
405            items.len() == *count && items.iter().all(|item| fits(inner, item))
406        }
407        (Kind::Tuple(params), Token::Tuple(items)) => {
408            params.len() == items.len() && params.iter().zip(items).all(|(param, item)| fits(&param.kind, item))
409        }
410        _ => false,
411    }
412}
413
414/// Whether a two's complement word is the sign extension of its low `bits`.
415fn sign_extended(word: &[u8; WORD], bits: u16) -> bool {
416    let spare = WORD - usize::from(bits) / 8;
417    if spare == 0 {
418        return true;
419    }
420    let fill = if word[spare] & 0x80 == 0 { 0x00 } else { 0xff };
421    word[..spare].iter().all(|byte| *byte == fill)
422}
423
424fn sequence(kinds: &[&Kind], tokens: &[Token]) -> Vec<u8> {
425    let heads: usize = kinds.iter().map(|kind| kind.head()).sum();
426    let mut head = Vec::with_capacity(heads);
427    let mut tail = Vec::new();
428    for (kind, token) in kinds.iter().zip(tokens) {
429        let encoded = one(kind, token);
430        match kind.is_dynamic() {
431            true => {
432                head.extend_from_slice(&word_of(heads + tail.len()));
433                tail.extend(encoded);
434            }
435            false => head.extend(encoded),
436        }
437    }
438    head.extend(tail);
439    head
440}
441
442/// One value checked by [`fits`]: its kind and token agree.
443fn one(kind: &Kind, token: &Token) -> Vec<u8> {
444    match (kind, token) {
445        (_, Token::Uint(value) | Token::Int(value)) => value.to_be_bytes().to_vec(),
446        (_, Token::Address(address)) => B256::from_address(*address).0.to_vec(),
447        (_, Token::Bool(value)) => word_of(usize::from(*value)).to_vec(),
448        (_, Token::String(text)) => packed(text.as_bytes()),
449        (_, Token::Bytes(bytes)) => packed(bytes),
450        (_, Token::Fixed(bytes)) => padded(bytes),
451        (Kind::Array(inner), Token::Array(items)) => {
452            let mut out = word_of(items.len()).to_vec();
453            out.extend(sequence(&vec![inner.as_ref(); items.len()], items));
454            out
455        }
456        (Kind::Sized(inner, _), Token::Array(items)) => sequence(&vec![inner.as_ref(); items.len()], items),
457        (Kind::Tuple(params), Token::Tuple(items)) => {
458            let kinds: Vec<&Kind> = params.iter().map(|param| &param.kind).collect();
459            sequence(&kinds, items)
460        }
461        (_, Token::Array(items) | Token::Tuple(items)) => sequence(&vec![kind; items.len()], items),
462    }
463}
464
465fn packed(bytes: &[u8]) -> Vec<u8> {
466    let mut out = word_of(bytes.len()).to_vec();
467    out.extend(padded(bytes));
468    out
469}
470
471fn padded(bytes: &[u8]) -> Vec<u8> {
472    let mut out = bytes.to_vec();
473    out.resize(bytes.len().div_ceil(WORD) * WORD, 0);
474    out
475}
476
477fn word_of(value: usize) -> [u8; WORD] {
478    U256::from_u64(value as u64).to_be_bytes()
479}
480
481/// `abi.decode(data, (types...))`, each word checked against its declared width.
482pub fn decode(params: &[Param], data: &[u8]) -> Result<Vec<Token>, AbiError> {
483    let kinds: Vec<&Kind> = params.iter().map(|param| &param.kind).collect();
484    unsequence(&kinds, data, 0)
485}
486
487fn unsequence(kinds: &[&Kind], data: &[u8], start: usize) -> Result<Vec<Token>, AbiError> {
488    let mut at = start;
489    let mut tokens = Vec::with_capacity(kinds.len().min(LONGEST / WORD));
490    for kind in kinds {
491        match kind.is_dynamic() {
492            true => {
493                let offset = length(data, at)?;
494                tokens.push(unone(kind, data, start + offset)?);
495                at += WORD;
496            }
497            false => {
498                tokens.push(unone(kind, data, at)?);
499                at += kind.head();
500            }
501        }
502    }
503    Ok(tokens)
504}
505
506fn word(data: &[u8], at: usize) -> Result<[u8; WORD], AbiError> {
507    data.get(at..at.saturating_add(WORD)).and_then(|slice| slice.try_into().ok()).ok_or(AbiError::Short(data.len()))
508}
509
510/// A length or an offset: small, or refused.
511fn length(data: &[u8], at: usize) -> Result<usize, AbiError> {
512    let value = U256::from_be_bytes(word(data, at)?);
513    value
514        .to_u64()
515        .and_then(|value| usize::try_from(value).ok())
516        .filter(|value| *value <= LONGEST)
517        .ok_or_else(|| AbiError::Misfit { at, kind: "a length".to_owned() })
518}
519
520fn unone(kind: &Kind, data: &[u8], at: usize) -> Result<Token, AbiError> {
521    let misfit = || AbiError::Misfit { at, kind: kind.canonical() };
522    Ok(match kind {
523        Kind::Uint(bits) => {
524            let value = U256::from_be_bytes(word(data, at)?);
525            if value.bits() > u32::from(*bits) {
526                return Err(misfit());
527            }
528            Token::Uint(value)
529        }
530        Kind::Int(bits) => {
531            let word = word(data, at)?;
532            if !sign_extended(&word, *bits) {
533                return Err(misfit());
534            }
535            Token::Int(U256::from_be_bytes(word))
536        }
537        Kind::Address => B256(word(data, at)?).to_address().map(Token::Address).ok_or_else(misfit)?,
538        Kind::Bool => match U256::from_be_bytes(word(data, at)?).to_u64() {
539            Some(0) => Token::Bool(false),
540            Some(1) => Token::Bool(true),
541            _ => return Err(misfit()),
542        },
543        Kind::Fixed(size) => {
544            let word = word(data, at)?;
545            if word[*size..].iter().any(|byte| *byte != 0) {
546                return Err(misfit());
547            }
548            Token::Fixed(word[..*size].to_vec())
549        }
550        Kind::String | Kind::Bytes => {
551            let length = length(data, at)?;
552            let start = at + WORD;
553            let bytes = data.get(start..start + length).ok_or(AbiError::Short(data.len()))?.to_vec();
554            match kind {
555                Kind::String => Token::String(String::from_utf8(bytes).map_err(|_| misfit())?),
556                _ => Token::Bytes(bytes),
557            }
558        }
559        Kind::Array(inner) => {
560            let count = length(data, at)?;
561            if count.saturating_mul(inner.head().max(1)) > data.len() {
562                return Err(AbiError::Short(data.len()));
563            }
564            Token::Array(unsequence(&vec![inner.as_ref(); count], data, at + WORD)?)
565        }
566        Kind::Sized(inner, count) => {
567            if count.saturating_mul(inner.head().max(1)) > data.len() {
568                return Err(AbiError::Short(data.len()));
569            }
570            Token::Array(unsequence(&vec![inner.as_ref(); *count], data, at)?)
571        }
572        Kind::Tuple(params) => {
573            let kinds: Vec<&Kind> = params.iter().map(|param| &param.kind).collect();
574            Token::Tuple(unsequence(&kinds, data, at)?)
575        }
576    })
577}
578
579impl Token {
580    #[must_use]
581    pub fn uint(value: impl Into<U256>) -> Token {
582        Token::Uint(value.into())
583    }
584
585    #[must_use]
586    pub fn int(value: i128) -> Token {
587        let magnitude = U256::from_u128(value.unsigned_abs());
588        Token::Int(match value < 0 {
589            true => negated(magnitude),
590            false => magnitude,
591        })
592    }
593
594    #[must_use]
595    pub fn address(address: Address) -> Token {
596        Token::Address(address)
597    }
598
599    /// A typed value read into this kind: decimal for integers, `0x` hex for
600    /// addresses and bytes, `true` or `false`, and `[a, b]` or `(a, b)` for
601    /// the containers. `name` is what a refusal calls the field.
602    pub fn parse(kind: &Kind, name: &str, text: &str) -> Result<Token, AbiError> {
603        let text = text.trim();
604        let refused = || AbiError::Value { name: name.to_owned(), wants: kind.wants(), got: text.to_owned() };
605        Ok(match kind {
606            Kind::Uint(bits) => {
607                let value = U256::from_decimal(text).map_err(|_| refused())?;
608                if value.bits() > u32::from(*bits) {
609                    return Err(refused());
610                }
611                Token::Uint(value)
612            }
613            Kind::Int(bits) => {
614                let (negative, digits) = match text.strip_prefix('-') {
615                    Some(rest) => (true, rest),
616                    None => (false, text),
617                };
618                let magnitude = U256::from_decimal(digits).map_err(|_| refused())?;
619                // One bit is the sign: a magnitude below 2^(bits-1), or exactly
620                // that when it is negative.
621                let room = u32::from(*bits) - 1;
622                let edge = magnitude.bits() == room + 1 && magnitude == power_of_two(room);
623                if magnitude.bits() > room && !(negative && edge) {
624                    return Err(refused());
625                }
626                Token::Int(match negative {
627                    true => negated(magnitude),
628                    false => magnitude,
629                })
630            }
631            Kind::Address => Token::Address(text.parse().map_err(|_| refused())?),
632            Kind::Bool => match text.to_ascii_lowercase().as_str() {
633                "true" => Token::Bool(true),
634                "false" => Token::Bool(false),
635                _ => return Err(refused()),
636            },
637            Kind::String => Token::String(text.to_owned()),
638            Kind::Bytes => Token::Bytes(hex_of(text).ok_or_else(refused)?),
639            Kind::Fixed(size) => Token::Fixed(hex_of(text).filter(|bytes| bytes.len() == *size).ok_or_else(refused)?),
640            Kind::Array(inner) | Kind::Sized(inner, _) => {
641                let inside = text.strip_prefix('[').and_then(|rest| rest.strip_suffix(']')).ok_or_else(refused)?;
642                let items: Vec<&str> = match inside.trim().is_empty() {
643                    true => Vec::new(),
644                    false => split(inside),
645                };
646                if let Kind::Sized(_, count) = kind
647                    && items.len() != *count
648                {
649                    return Err(refused());
650                }
651                Token::Array(items.iter().map(|item| Token::parse(inner, name, item)).collect::<Result<_, _>>()?)
652            }
653            Kind::Tuple(params) => {
654                let inside = text.strip_prefix('(').and_then(|rest| rest.strip_suffix(')')).ok_or_else(refused)?;
655                let items = split(inside);
656                if items.len() != params.len() {
657                    return Err(refused());
658                }
659                Token::Tuple(
660                    params
661                        .iter()
662                        .zip(items)
663                        .map(|(param, item)| Token::parse(&param.kind, param.name.as_deref().unwrap_or(name), item))
664                        .collect::<Result<_, _>>()?,
665                )
666            }
667        })
668    }
669
670    /// The value as a person reads it: decimal integers, `0x` hex, and the
671    /// containers in brackets, a tuple's fields named where `kind` names them.
672    #[must_use]
673    pub fn show(&self, kind: &Kind) -> String {
674        match (self, kind) {
675            (Token::Uint(value), _) => value.to_string(),
676            (Token::Int(value), _) => signed(*value),
677            (Token::Address(address), _) => address.to_hex(),
678            (Token::Bool(value), _) => value.to_string(),
679            (Token::String(text), _) => text.clone(),
680            (Token::Bytes(bytes) | Token::Fixed(bytes), _) => hex::encode_prefixed(bytes),
681            (Token::Array(items), Kind::Array(inner) | Kind::Sized(inner, _)) => {
682                format!("[{}]", items.iter().map(|item| item.show(inner)).collect::<Vec<_>>().join(", "))
683            }
684            (Token::Tuple(items), Kind::Tuple(params)) => format!(
685                "{{{}}}",
686                items
687                    .iter()
688                    .zip(params)
689                    .map(|(item, param)| match &param.name {
690                        Some(name) => format!("{name}: {}", item.show(&param.kind)),
691                        None => item.show(&param.kind),
692                    })
693                    .collect::<Vec<_>>()
694                    .join(", ")
695            ),
696            (Token::Array(items) | Token::Tuple(items), _) => {
697                format!("[{}]", items.iter().map(|item| item.show(kind)).collect::<Vec<_>>().join(", "))
698            }
699        }
700    }
701
702    /// A short name of the value, for a refusal.
703    fn describe(&self) -> String {
704        match self {
705            Token::Uint(value) => format!("the number {value}"),
706            Token::Int(value) => format!("the number {}", signed(*value)),
707            Token::Address(address) => format!("the address {address}"),
708            Token::Bool(value) => format!("{value}"),
709            Token::String(_) => "a string".to_owned(),
710            Token::Bytes(bytes) => format!("{} bytes", bytes.len()),
711            Token::Fixed(bytes) => format!("{} fixed bytes", bytes.len()),
712            Token::Array(items) => format!("a list of {}", items.len()),
713            Token::Tuple(items) => format!("a tuple of {}", items.len()),
714        }
715    }
716
717    #[must_use]
718    pub fn as_u256(&self) -> Option<U256> {
719        match self {
720            Token::Uint(value) => Some(*value),
721            _ => None,
722        }
723    }
724
725    #[must_use]
726    pub fn as_u128(&self) -> Option<u128> {
727        self.as_u256().and_then(U256::to_u128)
728    }
729
730    #[must_use]
731    pub fn as_u64(&self) -> Option<u64> {
732        self.as_u256().and_then(U256::to_u64)
733    }
734
735    #[must_use]
736    pub fn as_u32(&self) -> Option<u32> {
737        self.as_u64().and_then(|value| u32::try_from(value).ok())
738    }
739
740    #[must_use]
741    pub fn as_u16(&self) -> Option<u16> {
742        self.as_u64().and_then(|value| u16::try_from(value).ok())
743    }
744
745    #[must_use]
746    pub fn as_u8(&self) -> Option<u8> {
747        self.as_u64().and_then(|value| u8::try_from(value).ok())
748    }
749
750    /// A signed integer, while it fits an `i128`.
751    #[must_use]
752    pub fn as_i128(&self) -> Option<i128> {
753        let Token::Int(value) = self else { return None };
754        match value.bits() == 256 {
755            false => value.to_u128().and_then(|value| i128::try_from(value).ok()),
756            true => {
757                let magnitude = negated(*value).to_u128()?;
758                match magnitude == i128::MIN.unsigned_abs() {
759                    true => Some(i128::MIN),
760                    false => i128::try_from(magnitude).ok().map(|magnitude| -magnitude),
761                }
762            }
763        }
764    }
765
766    #[must_use]
767    pub fn as_i64(&self) -> Option<i64> {
768        self.as_i128().and_then(|value| i64::try_from(value).ok())
769    }
770
771    #[must_use]
772    pub fn as_i8(&self) -> Option<i8> {
773        self.as_i128().and_then(|value| i8::try_from(value).ok())
774    }
775
776    #[must_use]
777    pub fn as_address(&self) -> Option<Address> {
778        match self {
779            Token::Address(address) => Some(*address),
780            _ => None,
781        }
782    }
783
784    #[must_use]
785    pub fn as_bool(&self) -> Option<bool> {
786        match self {
787            Token::Bool(value) => Some(*value),
788            _ => None,
789        }
790    }
791
792    #[must_use]
793    pub fn as_str(&self) -> Option<&str> {
794        match self {
795            Token::String(text) => Some(text),
796            _ => None,
797        }
798    }
799
800    /// The bytes of a `bytes` or a `bytesN`.
801    #[must_use]
802    pub fn as_bytes(&self) -> Option<&[u8]> {
803        match self {
804            Token::Bytes(bytes) | Token::Fixed(bytes) => Some(bytes),
805            _ => None,
806        }
807    }
808
809    /// The items of an array or the fields of a tuple.
810    #[must_use]
811    pub fn as_items(&self) -> Option<&[Token]> {
812        match self {
813            Token::Array(items) | Token::Tuple(items) => Some(items),
814            _ => None,
815        }
816    }
817}
818
819/// `-value` in two's complement: `2^256 - value`, and zero for zero.
820fn negated(value: U256) -> U256 {
821    match value.checked_sub(U256::ONE) {
822        Some(less) => U256::MAX.checked_sub(less).unwrap_or(U256::ZERO),
823        None => U256::ZERO,
824    }
825}
826
827fn power_of_two(exponent: u32) -> U256 {
828    let mut word = [0u8; WORD];
829    let at = WORD - 1 - (exponent / 8) as usize;
830    word[at] = 1 << (exponent % 8);
831    U256::from_be_bytes(word)
832}
833
834/// A two's complement word in decimal, with its sign.
835fn signed(value: U256) -> String {
836    match value.bits() == 256 {
837        true => format!("-{}", negated(value)),
838        false => value.to_string(),
839    }
840}
841
842fn hex_of(text: &str) -> Option<Vec<u8>> {
843    text.strip_prefix("0x").or_else(|| text.strip_prefix("0X"))?;
844    hex::decode(text).ok()
845}
846
847#[cfg(test)]
848#[path = "tests/abi.rs"]
849mod tests;