Repository: dusk-network/rusk (language: rust)

Issue:
rusk-wallet: Cannot top up stake due to impossible min/max range
**Describe the bug**
On testnet, I have a node with a stake and I'd like to top up my existing stake using `rusk-wallet`. The existing stake is 15,000. I claimed the rewards and have around 292 dusk spendable which I now want to stake as a top-up. While trying to stake using the interactive menu for staking, I am blocked from progressing with an error indicating what I believe is a minimum and maximum range.

![Image](https://github.com/user-attachments/assets/0af746f6-5768-45a8-9add-fdf47e26e623)

There are two issues I see here.
Issue 1: The maximum value is lower than the minimum value
issue 2: The minimum value [should not apply](https://github.com/dusk-network/rusk/blob/master/contracts/stake/src/state.rs#L166) as this is not an initial stake


**What I think is the issue**

The last thing I did with the wallet and that account is set up multisig staking. There are two profiles in the wallet, and the owner of the stake is profile 2 while the staking is being done with profile 1. I think there is some confusion with the detection of the existing stake due to this.


**Expected behaviour**
The stake workflow should not have a minimum value applied in this case. I know others have used the top-up feature so there is something different with my setup.


**Platform**
The wallet version is `rusk-wallet 0.1.0-rc.0` from the latest installer.



Discussion / hints:
I have tried deleting the wallet.dat and the wallet cache and then reimporting the seed without generating the second profile. So the wallet only has 1 profile in it but the issue remains.
I may have encountered this issue when my node was not correctly synced. Will try it again when I get the node back online.
I am having this exact issue with my mainnet node. My node is currently synced and I am not using multi-sig. I've already topped up around numerous times since genesis without seeing this issue. 
@Daksh14 can you check this out please?
**Update**
I moved some more DUSK to my wallet balance, which put me over 1000. I was then able to top-up my stake without getting the error message. It seems that it is expecting top-ups to be over 1000 DUSK, which shouldn't be the case. 

Fix patch:
diff --git a/rusk-wallet/CHANGELOG.md b/rusk-wallet/CHANGELOG.md
index 14baa939bb..e5f8a4de1d 100644
--- a/rusk-wallet/CHANGELOG.md
+++ b/rusk-wallet/CHANGELOG.md
@@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 - Change dependency declaration to not require strict equal [#3405]
 
+### Fix
+
+- Fix wrong lower limit for stake operation when performing topup [#3394]
+
 ## [0.1.0] - 2025-01-20
 
 ### Add
@@ -42,6 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Fix stake info for inactive stakes with rewards [#2766]
 - Fix Moonlight stake reward withdrawal [#2523]
 
+
 <!-- Issues -->
 [#3405]: https://github.com/dusk-network/rusk/issues/3405
 [#3263]: https://github.com/dusk-network/rusk/issues/3263
@@ -63,6 +68,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 [#2396]: https://github.com/dusk-network/rusk/issues/2396
 [#2340]: https://github.com/dusk-network/rusk/issues/2340
 [#2288]: https://github.com/dusk-network/rusk/issues/2288
+[#3394]: https://github.com/dusk-network/rusk/issues/3394
 
 <!-- Releases -->
 [Unreleased]: https://github.com/dusk-network/rusk/compare/rusk-wallet-0.1.0...HEAD
diff --git a/rusk-wallet/src/bin/interactive/command_menu.rs b/rusk-wallet/src/bin/interactive/command_menu.rs
index 907fdc31f5..0eb5e5603e 100644
--- a/rusk-wallet/src/bin/interactive/command_menu.rs
+++ b/rusk-wallet/src/bin/interactive/command_menu.rs
@@ -6,6 +6,7 @@
 
 use std::fmt::Display;
 
+use dusk_core::stake::DEFAULT_MINIMUM_STAKE;
 use dusk_core::transfer::data::MAX_MEMO_SIZE;
 use inquire::{InquireError, Select};
 use rusk_wallet::currency::Dusk;
@@ -15,6 +16,7 @@ use rusk_wallet::gas::{
 };
 use rusk_wallet::{
     Address, Error, Wallet, MAX_CONTRACT_INIT_ARG_SIZE, MAX_FUNCTION_NAME_SIZE,
+    MIN_CONVERTIBLE,
 };
 
 use super::ProfileOp;
@@ -169,6 +171,21 @@ pub(crate) async fn online(
                 .public_key(stake_idx)
                 .expect("public key to exists in interactive mode");
 
+            let min_val = {
+                let has_stake = wallet
+                    .stake_info(stake_idx)
+                    .await?
+                    .map(|s| s.amount.is_some())
+                    .unwrap_or_default();
+
+                // if the user has stake then they are performing a topup
+                if has_stake {
+                    MIN_CONVERTIBLE
+                } else {
+                    DEFAULT_MINIMUM_STAKE.into()
+                }
+            };
+
             let owner = match wallet.find_stake_owner_account(stake_pk).await {
                 Ok(account) => account,
                 Err(Error::NotStaked) => {
@@ -177,6 +194,7 @@ pub(crate) async fn online(
                         .iter()
                         .map(|p| Address::Public(p.public_addr))
                         .collect();
+
                     prompt::request_address(stake_idx, choices)?
                 }
                 e => e?,
@@ -185,7 +203,7 @@ pub(crate) async fn online(
             ProfileOp::Run(Box::new(Command::Stake {
                 address: Some(addr),
                 owner: Some(owner),
-                amt: prompt::request_stake_token_amt(balance)?,
+                amt: prompt::request_stake_token_amt(balance, min_val)?,
                 gas_limit: prompt::request_gas_limit(gas::DEFAULT_LIMIT_CALL)?,
                 gas_price: prompt::request_gas_price(
                     DEFAULT_PRICE,
diff --git a/rusk-wallet/src/bin/io/prompt.rs b/rusk-wallet/src/bin/io/prompt.rs
index 7d941b5f41..3b3f9b1a59 100644
--- a/rusk-wallet/src/bin/io/prompt.rs
+++ b/rusk-wallet/src/bin/io/prompt.rs
@@ -16,7 +16,6 @@ use crossterm::{
 
 use anyhow::Result;
 use bip39::{ErrorKind, Language, Mnemonic};
-use dusk_core::stake::DEFAULT_MINIMUM_STAKE;
 
 use inquire::ui::RenderConfig;
 use inquire::validator::Validation;
@@ -265,10 +264,12 @@ pub(crate) fn request_optional_token_amt(
     request_token(action, min, balance, None).map_err(Error::from)
 }
 
-/// Request amount of tokens that can't be lower than MINIMUM_STAKE
-pub(crate) fn request_stake_token_amt(balance: Dusk) -> Result<Dusk, Error> {
-    let min: Dusk = DEFAULT_MINIMUM_STAKE.into();
-
+/// Request amount of tokens that can't be lower than the `min` argument and
+/// higher than `balance`
+pub(crate) fn request_stake_token_amt(
+    balance: Dusk,
+    min: Dusk,
+) -> Result<Dusk, Error> {
     request_token("stake", min, balance, None).map_err(Error::from)
 }
 


Test patch: