Skip to content

Commit

Permalink
feat(cast): abi-encode-packed
Browse files Browse the repository at this point in the history
  • Loading branch information
bernard-wagner committed Feb 16, 2024
1 parent dbd7fe1 commit 22c10aa
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 4 deletions.
8 changes: 6 additions & 2 deletions crates/cast/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,12 @@ async fn main() -> Result<()> {
let tokens = format_tokens(&tokens);
tokens.for_each(|t| println!("{t}"));
}
CastSubcommand::AbiEncode { sig, args } => {
println!("{}", SimpleCast::abi_encode(&sig, &args)?);
CastSubcommand::AbiEncode { sig, packed, args } => {
if !packed {
println!("{}", SimpleCast::abi_encode(&sig, &args)?);
} else {
println!("{}", SimpleCast::abi_encode_packed(&sig, &args)?);
}
}
CastSubcommand::CalldataDecode { sig, calldata } => {
let tokens = SimpleCast::calldata_decode(&sig, &calldata, true)?;
Expand Down
4 changes: 4 additions & 0 deletions crates/cast/bin/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,10 @@ pub enum CastSubcommand {
/// The function signature.
sig: String,

/// Whether to use packed encoding.
#[clap(long)]
packed: bool,

/// The arguments of the function.
#[clap(allow_hyphen_values = true)]
args: Vec<String>,
Expand Down
32 changes: 32 additions & 0 deletions crates/cast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ use std::{
use tokio::signal::ctrl_c;
use tx::{TxBuilderOutput, TxBuilderPeekOutput};

use foundry_common::abi::encode_function_args_packed;
pub use foundry_evm::*;
pub use rusoto_core::{
credential::ChainProvider as AwsChainProvider, region::Region as AwsRegion,
Expand Down Expand Up @@ -1551,6 +1552,37 @@ impl SimpleCast {
Ok(format!("0x{encoded}"))
}

/// Performs packed ABI encoding based off of the function signature or tuple.
///
/// # Examplez
///
/// ```
/// use cast::SimpleCast as Cast;
///
/// assert_eq!(
/// "0x0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000012c00000000000000c8",
/// Cast::abi_encode_packed("(uint128[] a, uint64 b)", &["[100, 300]", "200"]).unwrap().as_str()
/// );
///
/// assert_eq!(
/// "0x8dbd1b711dc621e1404633da156fcc779e1c6f3e68656c6c6f20776f726c64",
/// Cast::abi_encode_packed("foo(address a, string b)", &["0x8dbd1b711dc621e1404633da156fcc779e1c6f3e", "hello world"]).unwrap().as_str()
/// );
/// # Ok::<_, eyre::Report>(())
/// ```
pub fn abi_encode_packed(sig: &str, args: &[impl AsRef<str>]) -> Result<String> {
// If the signature is a tuple, we need to prefix it to make it a function
let sig =
if sig.trim_start().starts_with('(') { format!("foo{sig}") } else { sig.to_string() };

let func = get_func(sig.as_str())?;
let encoded = match encode_function_args_packed(&func, args) {
Ok(res) => hex::encode(res),
Err(e) => eyre::bail!("Could not ABI encode the function and arguments. Did you pass in the right types?\nError\n{}", e),
};
Ok(format!("0x{encoded}"))
}

/// Performs ABI encoding to produce the hexadecimal calldata with the given arguments.
///
/// # Example
Expand Down
17 changes: 17 additions & 0 deletions crates/common/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,23 @@ where
func.abi_encode_input(params.as_slice()).map_err(Into::into)
}

/// Given a function and a vector of string arguments, it proceeds to convert the args to alloy
/// [DynSolValue]s and encode them using the packed encoding.
pub fn encode_function_args_packed<I, S>(func: &Function, args: I) -> Result<Vec<u8>>
where
I: IntoIterator<Item = S>,
S: AsRef<str>,
{
let params: Vec<Vec<u8>> = std::iter::zip(&func.inputs, args)
.map(|(input, arg)| coerce_value(&input.selector_type(), arg.as_ref()))
.collect::<Result<Vec<_>>>()?
.into_iter()
.map(|v| v.abi_encode_packed())
.collect();

Ok(params.concat())
}

/// Decodes the calldata of the function
pub fn abi_decode_calldata(
sig: &str,
Expand Down
4 changes: 2 additions & 2 deletions crates/forge/src/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ impl<'a> ContractRunner<'a> {
if !span.is_disabled() {
let sig = &func.signature()[..];
if enabled!(tracing::Level::TRACE) {
span.record("sig", &sig);
span.record("sig", sig);
} else {
span.record("sig", sig.split('(').next().unwrap());
}
Expand Down Expand Up @@ -578,7 +578,7 @@ impl<'a> ContractRunner<'a> {
if !span.is_disabled() {
let sig = &func.signature()[..];
if enabled!(tracing::Level::TRACE) {
span.record("test", &sig);
span.record("test", sig);
} else {
span.record("test", sig.split('(').next().unwrap());
}
Expand Down

0 comments on commit 22c10aa

Please sign in to comment.