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);
}
}
}