diff --git a/execution_engine_testing/tests/src/test/regression/ee_1174.rs b/execution_engine_testing/tests/src/test/regression/ee_1174.rs index cc5d833bd1..496f3f7f89 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_1174.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_1174.rs @@ -10,7 +10,7 @@ use casper_types::{ self, auction::{self, DelegationRate}, }, - ApiError, U512, + ApiError, DEFAULT_MINIMUM_BID_AMOUNT, U512, }; const LARGE_DELEGATION_RATE: DelegationRate = 101; @@ -18,7 +18,7 @@ const LARGE_DELEGATION_RATE: DelegationRate = 101; #[ignore] #[test] fn should_run_ee_1174_delegation_rate_too_high() { - let bid_amount = U512::one(); + let bid_amount = U512::from(DEFAULT_MINIMUM_BID_AMOUNT); let mut builder = LmdbWasmTestBuilder::default(); builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); diff --git a/execution_engine_testing/tests/src/test/regression/ee_1217.rs b/execution_engine_testing/tests/src/test/regression/ee_1217.rs index a5f12aa12e..1e57438c13 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_1217.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_1217.rs @@ -6,7 +6,9 @@ use casper_execution_engine::{ engine_state::{engine_config::DEFAULT_MINIMUM_DELEGATION_AMOUNT, Error as CoreError}, execution::ExecError, }; -use casper_types::{runtime_args, system::auction, ApiError, PublicKey, SecretKey, U512}; +use casper_types::{ + runtime_args, system::auction, ApiError, PublicKey, SecretKey, DEFAULT_MINIMUM_BID_AMOUNT, U512, +}; use once_cell::sync::Lazy; const CONTRACT_REGRESSION: &str = "ee_1217_regression.wasm"; @@ -123,7 +125,7 @@ fn should_fail_to_withdraw_bid_from_stored_session_code() { *DEFAULT_ACCOUNT_ADDR, CONTRACT_ADD_BID, runtime_args! { - auction::ARG_AMOUNT => U512::one(), // zero results in Error::BondTooSmall + auction::ARG_AMOUNT => U512::from(DEFAULT_MINIMUM_BID_AMOUNT), // smaller amount results in Error::BondTooSmall auction::ARG_PUBLIC_KEY => default_public_key_arg.clone(), auction::ARG_DELEGATION_RATE => 0u8, }, @@ -178,7 +180,7 @@ fn should_fail_to_withdraw_bid_from_stored_contract_code() { *DEFAULT_ACCOUNT_ADDR, CONTRACT_ADD_BID, runtime_args! { - auction::ARG_AMOUNT => U512::one(), // zero results in Error::BondTooSmall + auction::ARG_AMOUNT => U512::from(DEFAULT_MINIMUM_BID_AMOUNT), // smaller amount results in Error::BondTooSmall auction::ARG_PUBLIC_KEY => default_public_key_arg.clone(), auction::ARG_DELEGATION_RATE => 0u8, }, @@ -252,7 +254,7 @@ fn should_fail_to_delegate_from_stored_session_code() { VALIDATOR_PUBLIC_KEY.to_account_hash(), CONTRACT_ADD_BID, runtime_args! { - auction::ARG_AMOUNT => U512::one(), // zero results in Error::BondTooSmall + auction::ARG_AMOUNT => U512::from(DEFAULT_MINIMUM_BID_AMOUNT), // smaller amount results in Error::BondTooSmall auction::ARG_PUBLIC_KEY => validator_public_key_arg.clone(), auction::ARG_DELEGATION_RATE => 0u8, }, @@ -332,7 +334,7 @@ fn should_fail_to_delegate_from_stored_contract_code() { VALIDATOR_PUBLIC_KEY.to_account_hash(), CONTRACT_ADD_BID, runtime_args! { - auction::ARG_AMOUNT => U512::one(), // zero results in Error::BondTooSmall + auction::ARG_AMOUNT => U512::from(DEFAULT_MINIMUM_BID_AMOUNT), // smaller amount results in Error::BondTooSmall auction::ARG_PUBLIC_KEY => validator_public_key_arg.clone(), auction::ARG_DELEGATION_RATE => 0u8, }, @@ -412,7 +414,7 @@ fn should_fail_to_undelegate_from_stored_session_code() { VALIDATOR_PUBLIC_KEY.to_account_hash(), CONTRACT_ADD_BID, runtime_args! { - auction::ARG_AMOUNT => U512::one(), // zero results in Error::BondTooSmall + auction::ARG_AMOUNT => U512::from(DEFAULT_MINIMUM_BID_AMOUNT), // smaller amount results in Error::BondTooSmall auction::ARG_PUBLIC_KEY => validator_public_key_arg.clone(), auction::ARG_DELEGATION_RATE => 0u8, }, @@ -506,7 +508,7 @@ fn should_fail_to_undelegate_from_stored_contract_code() { VALIDATOR_PUBLIC_KEY.to_account_hash(), CONTRACT_ADD_BID, runtime_args! { - auction::ARG_AMOUNT => U512::one(), // zero results in Error::BondTooSmall + auction::ARG_AMOUNT => U512::from(DEFAULT_MINIMUM_BID_AMOUNT), // smaller amount results in Error::BondTooSmall auction::ARG_PUBLIC_KEY => validator_public_key_arg.clone(), auction::ARG_DELEGATION_RATE => 0u8, }, @@ -581,7 +583,7 @@ fn should_fail_to_activate_bid_from_stored_session_code() { *DEFAULT_ACCOUNT_ADDR, CONTRACT_ADD_BID, runtime_args! { - auction::ARG_AMOUNT => U512::one(), // zero results in Error::BondTooSmall + auction::ARG_AMOUNT => U512::from(DEFAULT_MINIMUM_BID_AMOUNT), // smaller amount results in Error::BondTooSmall auction::ARG_PUBLIC_KEY => default_public_key_arg.clone(), auction::ARG_DELEGATION_RATE => 0u8, }, @@ -592,7 +594,7 @@ fn should_fail_to_activate_bid_from_stored_session_code() { *DEFAULT_ACCOUNT_ADDR, CONTRACT_WITHDRAW_BID, runtime_args! { - auction::ARG_AMOUNT => U512::one(), // zero results in Error::BondTooSmall + auction::ARG_AMOUNT => U512::from(DEFAULT_MINIMUM_BID_AMOUNT), // smaller amount results in Error::BondTooSmall auction::ARG_PUBLIC_KEY => default_public_key_arg.clone(), }, ) @@ -647,7 +649,7 @@ fn should_fail_to_activate_bid_from_stored_contract_code() { *DEFAULT_ACCOUNT_ADDR, CONTRACT_ADD_BID, runtime_args! { - auction::ARG_AMOUNT => U512::one(), // zero results in Error::BondTooSmall + auction::ARG_AMOUNT => U512::from(DEFAULT_MINIMUM_BID_AMOUNT), // smaller amount results in Error::BondTooSmall auction::ARG_PUBLIC_KEY => default_public_key_arg.clone(), auction::ARG_DELEGATION_RATE => 0u8, }, @@ -658,7 +660,7 @@ fn should_fail_to_activate_bid_from_stored_contract_code() { *DEFAULT_ACCOUNT_ADDR, CONTRACT_WITHDRAW_BID, runtime_args! { - auction::ARG_AMOUNT => U512::one(), // zero results in Error::BondTooSmall + auction::ARG_AMOUNT => U512::from(DEFAULT_MINIMUM_BID_AMOUNT), // smaller amount results in Error::BondTooSmall auction::ARG_PUBLIC_KEY => default_public_key_arg.clone(), }, ) diff --git a/execution_engine_testing/tests/src/test/regression/gh_3208.rs b/execution_engine_testing/tests/src/test/regression/gh_3208.rs index 037d35b2ce..b6baafadce 100644 --- a/execution_engine_testing/tests/src/test/regression/gh_3208.rs +++ b/execution_engine_testing/tests/src/test/regression/gh_3208.rs @@ -19,7 +19,8 @@ use casper_types::{ auction::{self, BidAddr, DelegationRate}, standard_payment, }, - ApiError, GenesisAccount, GenesisValidator, Key, Motes, StoredValue, U512, + ApiError, GenesisAccount, GenesisValidator, Key, Motes, StoredValue, + DEFAULT_MINIMUM_BID_AMOUNT, U512, }; use crate::lmdb_fixture; @@ -188,7 +189,7 @@ fn should_immediatelly_unbond_genesis_validator_with_zero_day_vesting_schedule() auction::METHOD_ADD_BID, runtime_args! { auction::ARG_PUBLIC_KEY => DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), - auction::ARG_AMOUNT => U512::from(1u64), + auction::ARG_AMOUNT => U512::from(DEFAULT_MINIMUM_BID_AMOUNT), auction::ARG_DELEGATION_RATE => 10 as DelegationRate, }, ) @@ -316,7 +317,7 @@ fn should_immediatelly_unbond_genesis_validator_with_zero_day_vesting_schedule_a auction::METHOD_ADD_BID, runtime_args! { auction::ARG_PUBLIC_KEY => DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), - auction::ARG_AMOUNT => U512::from(1u64), + auction::ARG_AMOUNT => U512::from(DEFAULT_MINIMUM_BID_AMOUNT), auction::ARG_DELEGATION_RATE => 10 as DelegationRate, }, ) diff --git a/execution_engine_testing/tests/src/test/regression/gov_116.rs b/execution_engine_testing/tests/src/test/regression/gov_116.rs index 380a964e5d..600578312f 100644 --- a/execution_engine_testing/tests/src/test/regression/gov_116.rs +++ b/execution_engine_testing/tests/src/test/regression/gov_116.rs @@ -14,14 +14,15 @@ use casper_storage::data_access_layer::GenesisRequest; use casper_types::{ runtime_args, system::auction::{self, DelegationRate, EraValidators, VESTING_SCHEDULE_LENGTH_MILLIS}, - GenesisAccount, GenesisValidator, Motes, PublicKey, SecretKey, U256, U512, + GenesisAccount, GenesisValidator, Motes, PublicKey, SecretKey, DEFAULT_MINIMUM_BID_AMOUNT, + U256, U512, }; const MINIMUM_BONDED_AMOUNT: u64 = 1_000; /// Validator with smallest stake will withdraw most of his stake to ensure we did move time forward /// to unlock his whole vesting schedule. -const WITHDRAW_AMOUNT: u64 = MINIMUM_BONDED_AMOUNT - 1; +const WITHDRAW_AMOUNT: u64 = MINIMUM_BONDED_AMOUNT - DEFAULT_MINIMUM_BID_AMOUNT; /// Initial lockup period const VESTING_BASE: u64 = DEFAULT_GENESIS_TIMESTAMP_MILLIS + DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS; diff --git a/execution_engine_testing/tests/src/test/regression/host_function_metrics_size_and_gas_cost.rs b/execution_engine_testing/tests/src/test/regression/host_function_metrics_size_and_gas_cost.rs index 2ef3cc5190..0ca9b0089e 100644 --- a/execution_engine_testing/tests/src/test/regression/host_function_metrics_size_and_gas_cost.rs +++ b/execution_engine_testing/tests/src/test/regression/host_function_metrics_size_and_gas_cost.rs @@ -16,7 +16,7 @@ const CONTRACT_TRANSFER_TO_ACCOUNT_U512: &str = "transfer_to_account_u512.wasm"; // This value is not systemic, as code is added the size of WASM will increase, // you can change this value to reflect the increase in WASM size. -const HOST_FUNCTION_METRICS_STANDARD_SIZE: usize = 132_461; +const HOST_FUNCTION_METRICS_STANDARD_SIZE: usize = 143_164; const HOST_FUNCTION_METRICS_STANDARD_GAS_COST: u64 = 422_402_224_490; /// Acceptable size regression/improvement in percentage. diff --git a/execution_engine_testing/tests/src/test/system_contracts/auction/bids.rs b/execution_engine_testing/tests/src/test/system_contracts/auction/bids.rs index 7349bf653e..0f9d3db038 100644 --- a/execution_engine_testing/tests/src/test/system_contracts/auction/bids.rs +++ b/execution_engine_testing/tests/src/test/system_contracts/auction/bids.rs @@ -37,7 +37,7 @@ use casper_types::{ ARG_REWARDS_MAP, ARG_VALIDATOR, ERA_ID_KEY, INITIAL_ERA_ID, METHOD_DISTRIBUTE, }, EntityAddr, EraId, GenesisAccount, GenesisValidator, Key, Motes, ProtocolVersion, PublicKey, - SecretKey, TransactionHash, U256, U512, + SecretKey, TransactionHash, DEFAULT_MINIMUM_BID_AMOUNT, U256, U512, }; const ARG_TARGET: &str = "target"; @@ -1940,7 +1940,7 @@ fn fully_undelegated_funds_should_be_released() { #[ignore] #[test] fn should_undelegate_delegators_when_validator_unbonds() { - const VALIDATOR_1_REMAINING_BID: u64 = 1; + const VALIDATOR_1_REMAINING_BID: u64 = DEFAULT_MINIMUM_BID_AMOUNT; const VALIDATOR_1_WITHDRAW_AMOUNT: u64 = VALIDATOR_1_STAKE - VALIDATOR_1_REMAINING_BID; let system_fund_request = ExecuteRequestBuilder::standard( @@ -2390,6 +2390,205 @@ fn should_undelegate_delegators_when_validator_fully_unbonds() { ); } +#[ignore] +#[test] +fn should_undelegate_delegators_when_validator_unbonds_below_minimum_bid_amount() { + const VALIDATOR_1_REMAINING_BID: u64 = DEFAULT_MINIMUM_BID_AMOUNT - 1; + const VALIDATOR_1_WITHDRAW_AMOUNT: u64 = VALIDATOR_1_STAKE - VALIDATOR_1_REMAINING_BID; + + let system_fund_request = ExecuteRequestBuilder::standard( + *DEFAULT_ACCOUNT_ADDR, + CONTRACT_TRANSFER_TO_ACCOUNT, + runtime_args! { + ARG_TARGET => *SYSTEM_ADDR, + ARG_AMOUNT => U512::from(TRANSFER_AMOUNT) + }, + ) + .build(); + + let validator_1_fund_request = ExecuteRequestBuilder::standard( + *DEFAULT_ACCOUNT_ADDR, + CONTRACT_TRANSFER_TO_ACCOUNT, + runtime_args! { + ARG_TARGET => *VALIDATOR_1_ADDR, + ARG_AMOUNT => U512::from(TRANSFER_AMOUNT) + }, + ) + .build(); + + let delegator_1_fund_request = ExecuteRequestBuilder::standard( + *DEFAULT_ACCOUNT_ADDR, + CONTRACT_TRANSFER_TO_ACCOUNT, + runtime_args! { + ARG_TARGET => *DELEGATOR_1_ADDR, + ARG_AMOUNT => U512::from(TRANSFER_AMOUNT) + }, + ) + .build(); + + let delegator_2_fund_request = ExecuteRequestBuilder::standard( + *DEFAULT_ACCOUNT_ADDR, + CONTRACT_TRANSFER_TO_ACCOUNT, + runtime_args! { + ARG_TARGET => *DELEGATOR_2_ADDR, + ARG_AMOUNT => U512::from(TRANSFER_AMOUNT) + }, + ) + .build(); + + let validator_1_add_bid_request = ExecuteRequestBuilder::standard( + *VALIDATOR_1_ADDR, + CONTRACT_ADD_BID, + runtime_args! { + ARG_AMOUNT => U512::from(VALIDATOR_1_STAKE), + ARG_DELEGATION_RATE => VALIDATOR_1_DELEGATION_RATE, + ARG_PUBLIC_KEY => VALIDATOR_1.clone(), + }, + ) + .build(); + + let delegator_1_delegate_request = ExecuteRequestBuilder::standard( + *DELEGATOR_1_ADDR, + CONTRACT_DELEGATE, + runtime_args! { + ARG_AMOUNT => U512::from(DELEGATOR_1_STAKE), + ARG_VALIDATOR => VALIDATOR_1.clone(), + ARG_DELEGATOR => DELEGATOR_1.clone(), + }, + ) + .build(); + + let delegator_2_delegate_request = ExecuteRequestBuilder::standard( + *DELEGATOR_2_ADDR, + CONTRACT_DELEGATE, + runtime_args! { + ARG_AMOUNT => U512::from(DELEGATOR_2_STAKE), + ARG_VALIDATOR => VALIDATOR_1.clone(), + ARG_DELEGATOR => DELEGATOR_2.clone(), + }, + ) + .build(); + + let post_genesis_requests = vec![ + system_fund_request, + validator_1_fund_request, + delegator_1_fund_request, + delegator_2_fund_request, + validator_1_add_bid_request, + delegator_1_delegate_request, + delegator_2_delegate_request, + ]; + + let mut timestamp_millis = DEFAULT_GENESIS_TIMESTAMP_MILLIS; + let mut builder = LmdbWasmTestBuilder::default(); + + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + + for request in post_genesis_requests { + builder.exec(request).commit().expect_success(); + } + + // Try to unbond partially. Stake would fall below minimum bid which should force a full + // unbonding. + let validator_1_withdraw_bid = ExecuteRequestBuilder::standard( + *VALIDATOR_1_ADDR, + CONTRACT_WITHDRAW_BID, + runtime_args! { + ARG_PUBLIC_KEY => VALIDATOR_1.clone(), + ARG_AMOUNT => U512::from(VALIDATOR_1_WITHDRAW_AMOUNT), + }, + ) + .build(); + + builder + .exec(validator_1_withdraw_bid) + .commit() + .expect_success(); + + let bids_after = builder.get_bids(); + assert!(bids_after.validator_bid(&VALIDATOR_1).is_none()); + + let unbonding_purses_before = builder.get_unbonds(); + + let unbond_kind = UnbondKind::Validator(VALIDATOR_1.clone()); + let validator_1_era = unbonding_purses_before + .get(&unbond_kind) + .expect("should have unbonding purse") + .first() + .expect("must have unbond") + .eras() + .first() + .expect("should have era"); + + let unbond_kind = UnbondKind::DelegatedPublicKey(DELEGATOR_1.clone()); + let delegator_1_unbonding_purse = unbonding_purses_before + .get(&unbond_kind) + .expect("should have unbonding purse entry") + .first() + .expect("must have unbond") + .eras() + .first() + .expect("should have unbonding purse"); + + let unbond_kind = UnbondKind::DelegatedPublicKey(DELEGATOR_2.clone()); + let delegator_2_unbonding_purse = unbonding_purses_before + .get(&unbond_kind) + .expect("should have unbonding purse entry") + .first() + .expect("must have unbond") + .eras() + .first() + .expect("should have unbonding purse"); + + assert_eq!(validator_1_era.amount(), &U512::from(VALIDATOR_1_STAKE)); + assert_eq!( + delegator_1_unbonding_purse.amount(), + &U512::from(DELEGATOR_1_STAKE) + ); + assert_eq!( + delegator_2_unbonding_purse.amount(), + &U512::from(DELEGATOR_2_STAKE) + ); + + // Process unbonding requests to verify delegators received their stakes + let validator_1 = builder + .get_entity_by_account_hash(*VALIDATOR_1_ADDR) + .expect("should have validator 1 account"); + let validator_1_balance_before = builder.get_purse_balance(validator_1.main_purse()); + + let delegator_1 = builder + .get_entity_by_account_hash(*DELEGATOR_1_ADDR) + .expect("should have delegator 1 account"); + let delegator_1_balance_before = builder.get_purse_balance(delegator_1.main_purse()); + + let delegator_2 = builder + .get_entity_by_account_hash(*DELEGATOR_2_ADDR) + .expect("should have delegator 1 account"); + let delegator_2_balance_before = builder.get_purse_balance(delegator_2.main_purse()); + + for _ in 0..=DEFAULT_UNBONDING_DELAY { + builder.run_auction(timestamp_millis, Vec::new()); + timestamp_millis += TIMESTAMP_MILLIS_INCREMENT; + } + + let validator_1_balance_after = builder.get_purse_balance(validator_1.main_purse()); + let delegator_1_balance_after = builder.get_purse_balance(delegator_1.main_purse()); + let delegator_2_balance_after = builder.get_purse_balance(delegator_2.main_purse()); + + assert_eq!( + validator_1_balance_before + U512::from(VALIDATOR_1_STAKE), + validator_1_balance_after + ); + assert_eq!( + delegator_1_balance_before + U512::from(DELEGATOR_1_STAKE), + delegator_1_balance_after + ); + assert_eq!( + delegator_2_balance_before + U512::from(DELEGATOR_2_STAKE), + delegator_2_balance_after + ); +} + #[ignore] #[test] fn should_handle_evictions() { diff --git a/execution_engine_testing/tests/src/test/system_contracts/auction_bidding.rs b/execution_engine_testing/tests/src/test/system_contracts/auction_bidding.rs index 7c8a72ad1d..cd55f15cc5 100644 --- a/execution_engine_testing/tests/src/test/system_contracts/auction_bidding.rs +++ b/execution_engine_testing/tests/src/test/system_contracts/auction_bidding.rs @@ -21,7 +21,7 @@ use casper_types::{ mint, }, ApiError, EraId, GenesisAccount, GenesisValidator, Motes, ProtocolVersion, PublicKey, - SecretKey, U512, + SecretKey, DEFAULT_MINIMUM_BID_AMOUNT, U512, }; const CONTRACT_TRANSFER_TO_ACCOUNT: &str = "transfer_to_account_u512.wasm"; @@ -93,7 +93,7 @@ fn should_run_successful_bond_and_unbond_and_slashing() { // Partial unbond // - let unbond_amount = U512::from(GENESIS_ACCOUNT_STAKE) - 1; + let unbond_amount = U512::from(GENESIS_ACCOUNT_STAKE - DEFAULT_MINIMUM_BID_AMOUNT); let unbonding_purse = builder .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -393,7 +393,7 @@ fn should_run_successful_bond_and_unbond_with_release() { // Partial unbond // - let unbond_amount = U512::from(GENESIS_ACCOUNT_STAKE) - 1; + let unbond_amount = U512::from(GENESIS_ACCOUNT_STAKE) - DEFAULT_MINIMUM_BID_AMOUNT; let exec_request_2 = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -421,6 +421,7 @@ fn should_run_successful_bond_and_unbond_with_release() { assert!(unbond.is_validator()); let era = unbond.eras().first().expect("should have era"); + assert_eq!(*era.amount(), unbond_amount); let unbond_era_1 = era.era_of_creation(); assert_eq!(unbond_era_1, INITIAL_ERA_ID + 1); @@ -561,7 +562,7 @@ fn should_run_successful_unbond_funds_after_changing_unbonding_delay() { // Partial unbond // - let unbond_amount = U512::from(GENESIS_ACCOUNT_STAKE) - 1; + let unbond_amount = U512::from(GENESIS_ACCOUNT_STAKE) - DEFAULT_MINIMUM_BID_AMOUNT; let exec_request_2 = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, diff --git a/smart_contracts/contracts/test/ee-1217-regression/src/main.rs b/smart_contracts/contracts/test/ee-1217-regression/src/main.rs index 6feec17cc9..2b153c95fe 100644 --- a/smart_contracts/contracts/test/ee-1217-regression/src/main.rs +++ b/smart_contracts/contracts/test/ee-1217-regression/src/main.rs @@ -31,7 +31,7 @@ fn add_bid() { let auction = system::get_auction(); let args = runtime_args! { auction::ARG_PUBLIC_KEY => public_key, - auction::ARG_AMOUNT => U512::one(), + auction::ARG_AMOUNT => U512::from(2), // smaller amount results in Error::BondTooSmall auction::ARG_DELEGATION_RATE => 42u8, }; runtime::call_contract::(auction, auction::METHOD_ADD_BID, args); diff --git a/storage/src/system/auction.rs b/storage/src/system/auction.rs index 7ff638b4de..6f14847213 100644 --- a/storage/src/system/auction.rs +++ b/storage/src/system/auction.rs @@ -201,7 +201,7 @@ pub trait Auction: let validator_bid_addr = BidAddr::from(public_key.clone()); let validator_bid_key = validator_bid_addr.into(); let mut validator_bid = read_validator_bid(self, &validator_bid_key)?; - let initial_amount = validator_bid.staked_amount(); + let staked_amount = validator_bid.staked_amount(); // An attempt to unbond more than is staked results in unbonding the staked amount. let unbonding_amount = U512::min(amount, validator_bid.staked_amount()); @@ -210,20 +210,20 @@ pub trait Auction: let updated_stake = validator_bid.decrease_stake(unbonding_amount, era_end_timestamp_millis)?; - detail::create_unbonding_purse( - self, - public_key.clone(), - UnbondKind::Validator(public_key.clone()), // validator is the unbonder - *validator_bid.bonding_purse(), - unbonding_amount, - None, - )?; - debug!( - "withdrawing bid for {} reducing {} by {} to {}", - validator_bid_addr, initial_amount, unbonding_amount, updated_stake + "withdrawing bid for {validator_bid_addr} reducing {staked_amount} by {unbonding_amount} to {updated_stake}", ); + // if validator stake is less than minimum_bid_amount, unbond fully and prune validator bid if updated_stake < U512::from(minimum_bid_amount) { + // create unbonding purse for full validator stake + detail::create_unbonding_purse( + self, + public_key.clone(), + UnbondKind::Validator(public_key.clone()), // validator is the unbonder + *validator_bid.bonding_purse(), + staked_amount, + None, + )?; // Unbond all delegators and zero them out let delegators = read_delegator_bids(self, &public_key)?; for mut delegator in delegators { @@ -245,6 +245,15 @@ pub trait Auction: debug!("pruning validator bid {}", validator_bid_addr); self.prune_bid(validator_bid_addr); } else { + // create unbonding purse for the unbonding amount + detail::create_unbonding_purse( + self, + public_key.clone(), + UnbondKind::Validator(public_key.clone()), // validator is the unbonder + *validator_bid.bonding_purse(), + unbonding_amount, + None, + )?; self.write_bid(validator_bid_key, BidKind::Validator(validator_bid))?; } diff --git a/types/src/chainspec/core_config.rs b/types/src/chainspec/core_config.rs index 8bf43c50cf..4371620e3d 100644 --- a/types/src/chainspec/core_config.rs +++ b/types/src/chainspec/core_config.rs @@ -44,7 +44,7 @@ pub const DEFAULT_FEE_HANDLING: FeeHandling = FeeHandling::NoFee; pub const DEFAULT_ALLOW_PREPAID: bool = false; /// Default value for minimum bid amount in motes. -pub const DEFAULT_MINIMUM_BID_AMOUNT: u64 = 1; +pub const DEFAULT_MINIMUM_BID_AMOUNT: u64 = 2; /// Default processing hold balance handling. #[allow(unused)]