etk_4byte/
lib.rs

1//! EVM Toolkit Function Selector Database.
2//!
3//! To roughly quote [4byte.directory](https://www.4byte.directory):
4//!
5//! > Function calls in the Ethereum Virtual Machine are specified by the first
6//! > four bytes of data sent with a transaction. These function selectors are
7//! > defined as the first four bytes of the Keccak-256 hash of the canonical
8//! > representation of the function signature. Since this is a one-way
9//! > operation, it is not possible to derive the human-readable representation
10//! > of the function (signature) from the four byte selector. This database is
11//! > meant to allow mapping those bytes signatures back to their
12//! > human-readable versions.
13#![deny(unsafe_code)]
14#![deny(missing_docs)]
15#![deny(unreachable_pub)]
16#![deny(missing_debug_implementations)]
17
18use lazy_static::lazy_static;
19
20use std::collections::BTreeMap;
21use std::convert::TryFrom;
22
23const PACKED: &[u8] = include_bytes!("database.br");
24
25lazy_static! {
26    static ref SIGNATURES: (BTreeMap<u32, u32>, Vec<Vec<String>>) = {
27        let mut input = brotli::Decompressor::new(PACKED, 4096);
28        bincode::deserialize_from(&mut input).unwrap()
29    };
30}
31
32/// Attempt to retrieve the human-readable signature given a selector.
33///
34/// ## Example
35///
36/// ```
37/// use etk_4byte::reverse_selector;
38///
39/// let signatures: Vec<_> = reverse_selector(0x3bb2dead).collect();
40///
41/// assert_eq!(signatures[0], "initialFundsReleaseNumerator()");
42/// assert_eq!(signatures[1], "resolveAddressLight(address)");
43/// ```
44pub fn reverse_selector(selector: u32) -> impl Iterator<Item = &'static str> {
45    SIGNATURES
46        .0
47        .get(&selector)
48        .map(|v| usize::try_from(*v).unwrap())
49        .map(|v| SIGNATURES.1[v].iter())
50        .unwrap_or_else(|| [].iter())
51        .map(String::as_str)
52}