Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions crates/cast/src/cmd/mktx.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::tx::{self, CastTxBuilder};
use alloy_ens::NameOrAddress;
use alloy_network::{EthereumWallet, TransactionBuilder, eip2718::Encodable2718};
use alloy_primitives::hex;
use alloy_primitives::{Address, hex};
use alloy_provider::Provider;
use alloy_signer::Signer;
use clap::Parser;
use eyre::{OptionExt, Result};
use eyre::Result;
use foundry_cli::{
opts::{EthereumOpts, TransactionOpts},
utils::{LoadConfig, get_provider},
Expand Down Expand Up @@ -49,7 +49,7 @@ pub struct MakeTxArgs {
/// Generate a raw RLP-encoded unsigned transaction.
///
/// Relaxes the wallet requirement.
#[arg(long, requires = "from")]
#[arg(long)]
raw_unsigned: bool,

/// Call `eth_signTransaction` using the `--from` argument or $ETH_FROM as sender
Expand Down Expand Up @@ -96,7 +96,7 @@ impl MakeTxArgs {

let provider = get_provider(&config)?;

let tx_builder = CastTxBuilder::new(&provider, tx, &config)
let tx_builder = CastTxBuilder::new(&provider, tx.clone(), &config)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could copy the nonce first, but this would just introduce another variable and doesnt really matter for this command

.await?
.with_to(to)
.await?
Expand All @@ -106,7 +106,17 @@ impl MakeTxArgs {

if raw_unsigned {
// Build unsigned raw tx
let from = eth.wallet.from.ok_or_eyre("missing `--from` address")?;
// Check if nonce is provided when --from is not specified
// See: <https://github.com/foundry-rs/foundry/issues/11110>
if eth.wallet.from.is_none() && tx.nonce.is_none() {
Comment on lines +109 to +111
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah yeah, that makes sense, the api is a bit weird like that because this basically reuses the regular signing function just with an optional value for returning unsigned

eyre::bail!(
"Missing required parameters for raw unsigned transaction. When --from is not provided, you must specify: --nonce"
);
}

// Use zero address as placeholder for unsigned transactions
let from = eth.wallet.from.unwrap_or(Address::ZERO);

let raw_tx = tx_builder.build_unsigned_raw(from).await?;

sh_println!("{raw_tx}")?;
Expand Down
67 changes: 67 additions & 0 deletions crates/cast/tests/cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1603,6 +1603,73 @@ casttest!(mktx_raw_unsigned, |_prj, cmd| {
]]);
});

casttest!(mktx_raw_unsigned_no_from_missing_chain, async |_prj, cmd| {
// As chain is not provided, a query is made to the provider to get the chain id, before the tx
// is built. Anvil is configured to use chain id 1 so that the produced tx will be the same
// as in the `mktx_raw_unsigned` test.
let (_, handle) = anvil::spawn(NodeConfig::test().with_chain_id(Some(1u64))).await;
cmd.args([
"mktx",
"--nonce",
"0",
"--gas-limit",
"21000",
"--gas-price",
"10000000000",
"--priority-gas-price",
"1000000000",
"0x0000000000000000000000000000000000000001",
"--raw-unsigned",
"--rpc-url",
&handle.http_endpoint(),
])
.assert_success()
.stdout_eq(str![[
r#"0x02e80180843b9aca008502540be4008252089400000000000000000000000000000000000000018080c0

"#
]]);
});

casttest!(mktx_raw_unsigned_no_from_missing_gas_pricing, async |_prj, cmd| {
let (_, handle) = anvil::spawn(NodeConfig::test()).await;
cmd.args([
"mktx",
"--nonce",
"0",
"0x0000000000000000000000000000000000000001",
"--raw-unsigned",
"--rpc-url",
&handle.http_endpoint(),
])
.assert_success()
.stdout_eq(str![[
r#"0x02e5827a69800184773594018252089400000000000000000000000000000000000000018080c0

"#
]]);
});

casttest!(mktx_raw_unsigned_no_from_missing_nonce, |_prj, cmd| {
cmd.args([
"mktx",
"--chain",
"1",
"--gas-limit",
"21000",
"--gas-price",
"20000000000",
"0x742d35Cc6634C0532925a3b8D6Ac6F67C9c2b7FD",
"--raw-unsigned",
])
.assert_failure()
.stderr_eq(str![[
r#"Error: Missing required parameters for raw unsigned transaction. When --from is not provided, you must specify: --nonce

"#
]]);
});

casttest!(mktx_ethsign, async |_prj, cmd| {
let (_api, handle) = anvil::spawn(NodeConfig::test()).await;
let rpc = handle.http_endpoint();
Expand Down