Skip to content

Commit 5e92b6e

Browse files
fix(cast): allow negative numbers for function call arguments (#11221)
* fix(cast): allow negative numbers for function call arguments * chore: fix test * chore: fix test * chore: fix test * Update crates/cast/tests/cli/main.rs * Update crates/cast/tests/cli/main.rs * chore: fix fmt --------- Co-authored-by: zerosnacks <[email protected]>
1 parent 5ea954f commit 5e92b6e

File tree

6 files changed

+142
-1
lines changed

6 files changed

+142
-1
lines changed

crates/cast/src/cmd/access_list.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub struct AccessListArgs {
2727
sig: Option<String>,
2828

2929
/// The arguments of the function to call.
30-
#[arg(value_name = "ARGS")]
30+
#[arg(value_name = "ARGS", allow_negative_numbers = true)]
3131
args: Vec<String>,
3232

3333
/// The block height to query at.

crates/cast/src/cmd/call.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ pub struct CallArgs {
7272
sig: Option<String>,
7373

7474
/// The arguments of the function to call.
75+
#[arg(allow_negative_numbers = true)]
7576
args: Vec<String>,
7677

7778
/// Raw hex-encoded data for the transaction. Used instead of \[SIG\] and \[ARGS\].
@@ -177,6 +178,7 @@ pub enum CallSubcommands {
177178
sig: Option<String>,
178179

179180
/// The arguments of the constructor.
181+
#[arg(allow_negative_numbers = true)]
180182
args: Vec<String>,
181183

182184
/// Ether to send in the transaction.
@@ -643,4 +645,21 @@ mod tests {
643645
Some(vec!["0x123:0x1:0x1234".to_string(), "0x456:0x2:0x5678".to_string()])
644646
);
645647
}
648+
649+
#[test]
650+
fn test_negative_args_with_flags() {
651+
// Test that negative args work with flags
652+
let args = CallArgs::parse_from([
653+
"foundry-cli",
654+
"--trace",
655+
"0xDeaDBeeFcAfEbAbEfAcEfEeDcBaDbEeFcAfEbAbE",
656+
"process(int256)",
657+
"-999999",
658+
"--debug",
659+
]);
660+
661+
assert!(args.trace);
662+
assert!(args.debug);
663+
assert_eq!(args.args, vec!["-999999"]);
664+
}
646665
}

crates/cast/src/cmd/estimate.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub struct EstimateArgs {
2222
sig: Option<String>,
2323

2424
/// The arguments of the function to call.
25+
#[arg(allow_negative_numbers = true)]
2526
args: Vec<String>,
2627

2728
/// The block height to query at.
@@ -58,6 +59,7 @@ pub enum EstimateSubcommands {
5859
sig: Option<String>,
5960

6061
/// Constructor arguments
62+
#[arg(allow_negative_numbers = true)]
6163
args: Vec<String>,
6264

6365
/// Ether to send in the transaction

crates/cast/src/cmd/mktx.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub struct MakeTxArgs {
2525
sig: Option<String>,
2626

2727
/// The arguments of the function to call.
28+
#[arg(allow_negative_numbers = true)]
2829
args: Vec<String>,
2930

3031
#[command(subcommand)]
@@ -69,6 +70,7 @@ pub enum MakeTxSubcommands {
6970
sig: Option<String>,
7071

7172
/// The constructor arguments.
73+
#[arg(allow_negative_numbers = true)]
7274
args: Vec<String>,
7375
},
7476
}

crates/cast/src/cmd/send.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub struct SendTxArgs {
3030
sig: Option<String>,
3131

3232
/// The arguments of the function to call.
33+
#[arg(allow_negative_numbers = true)]
3334
args: Vec<String>,
3435

3536
/// Only print the transaction hash and exit immediately.
@@ -80,6 +81,7 @@ pub enum SendTxSubcommands {
8081
sig: Option<String>,
8182

8283
/// The arguments of the function to call.
84+
#[arg(allow_negative_numbers = true)]
8385
args: Vec<String>,
8486
},
8587
}

crates/cast/tests/cli/main.rs

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3741,3 +3741,119 @@ Transaction successfully executed.
37413741
37423742
"#]]);
37433743
});
3744+
3745+
// Tests for negative number argument parsing
3746+
// Ensures that negative numbers in function arguments are properly parsed
3747+
// instead of being treated as command flags
3748+
3749+
// Test that cast call accepts negative numbers as function arguments
3750+
casttest!(cast_call_negative_numbers, |_prj, cmd| {
3751+
let rpc = next_rpc_endpoint(NamedChain::Sepolia);
3752+
// Test with negative int parameter - should not treat -456789 as a flag
3753+
cmd.args([
3754+
"call",
3755+
"0xAbCdEf1234567890aBcDeF1234567890aBcDeF12",
3756+
"processValue(int128)",
3757+
"-456789",
3758+
"--rpc-url",
3759+
rpc.as_str(),
3760+
])
3761+
.assert_success();
3762+
});
3763+
3764+
// Test negative numbers with multiple parameters
3765+
casttest!(cast_call_multiple_negative_numbers, |_prj, cmd| {
3766+
let rpc = next_rpc_endpoint(NamedChain::Sepolia);
3767+
cmd.args([
3768+
"call",
3769+
"--rpc-url",
3770+
rpc.as_str(),
3771+
"0xDeaDBeeFcAfEbAbEfAcEfEeDcBaDbEeFcAfEbAbE",
3772+
"calculateDelta(int64,int32,uint16)",
3773+
"-987654321",
3774+
"-42",
3775+
"65535",
3776+
])
3777+
.assert_success();
3778+
});
3779+
3780+
// Test negative numbers mixed with flags
3781+
casttest!(cast_call_negative_with_flags, |_prj, cmd| {
3782+
let rpc = next_rpc_endpoint(NamedChain::Sepolia);
3783+
cmd.args([
3784+
"call",
3785+
"--trace", // flag before
3786+
"0x9876543210FeDcBa9876543210FeDcBa98765432",
3787+
"updateBalance(int256)",
3788+
"-777888",
3789+
"--rpc-url",
3790+
rpc.as_str(), // flag after
3791+
])
3792+
.assert_success();
3793+
});
3794+
3795+
// Test that actual invalid flags are still caught
3796+
casttest!(cast_call_invalid_flag_still_caught, |_prj, cmd| {
3797+
cmd.args([
3798+
"call",
3799+
"--invalid-flag", // This should be caught as invalid
3800+
"0x5555555555555555555555555555555555555555",
3801+
])
3802+
.assert_failure()
3803+
.stderr_eq(str![[r#"
3804+
error: unexpected argument '--invalid-flag' found
3805+
3806+
tip: to pass '--invalid-flag' as a value, use '-- --invalid-flag'
3807+
3808+
Usage: cast[..] call [OPTIONS] [TO] [SIG] [ARGS]... [COMMAND]
3809+
3810+
For more information, try '--help'.
3811+
3812+
"#]]);
3813+
});
3814+
3815+
// Test cast estimate with negative numbers
3816+
casttest!(cast_estimate_negative_numbers, |_prj, cmd| {
3817+
let rpc = next_rpc_endpoint(NamedChain::Sepolia);
3818+
cmd.args([
3819+
"estimate",
3820+
"0xBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBb",
3821+
"rebalance(int64)",
3822+
"-8888",
3823+
"--rpc-url",
3824+
rpc.as_str(),
3825+
])
3826+
.assert_success();
3827+
});
3828+
3829+
// Test cast mktx with negative numbers
3830+
casttest!(cast_mktx_negative_numbers, |_prj, cmd| {
3831+
let rpc = next_rpc_endpoint(NamedChain::Sepolia);
3832+
cmd.args([
3833+
"mktx",
3834+
"0x1111111111111111111111111111111111111111",
3835+
"settleDebt(int256)",
3836+
"-15000",
3837+
"--private-key",
3838+
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", // anvil wallet #0
3839+
"--rpc-url",
3840+
rpc.as_str(),
3841+
"--gas-limit",
3842+
"100000",
3843+
])
3844+
.assert_success();
3845+
});
3846+
3847+
// Test cast access-list with negative numbers
3848+
casttest!(cast_access_list_negative_numbers, |_prj, cmd| {
3849+
let rpc = next_rpc_endpoint(NamedChain::Sepolia);
3850+
cmd.args([
3851+
"access-list",
3852+
"0x9999999999999999999999999999999999999999",
3853+
"adjustPosition(int128)",
3854+
"-33333",
3855+
"--rpc-url",
3856+
rpc.as_str(),
3857+
])
3858+
.assert_success();
3859+
});

0 commit comments

Comments
 (0)