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
2 changes: 1 addition & 1 deletion FULL_HELP_DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2325,7 +2325,7 @@ Calls the token's Stellar Asset Contract `mint` function. A non-SAC contract wit
###### **Options:**

- `--id <ID>` — The token to mint: a contract id or alias, or a classic asset as `CODE:ISSUER`
- `--to <TO>` — Account or contract to mint the tokens to. Accepts a `G…`/`M…` account, a `C…` contract address, or an alias
- `--to <TO>` — Account or contract to mint the tokens to. Accepts a `G…` account, a `C…` contract address, or an alias
- `--amount <AMOUNT>` — Amount to mint, in the token's smallest unit (stroops for a Stellar Asset Contract)
- `--output <OUTPUT>` — Format of the output

Expand Down
2 changes: 1 addition & 1 deletion cmd/crates/soroban-spec-tools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2514,7 +2514,7 @@ mod tests {
fn test_find_events_empty_spec() {
let spec = make_spec_with_events_and_functions(vec![], vec![]);
let found_events: Vec<_> = spec.find_events().unwrap().collect();
assert!(found_events.is_empty());
assert_eq!(found_events, Vec::<&ScSpecEventV0>::new());
}

#[test]
Expand Down
4 changes: 2 additions & 2 deletions cmd/crates/soroban-spec-tools/src/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ mod tests {
make_fn_entry("do_thing", vec![("s", make_udt_type("MyStruct"))], vec![]),
];
let spec = Spec::new(&entries);
assert!(spec.verify().is_empty());
assert_eq!(spec.verify(), Vec::<SpecWarning>::new());
}

#[test]
Expand Down Expand Up @@ -301,7 +301,7 @@ mod tests {
vec![],
)];
let spec = Spec::new(&entries);
assert!(spec.verify().is_empty());
assert_eq!(spec.verify(), Vec::<SpecWarning>::new());
}

#[test]
Expand Down
20 changes: 10 additions & 10 deletions cmd/crates/soroban-test/tests/it/integration/ledger/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ async fn ledger_entry_account_with_alias() {
let (_, expected_key) = expected_account_ledger_key(&new_account_addr).await;
let parsed: FullLedgerEntries = serde_json::from_str(&output).expect("Failed to parse JSON");

assert!(!parsed.entries.is_empty());
assert_ne!(parsed.entries.len(), 0);
assert_eq!(parsed.entries[0].key, expected_key);
assert!(matches!(
parsed.entries[0].val,
Expand Down Expand Up @@ -75,7 +75,7 @@ async fn ledger_entry_account_with_account_addr() {
let (_, expected_key) = expected_account_ledger_key(&new_account_addr).await;
let parsed: FullLedgerEntries = serde_json::from_str(&output).expect("Failed to parse JSON");

assert!(!parsed.entries.is_empty());
assert_ne!(parsed.entries.len(), 0);
assert_eq!(parsed.entries[0].key, expected_key);
assert!(matches!(
parsed.entries[0].val,
Expand Down Expand Up @@ -132,7 +132,7 @@ async fn ledger_entry_trustline_asset_usdc() {
});

let parsed: FullLedgerEntries = serde_json::from_str(&output).expect("Failed to parse JSON");
assert!(!parsed.entries.is_empty());
assert_ne!(parsed.entries.len(), 0);

let trustline_entry = &parsed.entries[0];
assert_eq!(trustline_entry.key, expected_trustline_key);
Expand Down Expand Up @@ -166,7 +166,7 @@ async fn ledger_entry_account_data() {
.stdout_as_str();

let parsed: FullLedgerEntries = serde_json::from_str(&output).expect("Failed to parse JSON");
assert!(!parsed.entries.is_empty());
assert_ne!(parsed.entries.len(), 0);

let (account_id, _) = expected_account_ledger_key(&new_account_addr).await;

Expand Down Expand Up @@ -222,7 +222,7 @@ async fn ledger_entry_contract_data() {
.success()
.stdout_as_str();
let parsed_key_output: FullLedgerEntries = serde_json::from_str(&key_output).unwrap();
assert!(!parsed_key_output.entries.is_empty());
assert_ne!(parsed_key_output.entries.len(), 0);

// get entry by key xdr
let key_xdr_output = sandbox
Expand All @@ -240,7 +240,7 @@ async fn ledger_entry_contract_data() {
.success()
.stdout_as_str();
let parsed_key_xdr_output: FullLedgerEntries = serde_json::from_str(&key_xdr_output).unwrap();
assert!(!parsed_key_xdr_output.entries.is_empty());
assert_ne!(parsed_key_xdr_output.entries.len(), 0);

let expected_contract_data_key = expected_contract_ledger_key(&contract_id, storage_key).await;

Expand Down Expand Up @@ -282,7 +282,7 @@ async fn ledger_entry_contract_data() {
key: ScVal::LedgerKeyContractInstance,
durability: ContractDataDurability::Persistent,
});
assert!(!parsed_instance_output.entries.is_empty());
assert_ne!(parsed_instance_output.entries.len(), 0);
assert_eq!(parsed_instance_output.entries[0].key, expected_instance_key);
assert!(matches!(
parsed_instance_output.entries[0].val,
Expand Down Expand Up @@ -331,7 +331,7 @@ async fn ledger_entry_contract_code() {
.stdout_as_str();
let parsed_output: FullLedgerEntries =
serde_json::from_str(&output).expect("Failed to parse JSON");
assert!(!parsed_output.entries.is_empty());
assert_ne!(parsed_output.entries.len(), 0);

let hash = Hash(
padded_hex_from_str(&contract_wasm_hash, 32)
Expand Down Expand Up @@ -378,7 +378,7 @@ async fn ledger_entry_claimable_balance() {
.stdout_as_str();
let parsed_output: FullLedgerEntries =
serde_json::from_str(&output).expect("Failed to parse JSON");
assert!(!parsed_output.entries.is_empty());
assert_ne!(parsed_output.entries.len(), 0);
let expected_key = LedgerKey::ClaimableBalance(LedgerKeyClaimableBalance {
balance_id: ClaimableBalanceId::ClaimableBalanceIdTypeV0(id),
});
Expand Down Expand Up @@ -431,7 +431,7 @@ async fn ledger_entry_liquidity_pool() {
.stdout_as_str();
let parsed_output: FullLedgerEntries =
serde_json::from_str(&output).expect("Failed to parse JSON");
assert!(!parsed_output.entries.is_empty());
assert_ne!(parsed_output.entries.len(), 0);
let expected_key = LedgerKey::LiquidityPool(LedgerKeyLiquidityPool {
liquidity_pool_id: PoolId(Hash(pool_id.0)),
});
Expand Down
20 changes: 20 additions & 0 deletions cmd/crates/soroban-test/tests/it/integration/token/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,26 @@ async fn mint_rejects_muxed_source_with_clear_error() {
));
}

#[tokio::test]
async fn mint_rejects_muxed_to_with_clear_error() {
let sandbox = &TestEnv::new();

// A muxed (M…) recipient isn't a valid `mint` target — the host rejects it
// mid-simulation with an opaque error — so the command rejects it up front
// with a clear message.
let muxed = "MA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAAAAAAAAAPCICBKU";
sandbox
.new_assert_cmd("token")
.args([
"mint", "--id", "native", "--source", "test", "--to", muxed, "--amount", "1",
])
.assert()
.failure()
.stderr(predicates::str::contains(
"muxed (M…) recipient accounts are not yet supported",
));
}

#[tokio::test]
async fn mint_warns_when_target_is_not_a_sac() {
let sandbox = &TestEnv::new();
Expand Down
2 changes: 1 addition & 1 deletion cmd/crates/soroban-test/tests/it/integration/tx/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ async fn tx_fetch_events() {
let parsed: GetTransactionEvents = serde_json::from_str(&output).unwrap();
// With diagnostic events enabled on the network, the RPC surfaces the full
// diagnostic stream (fn_call/fn_return, the contract log, and core_metrics).
assert!(!parsed.diagnostic_events.is_empty());
assert_ne!(parsed.diagnostic_events.len(), 0);
assert_eq!(parsed.contract_events.len(), 1);
assert_eq!(parsed.transaction_events.len(), 2);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ async fn set_some_options() {
after.home_domain,
"".parse::<xdr::StringM<32>>().unwrap().into()
);
assert!(after.signers.is_empty());
assert_eq!(after.signers.len(), 0);
sandbox
.new_assert_cmd("tx")
.args(["new", "set-options", "--set-clawback-enabled"])
Expand Down
3 changes: 3 additions & 0 deletions cmd/crates/stellar-ledger/src/signer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#[async_trait::async_trait]
// async_trait emits `#[must_use]` on methods that already return a must_use
// `Pin<Box<dyn Future>>`, tripping clippy 1.99.0's double_must_use. See #2784.
#[allow(clippy::double_must_use)]
pub trait Blob {
type Key: Send;
type Error;
Expand Down
2 changes: 1 addition & 1 deletion cmd/soroban-cli/src/commands/container/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ mod test {

#[test]
fn run_args_flags_emit_only_set_limits() {
assert!(RunArgs::default().flags().is_empty());
assert_eq!(RunArgs::default().flags().len(), 0);
assert_eq!(
RunArgs {
cpus: Some(1),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ mod tests {

let a = build_source_archive(root, &print, true, None).unwrap();
let b = build_source_archive(root, &print, true, None).unwrap();
assert!(!a.is_empty());
assert_ne!(a.len(), 0);
assert_eq!(a, b, "same tree should produce identical bytes");

// The `.git` dir git_init_commit created is never archived.
Expand Down
19 changes: 10 additions & 9 deletions cmd/soroban-cli/src/commands/token/clawback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,23 +109,24 @@ impl Cmd {
if matches!(source_account, crate::xdr::MuxedAccount::MuxedEd25519(_)) {
return Err(Error::MuxedSourceNotSupported);
}
// `clawback` is a SAC-admin function; warn (in human-readable mode) if the
// target isn't actually a Stellar Asset Contract.
if !output.is_json() {
args::warn_if_not_sac(output.print(), "clawback", &token.contract_id, &network).await;
}
// `--from` may be an account (`G…`), a contract (`C…`), or an alias. The
// host rejects a muxed (`M…`) holder mid-simulation with an opaque error,
// so reject one up front with a clear message — whether supplied as a
// direct `M…` strkey or an alias resolving to a muxed key.
// so reject one up front — before any network round-trip — with a clear
// message, whether supplied as a direct `M…` strkey or an alias resolving
// to a muxed key.
if self
.from
.is_muxed(&config.locator, &network.network_passphrase)
{
return Err(Error::MuxedFromNotSupported);
}
// Resolve it to an `ScAddress` and hand the strkey to the `clawback` arg,
// which accepts any of these holders.
// `clawback` is a SAC-admin function; warn (in human-readable mode) if the
// target isn't actually a Stellar Asset Contract.
if !output.is_json() {
args::warn_if_not_sac(output.print(), "clawback", &token.contract_id, &network).await;
}
// Resolve `--from` to an `ScAddress` and hand the strkey to the `clawback`
// arg, which accepts any of these holders.
let from = self
.from
.clone()
Expand Down
23 changes: 18 additions & 5 deletions cmd/soroban-cli/src/commands/token/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ pub struct Cmd {
#[arg(long = "id")]
pub id: UnresolvedToken,

/// Account or contract to mint the tokens to. Accepts a `G…`/`M…` account, a
/// `C…` contract address, or an alias.
/// Account or contract to mint the tokens to. Accepts a `G…` account, a `C…`
/// contract address, or an alias.
#[arg(long)]
pub to: UnresolvedScAddress,

Expand Down Expand Up @@ -55,6 +55,9 @@ pub enum Error {

#[error("muxed (M…) source accounts are not yet supported for `token mint`")]
MuxedSourceNotSupported,

#[error("muxed (M…) recipient accounts are not yet supported for `token mint`")]
MuxedToNotSupported,
}

/// Parse `--amount` as a non-negative `i128`. A negative mint amount is always
Expand Down Expand Up @@ -82,7 +85,7 @@ impl Error {
Error::ScAddress(_) => "invalid_address",
Error::Invoke(_) => "invoke",
Error::Serde(_) => "internal",
Error::MuxedSourceNotSupported => "unsupported",
Error::MuxedSourceNotSupported | Error::MuxedToNotSupported => "unsupported",
}
}
}
Expand Down Expand Up @@ -118,13 +121,23 @@ impl Cmd {
if matches!(source_account, crate::xdr::MuxedAccount::MuxedEd25519(_)) {
return Err(Error::MuxedSourceNotSupported);
}
// `--to` may be an account (`G…`), a contract (`C…`), or an alias. The
// host rejects a muxed (`M…`) recipient mid-simulation with an opaque
// error, so reject one up front — before any network round-trip — with a
// clear message, whether supplied as a direct `M…` strkey or an alias
// resolving to a muxed key.
if self
.to
.is_muxed(&config.locator, &network.network_passphrase)
{
return Err(Error::MuxedToNotSupported);
}
// `mint` is a SAC-admin function; warn (in human-readable mode) if the
// target isn't actually a Stellar Asset Contract.
if !output.is_json() {
args::warn_if_not_sac(output.print(), "mint", &token.contract_id, &network).await;
}
// `--to` may be an account (`G…`/`M…`), a contract (`C…`), or an alias;
// resolve it to an `ScAddress` and hand the strkey to the `mint` arg,
// Resolve `--to` to an `ScAddress` and hand the strkey to the `mint` arg,
// which accepts any of these destinations.
let to = self
.to
Expand Down
18 changes: 9 additions & 9 deletions cmd/soroban-cli/src/commands/token/set_admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,24 +104,24 @@ impl Cmd {
if matches!(source_account, crate::xdr::MuxedAccount::MuxedEd25519(_)) {
return Err(Error::MuxedSourceNotSupported);
}
// `set_admin` is a SAC-admin function; warn (in human-readable mode) if
// the target isn't actually a Stellar Asset Contract.
if !output.is_json() {
args::warn_if_not_sac(output.print(), "set_admin", &token.contract_id, &network).await;
}
// `--new-admin` may be an account (`G…`), a contract (`C…`), or an alias.
// A muxed (`M…`) successor would be stranded — it can't sign as a source
// (see #2645) and the SAC stores a plain `Address` — so reject one up
// front rather than performing an irreversible transfer to an
// unusable admin.
// front, before any network round-trip, rather than performing an
// irreversible transfer to an unusable admin.
if self
.new_admin
.is_muxed(&config.locator, &network.network_passphrase)
{
return Err(Error::MuxedNewAdminNotSupported);
}
// Resolve it to an `ScAddress` and hand the strkey to the `set_admin`
// arg, which accepts any of these administrators.
// `set_admin` is a SAC-admin function; warn (in human-readable mode) if
// the target isn't actually a Stellar Asset Contract.
if !output.is_json() {
args::warn_if_not_sac(output.print(), "set_admin", &token.contract_id, &network).await;
}
// Resolve `--new-admin` to an `ScAddress` and hand the strkey to the
// `set_admin` arg, which accepts any of these administrators.
let new_admin = self
.new_admin
.clone()
Expand Down
2 changes: 1 addition & 1 deletion cmd/soroban-cli/src/config/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ mod tests {
.expect("passphrase-only network should resolve for signing-only commands");
assert_eq!(network.network_passphrase, "specified manually");
assert_eq!(network.rpc_url, "");
assert!(network.rpc_headers.is_empty());
assert_eq!(network.rpc_headers.len(), 0);
}

#[test]
Expand Down
Loading