Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit f7d4ebe

Browse files
authored
added a flag to check if the recipient address is correct (#3085)
* added a flag to check if the recipient address is correct * small fix * Made the changes of adding the check to a suggested block * updating from base * was able to clear merge conflicts * added a couple tests * better names for tests * done with fixes * cargo fmt
1 parent 01c2c4b commit f7d4ebe

File tree

1 file changed

+87
-6
lines changed

1 file changed

+87
-6
lines changed

token/cli/src/main.rs

Lines changed: 87 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,7 @@ fn command_transfer(
649649
memo: Option<String>,
650650
bulk_signers: BulkSigners,
651651
no_wait: bool,
652+
allow_non_system_account_recipient: bool,
652653
) -> CommandResult {
653654
let sender = if let Some(sender) = sender {
654655
sender
@@ -709,17 +710,31 @@ fn command_transfer(
709710
.get_account_with_commitment(&recipient, config.rpc_client.commitment())?
710711
.value
711712
.map(|account| {
712-
account.owner == config.program_id && account.data.len() == Account::LEN
713+
(
714+
account.owner == config.program_id && account.data.len() == Account::LEN,
715+
account.owner == system_program::id(),
716+
)
713717
});
714-
715-
if recipient_account_info.is_none() && !allow_unfunded_recipient {
718+
if let Some((recipient_is_token_account, recipient_is_system_account)) =
719+
recipient_account_info
720+
{
721+
if !recipient_is_token_account
722+
&& !recipient_is_system_account
723+
&& !allow_non_system_account_recipient
724+
{
725+
return Err("Error: The recipient address is not owned by the System Program. \
726+
Add `--allow-non-system-account-recipient` to complete the transfer. \
727+
".into());
728+
}
729+
} else if recipient_account_info.is_none() && !allow_unfunded_recipient {
716730
return Err("Error: The recipient address is not funded. \
717-
Add `--allow-unfunded-recipient` to complete the transfer \
731+
Add `--allow-unfunded-recipient` to complete the transfer. \
718732
"
719733
.into());
720734
}
721-
722-
recipient_account_info.unwrap_or(false)
735+
recipient_account_info
736+
.map(|(recipient_is_token_account, _)| recipient_is_token_account)
737+
.unwrap_or(false)
723738
} else {
724739
!recipient_is_ata_owner
725740
};
@@ -2024,6 +2039,12 @@ fn app<'a, 'b>(
20242039
.takes_value(false)
20252040
.help("Return signature immediately after submitting the transaction, instead of waiting for confirmations"),
20262041
)
2042+
.arg(
2043+
Arg::with_name("allow_non_system_account_recipient")
2044+
.long("allow-non-system-account-recipient")
2045+
.takes_value(false)
2046+
.help("Send tokens to the recipient even if the recipient is not a wallet owned by System Program."),
2047+
)
20272048
.arg(
20282049
Arg::with_name("recipient_is_ata_owner")
20292050
.long("recipient-is-ata-owner")
@@ -2785,6 +2806,7 @@ fn process_command(
27852806
memo,
27862807
bulk_signers,
27872808
arg_matches.is_present("no_wait"),
2809+
arg_matches.is_present("allow_non_system_account_recipient"),
27882810
)
27892811
}
27902812
("burn", arg_matches) => {
@@ -3490,6 +3512,65 @@ mod tests {
34903512
assert_eq!(ui_account.token_amount.amount, "90");
34913513
}
34923514

3515+
#[test]
3516+
fn failing_to_allow_non_system_account_recipient() {
3517+
let (test_validator, payer) = validator_for_test();
3518+
let config = test_config(&test_validator, &payer, &spl_token::id());
3519+
3520+
let token = create_token(&config, &payer);
3521+
let source = create_associated_account(&config, &payer, token);
3522+
let recipient = token.to_string();
3523+
let ui_amount = 100.0;
3524+
mint_tokens(&config, &payer, token, ui_amount, source);
3525+
let result = process_test_command(
3526+
&config,
3527+
&payer,
3528+
&[
3529+
"spl-token",
3530+
"transfer",
3531+
"--fund-recipient",
3532+
&token.to_string(),
3533+
"10",
3534+
&recipient,
3535+
],
3536+
);
3537+
assert!(result.is_err());
3538+
}
3539+
3540+
#[test]
3541+
fn allow_non_system_account_recipient() {
3542+
let (test_validator, payer) = validator_for_test();
3543+
let config = test_config(&test_validator, &payer, &spl_token::id());
3544+
3545+
let token = create_token(&config, &payer);
3546+
let source = create_associated_account(&config, &payer, token);
3547+
let recipient = token.to_string();
3548+
let ui_amount = 100.0;
3549+
mint_tokens(&config, &payer, token, ui_amount, source);
3550+
let result = process_test_command(
3551+
&config,
3552+
&payer,
3553+
&[
3554+
"spl-token",
3555+
"transfer",
3556+
"--fund-recipient",
3557+
"--allow-non-system-account-recipient",
3558+
"--allow-unfunded-recipient",
3559+
&token.to_string(),
3560+
"10",
3561+
&recipient,
3562+
],
3563+
);
3564+
result.unwrap();
3565+
3566+
let ui_account = config
3567+
.rpc_client
3568+
.get_token_account(&source)
3569+
.unwrap()
3570+
.unwrap();
3571+
assert_eq!(ui_account.token_amount.amount, "90");
3572+
}
3573+
34933574
#[test]
34943575
fn disable_mint_authority() {
34953576
let (test_validator, payer) = validator_for_test();

0 commit comments

Comments
 (0)