diff --git a/validations/src/validations.rs b/validations/src/validations.rs index d9fe95e6e..a3735c93e 100644 --- a/validations/src/validations.rs +++ b/validations/src/validations.rs @@ -1465,12 +1465,14 @@ pub fn validate_unstake_transaction<'a>( min_stake_nanowits: u64, unstake_delay: u64, ) -> Result<(u64, u32, Vec<&'a ValueTransferOutput>), anyhow::Error> { - if get_protocol_version(Some(epoch)) <= ProtocolVersion::V1_8 { + let protocol_version = get_protocol_version(Some(epoch)); + + if protocol_version <= ProtocolVersion::V1_8 { return Err(TransactionError::NoUnstakeTransactionsAllowed.into()); } // Check if is unstaking more than the total stake - let amount_to_unstake = ut_tx.body.value() + ut_tx.body.fee; + let mut amount_to_unstake = ut_tx.body.value() + ut_tx.body.fee; let validator = ut_tx.body.operator; let withdrawer = ut_tx.signature.public_key.pkh(); @@ -1515,6 +1517,13 @@ pub fn validate_unstake_transaction<'a>( } }; + // Introduced in V2_1: + // Apply a protocol-level "rule of convenience", where an amount to unstake of u64::MAX actually + // means "unstake all my stake". + if protocol_version >= ProtocolVersion::V2_1 && amount_to_unstake == u64::MAX { + amount_to_unstake = staked_amount; + } + // Allowed unstake actions: // 1) Unstake the full balance (checked by the first condition) // 2) Unstake an amount such that the remainder (the stake amount that is left over) is greater