Skip to content

Commit

Permalink
feat(forge create): read calldata from file (gakonst#674)
Browse files Browse the repository at this point in the history
* feat(forge create): read calldata from file

It is possible to create a transaction where the
calldata is too large to be passed via `argv`.
See https://wiki.debian.org/CommonErrorMessages/ArgumentListTooLong
for more information on this limitation. To make it
possible to create these large transactions, update
`forge create` so that it can read the calldata
from a file.

A new cli argument is added `--constructor-args-path`
that conflicts with `--constructor-args`. This new
argument should point to a file on the filesystem
that contains a whitespace delimited list of
constructor arguments.

* refactor out `mut`

Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>

* Update cli/src/cmd/create.rs

Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>

* fix: get compiling

* chore: fmt with latest nightly

* chore: clippy lints

Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>
  • Loading branch information
tynes and gakonst authored Feb 6, 2022
1 parent acb5cd4 commit d7f81c4
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 22 deletions.
44 changes: 38 additions & 6 deletions cli/src/cmd/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,32 @@ use ethers::{

use eyre::Result;
use foundry_utils::parse_tokens;
use std::fs;

use crate::opts::forge::ContractInfo;
use clap::Parser;
use std::sync::Arc;
use clap::{Parser, ValueHint};
use std::{path::PathBuf, sync::Arc};

#[derive(Debug, Clone, Parser)]
pub struct CreateArgs {
#[clap(long, multiple_values = true, help = "constructor args calldata arguments.")]
#[clap(
long,
multiple_values = true,
help = "constructor args calldata arguments",
name = "constructor_args",
conflicts_with = "constructor_args_path"
)]
constructor_args: Vec<String>,

#[clap(
long,
help = "path to a file containing the constructor args",
value_hint = ValueHint::FilePath,
name = "constructor_args_path",
conflicts_with = "constructor_args",
)]
constructor_args_path: Option<PathBuf>,

#[clap(flatten)]
opts: BuildArgs,

Expand Down Expand Up @@ -57,7 +73,19 @@ impl Cmd for CreateArgs {
// Add arguments to constructor
let provider = Provider::<Http>::try_from(self.eth.rpc_url()?)?;
let params = match abi.constructor {
Some(ref v) => self.parse_constructor_args(v)?,
Some(ref v) => {
let constructor_args =
if let Some(ref constructor_args_path) = self.constructor_args_path {
if !std::path::Path::new(&constructor_args_path).exists() {
eyre::bail!("constructor args path not found");
}
let file = fs::read_to_string(constructor_args_path)?;
file.split(' ').map(|s| s.to_string()).collect::<Vec<String>>()
} else {
self.constructor_args.clone()
};
self.parse_constructor_args(v, &constructor_args)?
}
None => vec![],
};

Expand Down Expand Up @@ -117,11 +145,15 @@ impl CreateArgs {
Ok(())
}

fn parse_constructor_args(&self, constructor: &Constructor) -> Result<Vec<Token>> {
fn parse_constructor_args(
&self,
constructor: &Constructor,
constructor_args: &[String],
) -> Result<Vec<Token>> {
let params = constructor
.inputs
.iter()
.zip(&self.constructor_args)
.zip(constructor_args)
.map(|(input, arg)| (&input.kind, arg.as_str()))
.collect::<Vec<_>>();

Expand Down
53 changes: 40 additions & 13 deletions cli/src/opts/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,14 @@ pub enum Subcommands {
#[clap(aliases = &["--from-ascii"])]
#[clap(name = "--from-utf8")]
#[clap(about = "convert text data into hexdata")]
FromUtf8 { text: Option<String> },
FromUtf8 {
text: Option<String>,
},
#[clap(name = "--to-hex")]
#[clap(about = "convert a decimal number into hex")]
ToHex { decimal: Option<String> },
ToHex {
decimal: Option<String>,
},
#[clap(name = "--to-hexdata")]
#[clap(about = r#"[<hex>|</path>|<@tag>]
Output lowercase, 0x-prefixed hex, converting from the
Expand All @@ -37,14 +41,20 @@ pub enum Subcommands {
- absolute path to file
- @tag, where $TAG is defined in environment variables
"#)]
ToHexdata { input: Option<String> },
ToHexdata {
input: Option<String>,
},
#[clap(aliases = &["--to-checksum"])] // Compatibility with dapptools' cast
#[clap(name = "--to-checksum-address")]
#[clap(about = "convert an address to a checksummed format (EIP-55)")]
ToCheckSumAddress { address: Option<Address> },
ToCheckSumAddress {
address: Option<Address>,
},
#[clap(name = "--to-ascii")]
#[clap(about = "convert hex data to text data")]
ToAscii { hexdata: Option<String> },
ToAscii {
hexdata: Option<String>,
},
#[clap(name = "--to-bytes32")]
#[clap(about = "left-pads a hex bytes string to 32 bytes)")]
#[clap(name = "--from-fix")]
Expand All @@ -54,10 +64,14 @@ pub enum Subcommands {
#[clap(allow_hyphen_values = true)] // negative values not yet supported internally
value: Option<String>,
},
ToBytes32 { bytes: Option<String> },
ToBytes32 {
bytes: Option<String>,
},
#[clap(name = "--to-dec")]
#[clap(about = "convert hex value into decimal number")]
ToDec { hexvalue: Option<String> },
ToDec {
hexvalue: Option<String>,
},
#[clap(name = "--to-fix")]
#[clap(about = "convert integers into fixed point with specified decimals")]
ToFix {
Expand All @@ -67,10 +81,14 @@ pub enum Subcommands {
},
#[clap(name = "--to-uint256")]
#[clap(about = "convert a number into uint256 hex string with 0x prefix")]
ToUint256 { value: Option<String> },
ToUint256 {
value: Option<String>,
},
#[clap(name = "--to-int256")]
#[clap(about = "convert a number into int256 hex string with 0x prefix")]
ToInt256 { value: Option<String> },
ToInt256 {
value: Option<String>,
},
#[clap(name = "--to-unit")]
#[clap(
about = r#"convert an ETH amount into a specified unit: ether, gwei or wei (default: wei).
Expand All @@ -82,7 +100,10 @@ pub enum Subcommands {
- 1gwei ether | converts 1 gwei to ether
"#
)]
ToUnit { value: Option<String>, unit: Option<String> },
ToUnit {
value: Option<String>,
unit: Option<String>,
},
#[clap(name = "--to-wei")]
#[clap(about = "convert an ETH amount into wei. Consider using --to-unit.")]
ToWei {
Expand Down Expand Up @@ -162,7 +183,9 @@ pub enum Subcommands {
},
#[clap(name = "namehash")]
#[clap(about = "returns ENS namehash of provided name")]
Namehash { name: String },
Namehash {
name: String,
},
#[clap(name = "tx")]
#[clap(about = "Show information about the transaction <tx-hash>")]
Tx {
Expand Down Expand Up @@ -307,7 +330,9 @@ pub enum Subcommands {
id: Option<String>,
},
#[clap(name = "4byte-event")]
#[clap(about = "Takes a 32 byte topic and prints the response from querying 4byte.directory for that topic")]
#[clap(
about = "Takes a 32 byte topic and prints the response from querying 4byte.directory for that topic"
)]
FourByteEvent {
#[clap(help = "the 32 byte topic")]
topic: String,
Expand Down Expand Up @@ -356,7 +381,9 @@ pub enum Subcommands {
},
#[clap(name = "keccak")]
#[clap(about = "Keccak-256 hashes arbitrary data")]
Keccak { data: String },
Keccak {
data: String,
},
#[clap(name = "resolve-name")]
#[clap(about = "Returns the address the provided ENS name resolves to")]
ResolveName {
Expand Down
12 changes: 9 additions & 3 deletions utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ pub async fn fourbyte_event(topic: &str) -> Result<Vec<(String, i32)>> {

let topic = &topic.strip_prefix("0x").unwrap_or(topic);
if topic.len() < 64 {
return Err(eyre::eyre!("Invalid topic"));
return Err(eyre::eyre!("Invalid topic"))
}
let topic = &topic[..8];

Expand Down Expand Up @@ -979,11 +979,17 @@ mod tests {

#[tokio::test]
async fn test_fourbyte_event() {
let sigs = fourbyte_event("0x7e1db2a1cd12f0506ecd806dba508035b290666b84b096a87af2fd2a1516ede6").await.unwrap();
let sigs =
fourbyte_event("0x7e1db2a1cd12f0506ecd806dba508035b290666b84b096a87af2fd2a1516ede6")
.await
.unwrap();
assert_eq!(sigs[0].0, "updateAuthority(address,uint8)".to_string());
assert_eq!(sigs[0].1, 79573);

let sigs = fourbyte_event("0xb7009613e63fb13fd59a2fa4c206a992c1f090a44e5d530be255aa17fed0b3dd").await.unwrap();
let sigs =
fourbyte_event("0xb7009613e63fb13fd59a2fa4c206a992c1f090a44e5d530be255aa17fed0b3dd")
.await
.unwrap();
assert_eq!(sigs[0].0, "canCall(address,address,bytes4)".to_string());
}

Expand Down

0 comments on commit d7f81c4

Please sign in to comment.