foundry_evm_abi/console/
hardhat.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
use alloy_primitives::{map::HashMap, Selector};
use alloy_sol_types::sol;
use foundry_common_fmt::*;
use foundry_macros::ConsoleFmt;
use std::sync::LazyLock;

sol!(
    #[sol(abi)]
    #[derive(ConsoleFmt)]
    HardhatConsole,
    "src/HardhatConsole.json"
);

/// Patches the given Hardhat `console` function selector to its ABI-normalized form.
///
/// See [`HARDHAT_CONSOLE_SELECTOR_PATCHES`] for more details.
pub fn patch_hh_console_selector(input: &mut [u8]) {
    if let Some(selector) = hh_console_selector(input) {
        input[..4].copy_from_slice(selector.as_slice());
    }
}

/// Returns the ABI-normalized selector for the given Hardhat `console` function selector.
///
/// See [`HARDHAT_CONSOLE_SELECTOR_PATCHES`] for more details.
pub fn hh_console_selector(input: &[u8]) -> Option<&'static Selector> {
    if let Some(selector) = input.get(..4) {
        let selector: &[u8; 4] = selector.try_into().unwrap();
        HARDHAT_CONSOLE_SELECTOR_PATCHES.get(selector).map(Into::into)
    } else {
        None
    }
}

/// Maps all the `hardhat/console.log` log selectors that use the legacy ABI (`int`, `uint`) to
/// their normalized counterparts (`int256`, `uint256`).
///
/// `hardhat/console.log` logs its events manually, and in functions that accept integers they're
/// encoded as `abi.encodeWithSignature("log(int)", p0)`, which is not the canonical ABI encoding
/// for `int` that Solidity and [`sol!`] use.
pub static HARDHAT_CONSOLE_SELECTOR_PATCHES: LazyLock<HashMap<[u8; 4], [u8; 4]>> =
    LazyLock::new(|| HashMap::from_iter(include!("./patches.rs")));

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

    #[test]
    fn hardhat_console_patch() {
        for (hh, generated) in HARDHAT_CONSOLE_SELECTOR_PATCHES.iter() {
            let mut hh = *hh;
            patch_hh_console_selector(&mut hh);
            assert_eq!(hh, *generated);
        }
    }
}