diff --git a/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs b/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs index ad305a018ee0d..a75cf4008e055 100644 --- a/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs +++ b/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs @@ -538,6 +538,18 @@ pub enum EntryFunctionCall { pool_address: AccountAddress, }, + PboDelegationPoolFundDelegatorsWithLockedStake { + pool_address: AccountAddress, + delegators: Vec, + stakes: Vec, + }, + + PboDelegationPoolFundDelegatorsWithStake { + pool_address: AccountAddress, + delegators: Vec, + stakes: Vec, + }, + /// Move `amount` of coins from pending_inactive to active. PboDelegationPoolReactivateStake { pool_address: AccountAddress, @@ -1484,6 +1496,20 @@ impl EntryFunctionCall { PboDelegationPoolEnablePartialGovernanceVoting { pool_address } => { pbo_delegation_pool_enable_partial_governance_voting(pool_address) }, + PboDelegationPoolFundDelegatorsWithLockedStake { + pool_address, + delegators, + stakes, + } => pbo_delegation_pool_fund_delegators_with_locked_stake( + pool_address, + delegators, + stakes, + ), + PboDelegationPoolFundDelegatorsWithStake { + pool_address, + delegators, + stakes, + } => pbo_delegation_pool_fund_delegators_with_stake(pool_address, delegators, stakes), PboDelegationPoolReactivateStake { pool_address, amount, @@ -3235,6 +3261,52 @@ pub fn pbo_delegation_pool_enable_partial_governance_voting( )) } +pub fn pbo_delegation_pool_fund_delegators_with_locked_stake( + pool_address: AccountAddress, + delegators: Vec, + stakes: Vec, +) -> TransactionPayload { + TransactionPayload::EntryFunction(EntryFunction::new( + ModuleId::new( + AccountAddress::new([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, + ]), + ident_str!("pbo_delegation_pool").to_owned(), + ), + ident_str!("fund_delegators_with_locked_stake").to_owned(), + vec![], + vec![ + bcs::to_bytes(&pool_address).unwrap(), + bcs::to_bytes(&delegators).unwrap(), + bcs::to_bytes(&stakes).unwrap(), + ], + )) +} + +pub fn pbo_delegation_pool_fund_delegators_with_stake( + pool_address: AccountAddress, + delegators: Vec, + stakes: Vec, +) -> TransactionPayload { + TransactionPayload::EntryFunction(EntryFunction::new( + ModuleId::new( + AccountAddress::new([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, + ]), + ident_str!("pbo_delegation_pool").to_owned(), + ), + ident_str!("fund_delegators_with_stake").to_owned(), + vec![], + vec![ + bcs::to_bytes(&pool_address).unwrap(), + bcs::to_bytes(&delegators).unwrap(), + bcs::to_bytes(&stakes).unwrap(), + ], + )) +} + /// Move `amount` of coins from pending_inactive to active. pub fn pbo_delegation_pool_reactivate_stake( pool_address: AccountAddress, @@ -5870,6 +5942,38 @@ mod decoder { } } + pub fn pbo_delegation_pool_fund_delegators_with_locked_stake( + payload: &TransactionPayload, + ) -> Option { + if let TransactionPayload::EntryFunction(script) = payload { + Some( + EntryFunctionCall::PboDelegationPoolFundDelegatorsWithLockedStake { + pool_address: bcs::from_bytes(script.args().get(0)?).ok()?, + delegators: bcs::from_bytes(script.args().get(1)?).ok()?, + stakes: bcs::from_bytes(script.args().get(2)?).ok()?, + }, + ) + } else { + None + } + } + + pub fn pbo_delegation_pool_fund_delegators_with_stake( + payload: &TransactionPayload, + ) -> Option { + if let TransactionPayload::EntryFunction(script) = payload { + Some( + EntryFunctionCall::PboDelegationPoolFundDelegatorsWithStake { + pool_address: bcs::from_bytes(script.args().get(0)?).ok()?, + delegators: bcs::from_bytes(script.args().get(1)?).ok()?, + stakes: bcs::from_bytes(script.args().get(2)?).ok()?, + }, + ) + } else { + None + } + } + pub fn pbo_delegation_pool_reactivate_stake( payload: &TransactionPayload, ) -> Option { @@ -7218,6 +7322,14 @@ static SCRIPT_FUNCTION_DECODER_MAP: once_cell::sync::Lazy = b"supra_framework::pbo_delegation_pool"; @@ -277,11 +279,11 @@ module supra_framework::pbo_delegation_pool { /// Capability that represents ownership over privileged operations on the underlying stake pool. struct DelegationPoolOwnership has key, store { /// equal to address of the resource account owning the stake pool - pool_address: address, + pool_address: address } struct ObservedLockupCycle has copy, drop, store { - index: u64, + index: u64 } struct UnlockSchedule has copy, drop, store { @@ -299,11 +301,10 @@ module supra_framework::pbo_delegation_pool { // Last vesting period, 1-indexed. For example if 2 months have passed, the last vesting period, if distribution // was requested, would be 2. Default value is 0 which means there have been no vesting periods yet. last_unlock_period: u64, - cumulative_unlocked_fraction: FixedPoint64, + cumulative_unlocked_fraction: FixedPoint64 } struct DelegationPool has key { - multisig_admin: Option
, // Shares pool of `active` + `pending_active` stake active_shares: pool_u64::Pool, @@ -329,12 +330,12 @@ module supra_framework::pbo_delegation_pool { reactivate_stake_events: EventHandle, unlock_stake_events: EventHandle, withdraw_stake_events: EventHandle, - distribute_commission_events: EventHandle, + distribute_commission_events: EventHandle } struct VotingRecordKey has copy, drop, store { voter: address, - proposal_id: u64, + proposal_id: u64 } /// Track delgated voter of each delegator. @@ -349,7 +350,7 @@ module supra_framework::pbo_delegation_pool { // If != last_locked_until_secs, it means that a lockup period has passed. // This is slightly different from ObservedLockupCycle because ObservedLockupCycle cannot detect if a lockup // period is passed when there is no unlocking during the lockup period. - last_locked_until_secs: u64, + last_locked_until_secs: u64 } /// Track total voteing power of each voter. @@ -366,7 +367,7 @@ module supra_framework::pbo_delegation_pool { // If != last_locked_until_secs, it means that a lockup period has passed. // This is slightly different from ObservedLockupCycle because ObservedLockupCycle cannot detect if a lockup // period is passed when there is no unlocking during the lockup period. - last_locked_until_secs: u64, + last_locked_until_secs: u64 } /// Track governance information of a delegation(e.g. voter delegation/voting power calculation). @@ -382,48 +383,48 @@ module supra_framework::pbo_delegation_pool { create_proposal_events: EventHandle, // Note: a DelegateVotingPowerEvent event only means that the delegator tries to change its voter. The change // won't take effect until the next lockup period. - delegate_voting_power_events: EventHandle, + delegate_voting_power_events: EventHandle } struct BeneficiaryForOperator has key { - beneficiary_for_operator: address, + beneficiary_for_operator: address } struct NextCommissionPercentage has key { commission_percentage_next_lockup_cycle: u64, - effective_after_secs: u64, + effective_after_secs: u64 } struct AddStakeEvent has drop, store { pool_address: address, delegator_address: address, amount_added: u64, - add_stake_fee: u64, + add_stake_fee: u64 } struct ReactivateStakeEvent has drop, store { pool_address: address, delegator_address: address, - amount_reactivated: u64, + amount_reactivated: u64 } struct UnlockStakeEvent has drop, store { pool_address: address, delegator_address: address, - amount_unlocked: u64, + amount_unlocked: u64 } struct WithdrawStakeEvent has drop, store { pool_address: address, delegator_address: address, - amount_withdrawn: u64, + amount_withdrawn: u64 } struct DistributeCommissionEvent has drop, store { pool_address: address, operator: address, commission_active: u64, - commission_pending_inactive: u64, + commission_pending_inactive: u64 } #[event] @@ -432,14 +433,14 @@ module supra_framework::pbo_delegation_pool { operator: address, beneficiary: address, commission_active: u64, - commission_pending_inactive: u64, + commission_pending_inactive: u64 } #[event] struct DelegatorReplacemendEvent has drop, store { pool_address: address, old_delegator: address, - new_delegator: address, + new_delegator: address } struct VoteEvent has drop, store { @@ -447,33 +448,33 @@ module supra_framework::pbo_delegation_pool { proposal_id: u64, delegation_pool: address, num_votes: u64, - should_pass: bool, + should_pass: bool } struct CreateProposalEvent has drop, store { proposal_id: u64, voter: address, - delegation_pool: address, + delegation_pool: address } struct DelegateVotingPowerEvent has drop, store { pool_address: address, delegator: address, - voter: address, + voter: address } #[event] struct SetBeneficiaryForOperator has drop, store { operator: address, old_beneficiary: address, - new_beneficiary: address, + new_beneficiary: address } #[event] struct CommissionPercentageChange has drop, store { pool_address: address, owner: address, - commission_percentage_next_lockup_cycle: u64, + commission_percentage_next_lockup_cycle: u64 } #[view] @@ -498,8 +499,8 @@ module supra_framework::pbo_delegation_pool { #[view] /// Return whether a delegation pool has already enabled partial govnernance voting. public fun partial_governance_voting_enabled(pool_address: address): bool { - exists(pool_address) && stake::get_delegated_voter(pool_address) == - pool_address + exists(pool_address) + && stake::get_delegated_voter(pool_address) == pool_address } #[view] @@ -511,14 +512,19 @@ module supra_framework::pbo_delegation_pool { #[view] /// Return whether the commission percentage for the next lockup cycle is effective. - public fun is_next_commission_percentage_effective(pool_address: address): bool acquires NextCommissionPercentage { - exists(pool_address) && timestamp::now_seconds() >= borrow_global< - NextCommissionPercentage>(pool_address).effective_after_secs + public fun is_next_commission_percentage_effective( + pool_address: address + ): bool acquires NextCommissionPercentage { + exists(pool_address) + && timestamp::now_seconds() + >= borrow_global(pool_address).effective_after_secs } #[view] /// Return the operator commission percentage set on the delegation pool `pool_address`. - public fun operator_commission_percentage(pool_address: address): u64 acquires DelegationPool, NextCommissionPercentage { + public fun operator_commission_percentage( + pool_address: address + ): u64 acquires DelegationPool, NextCommissionPercentage { assert_delegation_pool_exists(pool_address); if (is_next_commission_percentage_effective(pool_address)) { operator_commission_percentage_next_lockup_cycle(pool_address) @@ -529,7 +535,9 @@ module supra_framework::pbo_delegation_pool { #[view] /// Return the operator commission percentage for the next lockup cycle. - public fun operator_commission_percentage_next_lockup_cycle(pool_address: address): u64 acquires DelegationPool, NextCommissionPercentage { + public fun operator_commission_percentage_next_lockup_cycle( + pool_address: address + ): u64 acquires DelegationPool, NextCommissionPercentage { assert_delegation_pool_exists(pool_address); if (exists(pool_address)) { borrow_global(pool_address).commission_percentage_next_lockup_cycle @@ -542,7 +550,9 @@ module supra_framework::pbo_delegation_pool { /// Return the number of delegators owning active stake within `pool_address`. public fun shareholders_count_active_pool(pool_address: address): u64 acquires DelegationPool { assert_delegation_pool_exists(pool_address); - pool_u64::shareholders_count(&borrow_global(pool_address).active_shares) + pool_u64::shareholders_count( + &borrow_global(pool_address).active_shares + ) } #[view] @@ -556,31 +566,32 @@ module supra_framework::pbo_delegation_pool { #[view] /// Return whether the given delegator has any withdrawable stake. If they recently requested to unlock /// some stake and the stake pool's lockup cycle has not ended, their coins are not withdrawable yet. - public fun get_pending_withdrawal(pool_address: address, delegator_address: address) - : (bool, u64) acquires DelegationPool { + public fun get_pending_withdrawal( + pool_address: address, delegator_address: address + ): (bool, u64) acquires DelegationPool { assert_delegation_pool_exists(pool_address); let pool = borrow_global(pool_address); - let (lockup_cycle_ended, _, pending_inactive, _, commission_pending_inactive) = calculate_stake_pool_drift( - pool - ); + let (lockup_cycle_ended, _, pending_inactive, _, commission_pending_inactive) = + calculate_stake_pool_drift(pool); - let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists(pool, - delegator_address); + let (withdrawal_exists, withdrawal_olc) = + pending_withdrawal_exists(pool, delegator_address); if (!withdrawal_exists) { // if no pending withdrawal, there is neither inactive nor pending_inactive stake - (false, 0) } else { + (false, 0) + } else { // delegator has either inactive or pending_inactive stake due to automatic withdrawals let inactive_shares = table::borrow(&pool.inactive_shares, withdrawal_olc); if (withdrawal_olc.index < pool.observed_lockup_cycle.index) { // if withdrawal's lockup cycle ended on delegation pool then it is inactive (true, pool_u64::balance(inactive_shares, delegator_address)) - } - else { + } else { pending_inactive = pool_u64::shares_to_amount_with_total_coins( inactive_shares, pool_u64::shares(inactive_shares, delegator_address), // exclude operator pending_inactive rewards not converted to shares yet - pending_inactive - commission_pending_inactive); + pending_inactive - commission_pending_inactive + ); // if withdrawal's lockup cycle ended ONLY on stake pool then it is also inactive (lockup_cycle_ended, pending_inactive) } @@ -590,39 +601,44 @@ module supra_framework::pbo_delegation_pool { #[view] /// Return total stake owned by `delegator_address` within delegation pool `pool_address` /// in each of its individual states: (`active`,`inactive`,`pending_inactive`) - public fun get_stake(pool_address: address, delegator_address: address): (u64, u64, u64) acquires DelegationPool, BeneficiaryForOperator { + public fun get_stake( + pool_address: address, delegator_address: address + ): (u64, u64, u64) acquires DelegationPool, BeneficiaryForOperator { assert_delegation_pool_exists(pool_address); let pool = borrow_global(pool_address); let (lockup_cycle_ended, active, _, commission_active, commission_pending_inactive) = - calculate_stake_pool_drift(pool); + + calculate_stake_pool_drift(pool); let total_active_shares = pool_u64::total_shares(&pool.active_shares); - let delegator_active_shares = pool_u64::shares(&pool.active_shares, - delegator_address); + let delegator_active_shares = + pool_u64::shares(&pool.active_shares, delegator_address); let (_, _, pending_active, _) = stake::get_stake(pool_address); if (pending_active == 0) { // zero `pending_active` stake indicates that either there are no `add_stake` fees or // previous epoch has ended and should identify shares owning these fees as released - total_active_shares = total_active_shares - pool_u64::shares(&pool.active_shares, - NULL_SHAREHOLDER); + total_active_shares = total_active_shares + - pool_u64::shares(&pool.active_shares, NULL_SHAREHOLDER); if (delegator_address == NULL_SHAREHOLDER) { delegator_active_shares = 0 } }; - active = pool_u64::shares_to_amount_with_total_stats(&pool.active_shares, + active = pool_u64::shares_to_amount_with_total_stats( + &pool.active_shares, delegator_active_shares, // exclude operator active rewards not converted to shares yet - active - commission_active, total_active_shares); + active - commission_active, + total_active_shares + ); // get state and stake (0 if there is none) of the pending withdrawal - let (withdrawal_inactive, withdrawal_stake) = get_pending_withdrawal(pool_address, - delegator_address); + let (withdrawal_inactive, withdrawal_stake) = + get_pending_withdrawal(pool_address, delegator_address); // report non-active stakes accordingly to the state of the pending withdrawal - let (inactive, pending_inactive) = if (withdrawal_inactive) - (withdrawal_stake, 0) - else - (0, withdrawal_stake); + let (inactive, pending_inactive) = + if (withdrawal_inactive) (withdrawal_stake, 0) + else (0, withdrawal_stake); // should also include commission rewards in case of the operator account // operator rewards are actually used to buy shares which is introducing @@ -650,19 +666,21 @@ module supra_framework::pbo_delegation_pool { /// To mitigate this, some of the added stake is extracted and fed back into the pool as placeholder /// for the rewards the remaining stake would have earned if active: /// extracted-fee = (amount - extracted-fee) * reward-rate% * (100% - operator-commission%) - public fun get_add_stake_fee(pool_address: address, amount: u64): u64 acquires DelegationPool, NextCommissionPercentage { + public fun get_add_stake_fee( + pool_address: address, amount: u64 + ): u64 acquires DelegationPool, NextCommissionPercentage { if (stake::is_current_epoch_validator(pool_address)) { - let (rewards_rate, rewards_rate_denominator) = staking_config::get_reward_rate(&staking_config::get()); + let (rewards_rate, rewards_rate_denominator) = + staking_config::get_reward_rate(&staking_config::get()); if (rewards_rate_denominator > 0) { assert_delegation_pool_exists(pool_address); - rewards_rate = rewards_rate * (MAX_FEE - operator_commission_percentage( - pool_address - )); + rewards_rate = rewards_rate + * (MAX_FEE - operator_commission_percentage(pool_address)); rewards_rate_denominator = rewards_rate_denominator * MAX_FEE; ( - (((amount as u128) * (rewards_rate as u128)) / ((rewards_rate as u128) - + (rewards_rate_denominator as u128))) as u64 + (((amount as u128) * (rewards_rate as u128)) + / ((rewards_rate as u128) + (rewards_rate_denominator as u128))) as u64 ) } else { 0 } } else { 0 } @@ -673,23 +691,24 @@ module supra_framework::pbo_delegation_pool { /// the delegation pool, implicitly its stake pool, in the special case /// the validator had gone inactive before its lockup expired. public fun can_withdraw_pending_inactive(pool_address: address): bool { - stake::get_validator_state(pool_address) == VALIDATOR_STATUS_INACTIVE && timestamp::now_seconds() - >= stake::get_lockup_secs(pool_address) + stake::get_validator_state(pool_address) == VALIDATOR_STATUS_INACTIVE + && timestamp::now_seconds() >= stake::get_lockup_secs(pool_address) } #[view] /// Return the total voting power of a delegator in a delegation pool. This function syncs DelegationPool to the /// latest state. - public fun calculate_and_update_voter_total_voting_power(pool_address: address, voter: address) - : u64 acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public fun calculate_and_update_voter_total_voting_power( + pool_address: address, voter: address + ): u64 acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { assert_partial_governance_voting_enabled(pool_address); // Delegation pool need to be synced to explain rewards(which could change the coin amount) and // commission(which could cause share transfer). synchronize_delegation_pool(pool_address); let pool = borrow_global(pool_address); let governance_records = borrow_global_mut(pool_address); - let latest_delegated_votes = update_and_borrow_mut_delegated_votes(pool, - governance_records, voter); + let latest_delegated_votes = + update_and_borrow_mut_delegated_votes(pool, governance_records, voter); calculate_total_voting_power(pool, latest_delegated_votes) } @@ -700,11 +719,11 @@ module supra_framework::pbo_delegation_pool { pool_address: address, delegator_address: address ): address acquires DelegationPool, GovernanceRecords { assert_partial_governance_voting_enabled(pool_address); - calculate_and_update_delegator_voter_internal(borrow_global( - pool_address - ), + calculate_and_update_delegator_voter_internal( + borrow_global(pool_address), borrow_global_mut(pool_address), - delegator_address) + delegator_address + ) } #[view] @@ -738,67 +757,98 @@ module supra_framework::pbo_delegation_pool { unlock_numerators: vector, unlock_denominator: u64, unlock_start_time: u64, - unlock_duration: u64, + unlock_duration: u64 ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { //if there is an admin, it must be a multisig if (option::is_some
(&multisig_admin)) { // `ms_admin` is guaranteed to be NOT `@0x0` here let ms_admin = option::get_with_default
(&multisig_admin, @0x0); - assert!(ms_admin != @0x0, error::invalid_argument(EADMIN_ADDRESS_CANNOT_BE_ZERO)); - assert!(multisig_account::num_signatures_required(ms_admin) >= 2, - EADMIN_NOT_MULTISIG); + assert!( + ms_admin != @0x0, + error::invalid_argument(EADMIN_ADDRESS_CANNOT_BE_ZERO) + ); + assert!( + multisig_account::num_signatures_required(ms_admin) >= 2, + EADMIN_NOT_MULTISIG + ); }; // fail if the length of delegator_address and principle_stake is not the same - assert!(vector::length(&delegator_address) == vector::length(&principle_stake), - error::invalid_argument(EVECTOR_LENGTH_NOT_SAME)); + assert!( + vector::length(&delegator_address) == vector::length(&principle_stake), + error::invalid_argument(EVECTOR_LENGTH_NOT_SAME) + ); //Delegation pool must be enabled - assert!(features::delegation_pools_enabled(), - error::invalid_state(EDELEGATION_POOLS_DISABLED)); + assert!( + features::delegation_pools_enabled(), + error::invalid_state(EDELEGATION_POOLS_DISABLED) + ); //Unlock start time can not be in the past - assert!(unlock_start_time >= timestamp::now_seconds(), - error::invalid_argument(ESTARTUP_TIME_IN_PAST)); + assert!( + unlock_start_time >= timestamp::now_seconds(), + error::invalid_argument(ESTARTUP_TIME_IN_PAST) + ); //Unlock duration can not be zero assert!(unlock_duration > 0, error::invalid_argument(EPERIOD_DURATION_IS_ZERO)); //Fraction denominator can not be zero assert!(unlock_denominator != 0, error::invalid_argument(EDENOMINATOR_IS_ZERO)); //Fraction numerators can not be empty - assert!(vector::length(&unlock_numerators) > 0, - error::invalid_argument(EEMPTY_UNLOCK_SCHEDULE)); + assert!( + vector::length(&unlock_numerators) > 0, + error::invalid_argument(EEMPTY_UNLOCK_SCHEDULE) + ); //Fraction numerators can not be zero - assert!(!vector::any(&unlock_numerators, |e| { *e == 0 }), - error::invalid_argument(ESCHEDULE_WITH_ZERO_FRACTION)); + assert!( + !vector::any(&unlock_numerators, |e| { *e == 0 }), + error::invalid_argument(ESCHEDULE_WITH_ZERO_FRACTION) + ); let sum = vector::foldr(unlock_numerators, 0, |e, a| { e + a }); //Sum of numerators can not be greater than denominators - assert!(sum <= unlock_denominator, - error::invalid_argument(ENUMERATORS_GRATER_THAN_DENOMINATOR)); + assert!( + sum <= unlock_denominator, + error::invalid_argument(ENUMERATORS_GRATER_THAN_DENOMINATOR) + ); let owner_address = signer::address_of(owner); - assert!(!owner_cap_exists(owner_address), - error::already_exists(EOWNER_CAP_ALREADY_EXISTS)); - assert!(operator_commission_percentage <= MAX_FEE, - error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE)); + assert!( + !owner_cap_exists(owner_address), + error::already_exists(EOWNER_CAP_ALREADY_EXISTS) + ); + assert!( + operator_commission_percentage <= MAX_FEE, + error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE) + ); let sum = vector::fold(principle_stake, 0, |a, e| { a + e }); // fail if the value of coin and the sum of principle_stake is not the same - assert!(coin::value(&coin) == sum, - error::invalid_state(ECOIN_VALUE_NOT_SAME_AS_PRINCIPAL_STAKE)); + assert!( + coin::value(&coin) == sum, + error::invalid_state(ECOIN_VALUE_NOT_SAME_AS_PRINCIPAL_STAKE) + ); // generate a seed to be used to create the resource account hosting the delegation pool let seed = create_resource_account_seed(delegation_pool_creation_seed); - let (stake_pool_signer, stake_pool_signer_cap) = account::create_resource_account(owner, seed); + let (stake_pool_signer, stake_pool_signer_cap) = + account::create_resource_account(owner, seed); coin::register(&stake_pool_signer); // stake_pool_signer will be owner of the stake pool and have its `stake::OwnerCapability` let pool_address = signer::address_of(&stake_pool_signer); - stake::initialize_stake_owner(&stake_pool_signer, 0, owner_address, owner_address); + stake::initialize_stake_owner( + &stake_pool_signer, + 0, + owner_address, + owner_address + ); coin::deposit(pool_address, coin); let inactive_shares = table::new(); - table::add(&mut inactive_shares, + table::add( + &mut inactive_shares, olc_with_index(0), - pool_u64::create_with_scaling_factor(SHARES_SCALING_FACTOR)); + pool_u64::create_with_scaling_factor(SHARES_SCALING_FACTOR) + ); let delegator_address_copy = copy delegator_address; let principle_stake_copy = copy principle_stake; @@ -813,14 +863,19 @@ module supra_framework::pbo_delegation_pool { //Create unlock schedule let schedule = vector::empty(); - vector::for_each_ref(&unlock_numerators, + vector::for_each_ref( + &unlock_numerators, |e| { - let fraction = fixed_point64::create_from_rational((*e as u128), - (unlock_denominator as u128)); + let fraction = + fixed_point64::create_from_rational( + (*e as u128), (unlock_denominator as u128) + ); vector::push_back(&mut schedule, fraction); - }); + } + ); - move_to(&stake_pool_signer, + move_to( + &stake_pool_signer, DelegationPool { multisig_admin: multisig_admin, active_shares: pool_u64::create_with_scaling_factor(SHARES_SCALING_FACTOR), @@ -835,15 +890,27 @@ module supra_framework::pbo_delegation_pool { start_timestamp_secs: unlock_start_time, period_duration: unlock_duration, last_unlock_period: 0, - cumulative_unlocked_fraction: fixed_point64::create_from_rational(0, 1), + cumulative_unlocked_fraction: fixed_point64::create_from_rational( + 0, 1 + ) }, principle_stake: principle_stake_table, - add_stake_events: account::new_event_handle(&stake_pool_signer), - reactivate_stake_events: account::new_event_handle(&stake_pool_signer), - unlock_stake_events: account::new_event_handle(&stake_pool_signer), - withdraw_stake_events: account::new_event_handle(&stake_pool_signer), - distribute_commission_events: account::new_event_handle(&stake_pool_signer), - }); + add_stake_events: account::new_event_handle( + &stake_pool_signer + ), + reactivate_stake_events: account::new_event_handle( + &stake_pool_signer + ), + unlock_stake_events: account::new_event_handle( + &stake_pool_signer + ), + withdraw_stake_events: account::new_event_handle( + &stake_pool_signer + ), + distribute_commission_events: account::new_event_handle< + DistributeCommissionEvent>(&stake_pool_signer) + } + ); // save delegation pool ownership and resource account address (inner stake pool address) on `owner` move_to(owner, DelegationPoolOwnership { pool_address }); @@ -856,16 +923,84 @@ module supra_framework::pbo_delegation_pool { }; let (active_stake, _, _, _) = stake::get_stake(pool_address); // fail if coin in StakePool.active does not match with the balance in active_shares pool. - assert!(active_stake == pool_u64::total_coins(&borrow_global( - pool_address - ).active_shares), - error::invalid_state(EACTIVE_COIN_VALUE_NOT_SAME_STAKE_DELEGATION_POOL)); + assert!( + active_stake + == pool_u64::total_coins( + &borrow_global(pool_address).active_shares + ), + error::invalid_state(EACTIVE_COIN_VALUE_NOT_SAME_STAKE_DELEGATION_POOL) + ); // All delegation pool enable partial governace voting by default once the feature flag is enabled. - if (features::partial_governance_voting_enabled() && features::delegation_pool_partial_governance_voting_enabled()) { + if (features::partial_governance_voting_enabled() + && features::delegation_pool_partial_governance_voting_enabled()) { enable_partial_governance_voting(pool_address); } } + public entry fun fund_delegators_with_locked_stake( + funder: &signer, + pool_address: address, + delegators: vector
, + stakes: vector + ) acquires DelegationPool, BeneficiaryForOperator, GovernanceRecords, NextCommissionPercentage { + { + assert!( + is_admin(signer::address_of(funder), pool_address), + error::permission_denied(ENOT_AUTHORIZED) + ); + }; + let principle_stake_table = + &mut (borrow_global_mut(pool_address).principle_stake); + + vector::zip_reverse( + delegators, + stakes, + |delegator, stake| { + //Ignore if stake to be added is `0` + if (stake > 0) { + //Compute the actual stake that would be added, `principle_stake` has to be + //populated in the table accordingly + if (table::contains(principle_stake_table, delegator)) { + let stake_amount = + table::borrow_mut(principle_stake_table, delegator); + *stake_amount = *stake_amount + stake; + } else { + table::add(principle_stake_table, delegator, stake); + } + } + } + ); + + fund_delegators_with_stake(funder, pool_address, delegators, stakes); + } + + public entry fun fund_delegators_with_stake( + funder: &signer, + pool_address: address, + delegators: vector
, + stakes: vector + ) acquires DelegationPool, BeneficiaryForOperator, GovernanceRecords, NextCommissionPercentage { + //length equality check is performed by `zip_reverse` + vector::zip_reverse( + delegators, + stakes, + |delegator, stake| { + fund_delegator_stake(funder, pool_address, delegator, stake); + } + ); + + } + + #[view] + public fun is_admin(user_addr: address, pool_address: address): bool acquires DelegationPool { + let option_multisig = get_admin(pool_address); + if (!option::is_some(&option_multisig)) { + return false + } else { + user_addr == *option::borrow(&option_multisig) + } + } + #[view] public fun get_admin(pool_address: address): option::Option
acquires DelegationPool { return borrow_global(pool_address).multisig_admin @@ -876,16 +1011,24 @@ module supra_framework::pbo_delegation_pool { public fun beneficiary_for_operator(operator: address): address acquires BeneficiaryForOperator { if (exists(operator)) { return borrow_global(operator).beneficiary_for_operator - } else { operator } + } else { + operator + } } /// Enable partial governance voting on a stake pool. The voter of this stake pool will be managed by this module. /// THe existing voter will be replaced. The function is permissionless. - public entry fun enable_partial_governance_voting(pool_address: address,) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { - assert!(features::partial_governance_voting_enabled(), - error::invalid_state(EDISABLED_FUNCTION)); - assert!(features::delegation_pool_partial_governance_voting_enabled(), - error::invalid_state(EDISABLED_FUNCTION)); + public entry fun enable_partial_governance_voting( + pool_address: address + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + assert!( + features::partial_governance_voting_enabled(), + error::invalid_state(EDISABLED_FUNCTION) + ); + assert!( + features::delegation_pool_partial_governance_voting_enabled(), + error::invalid_state(EDISABLED_FUNCTION) + ); assert_delegation_pool_exists(pool_address); // synchronize delegation and stake pools before any user operation. synchronize_delegation_pool(pool_address); @@ -894,19 +1037,25 @@ module supra_framework::pbo_delegation_pool { let stake_pool_signer = retrieve_stake_pool_owner(delegation_pool); // delegated_voter is managed by the stake pool itself, which signer capability is managed by DelegationPool. // So voting power of this stake pool can only be used through this module. - stake::set_delegated_voter(&stake_pool_signer, - signer::address_of(&stake_pool_signer)); + stake::set_delegated_voter( + &stake_pool_signer, signer::address_of(&stake_pool_signer) + ); - move_to(&stake_pool_signer, + move_to( + &stake_pool_signer, GovernanceRecords { votes: smart_table::new(), votes_per_proposal: smart_table::new(), vote_delegation: smart_table::new(), delegated_votes: smart_table::new(), vote_events: account::new_event_handle(&stake_pool_signer), - create_proposal_events: account::new_event_handle(&stake_pool_signer), - delegate_voting_power_events: account::new_event_handle(&stake_pool_signer), - }); + create_proposal_events: account::new_event_handle( + &stake_pool_signer + ), + delegate_voting_power_events: account::new_event_handle< + DelegateVotingPowerEvent>(&stake_pool_signer) + } + ); } fun assert_owner_cap_exists(owner: address) { @@ -914,35 +1063,50 @@ module supra_framework::pbo_delegation_pool { } fun assert_delegation_pool_exists(pool_address: address) { - assert!(delegation_pool_exists(pool_address), - error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST)); + assert!( + delegation_pool_exists(pool_address), + error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST) + ); } - fun assert_min_active_balance(pool: &DelegationPool, delegator_address: address) { + fun assert_min_active_balance( + pool: &DelegationPool, delegator_address: address + ) { let balance = pool_u64::balance(&pool.active_shares, delegator_address); - assert!(balance >= MIN_COINS_ON_SHARES_POOL, - error::invalid_argument(EDELEGATOR_ACTIVE_BALANCE_TOO_LOW)); + assert!( + balance >= MIN_COINS_ON_SHARES_POOL, + error::invalid_argument(EDELEGATOR_ACTIVE_BALANCE_TOO_LOW) + ); } - fun assert_min_pending_inactive_balance(pool: &DelegationPool, delegator_address: address) { - let balance = pool_u64::balance(pending_inactive_shares_pool(pool), - delegator_address); - assert!(balance >= MIN_COINS_ON_SHARES_POOL, - error::invalid_argument(EDELEGATOR_PENDING_INACTIVE_BALANCE_TOO_LOW)); + fun assert_min_pending_inactive_balance( + pool: &DelegationPool, delegator_address: address + ) { + let balance = + pool_u64::balance(pending_inactive_shares_pool(pool), delegator_address); + assert!( + balance >= MIN_COINS_ON_SHARES_POOL, + error::invalid_argument(EDELEGATOR_PENDING_INACTIVE_BALANCE_TOO_LOW) + ); } fun assert_partial_governance_voting_enabled(pool_address: address) { assert_delegation_pool_exists(pool_address); - assert!(partial_governance_voting_enabled(pool_address), - error::invalid_state(EPARTIAL_GOVERNANCE_VOTING_NOT_ENABLED)); + assert!( + partial_governance_voting_enabled(pool_address), + error::invalid_state(EPARTIAL_GOVERNANCE_VOTING_NOT_ENABLED) + ); } fun coins_to_redeem_to_ensure_min_stake( - src_shares_pool: &pool_u64::Pool, shareholder: address, amount: u64, + src_shares_pool: &pool_u64::Pool, shareholder: address, amount: u64 ): u64 { // find how many coins would be redeemed if supplying `amount` - let redeemed_coins = pool_u64::shares_to_amount(src_shares_pool, - amount_to_shares_to_redeem(src_shares_pool, shareholder, amount)); + let redeemed_coins = + pool_u64::shares_to_amount( + src_shares_pool, + amount_to_shares_to_redeem(src_shares_pool, shareholder, amount) + ); // if balance drops under threshold then redeem it entirely let src_balance = pool_u64::balance(src_shares_pool, shareholder); if (src_balance - redeemed_coins < MIN_COINS_ON_SHARES_POOL) { @@ -955,11 +1119,14 @@ module supra_framework::pbo_delegation_pool { src_shares_pool: &pool_u64::Pool, dst_shares_pool: &pool_u64::Pool, shareholder: address, - amount: u64, + amount: u64 ): u64 { // find how many coins would be redeemed from source if supplying `amount` - let redeemed_coins = pool_u64::shares_to_amount(src_shares_pool, - amount_to_shares_to_redeem(src_shares_pool, shareholder, amount)); + let redeemed_coins = + pool_u64::shares_to_amount( + src_shares_pool, + amount_to_shares_to_redeem(src_shares_pool, shareholder, amount) + ); // if balance on destination would be less than threshold then redeem difference to threshold let dst_balance = pool_u64::balance(dst_shares_pool, shareholder); if (dst_balance + redeemed_coins < MIN_COINS_ON_SHARES_POOL) { @@ -982,12 +1149,16 @@ module supra_framework::pbo_delegation_pool { } /// Get the active share amount of the delegator. - fun get_delegator_active_shares(pool: &DelegationPool, delegator: address): u128 { + fun get_delegator_active_shares( + pool: &DelegationPool, delegator: address + ): u128 { pool_u64::shares(&pool.active_shares, delegator) } /// Get the pending inactive share amount of the delegator. - fun get_delegator_pending_inactive_shares(pool: &DelegationPool, delegator: address): u128 { + fun get_delegator_pending_inactive_shares( + pool: &DelegationPool, delegator: address + ): u128 { pool_u64::shares(pending_inactive_shares_pool(pool), delegator) } @@ -996,12 +1167,14 @@ module supra_framework::pbo_delegation_pool { governance_records: &GovernanceRecords, voter: address, proposal_id: u64 ): u64 { let votes = &governance_records.votes; - let key = VotingRecordKey { voter, proposal_id, }; + let key = VotingRecordKey { voter, proposal_id }; *smart_table::borrow_with_default(votes, key, &0) } /// Create the seed to derive the resource account address. - fun create_resource_account_seed(delegation_pool_creation_seed: vector,): vector { + fun create_resource_account_seed( + delegation_pool_creation_seed: vector + ): vector { let seed = vector::empty(); // include module salt (before any subseeds) to avoid conflicts with other modules creating resource accounts vector::append(&mut seed, MODULE_SALT); @@ -1015,13 +1188,15 @@ module supra_framework::pbo_delegation_pool { governance_records: &mut GovernanceRecords, voter: address, proposal_id: u64 ): &mut u64 { let votes = &mut governance_records.votes; - let key = VotingRecordKey { proposal_id, voter, }; + let key = VotingRecordKey { proposal_id, voter }; smart_table::borrow_mut_with_default(votes, key, 0) } /// Update VoteDelegation of a delegator to up-to-date then borrow_mut it. fun update_and_borrow_mut_delegator_vote_delegation( - pool: &DelegationPool, governance_records: &mut GovernanceRecords, delegator: address + pool: &DelegationPool, + governance_records: &mut GovernanceRecords, + delegator: address ): &mut VoteDelegation { let pool_address = get_pool_address(pool); let locked_until_secs = stake::get_lockup_secs(pool_address); @@ -1030,20 +1205,21 @@ module supra_framework::pbo_delegation_pool { // By default, a delegator's delegated voter is itself. // TODO: recycle storage when VoteDelegation equals to default value. if (!smart_table::contains(vote_delegation_table, delegator)) { - return smart_table::borrow_mut_with_default(vote_delegation_table, + return smart_table::borrow_mut_with_default( + vote_delegation_table, delegator, VoteDelegation { voter: delegator, last_locked_until_secs: locked_until_secs, - pending_voter: delegator, + pending_voter: delegator } ) }; let vote_delegation = smart_table::borrow_mut(vote_delegation_table, delegator); // A lockup period has passed since last time `vote_delegation` was updated. Pending voter takes effect. - if (vote_delegation.last_locked_until_secs < locked_until_secs && vote_delegation.voter != vote_delegation - .pending_voter) { + if (vote_delegation.last_locked_until_secs < locked_until_secs + && vote_delegation.voter != vote_delegation.pending_voter) { vote_delegation.voter = vote_delegation.pending_voter; }; vote_delegation @@ -1062,13 +1238,14 @@ module supra_framework::pbo_delegation_pool { if (!smart_table::contains(delegated_votes_per_voter, voter)) { let active_shares = get_delegator_active_shares(pool, voter); let inactive_shares = get_delegator_pending_inactive_shares(pool, voter); - return smart_table::borrow_mut_with_default(delegated_votes_per_voter, + return smart_table::borrow_mut_with_default( + delegated_votes_per_voter, voter, DelegatedVotes { active_shares, pending_inactive_shares: inactive_shares, active_shares_next_lockup: active_shares, - last_locked_until_secs: locked_until_secs, + last_locked_until_secs: locked_until_secs } ) }; @@ -1092,20 +1269,28 @@ module supra_framework::pbo_delegation_pool { fun calculate_total_voting_power( delegation_pool: &DelegationPool, latest_delegated_votes: &DelegatedVotes ): u64 { - let active_amount = pool_u64::shares_to_amount(&delegation_pool.active_shares, - latest_delegated_votes.active_shares); - let pending_inactive_amount = pool_u64::shares_to_amount( - pending_inactive_shares_pool(delegation_pool), - latest_delegated_votes.pending_inactive_shares); + let active_amount = + pool_u64::shares_to_amount( + &delegation_pool.active_shares, latest_delegated_votes.active_shares + ); + let pending_inactive_amount = + pool_u64::shares_to_amount( + pending_inactive_shares_pool(delegation_pool), + latest_delegated_votes.pending_inactive_shares + ); active_amount + pending_inactive_amount } /// Update VoteDelegation of a delegator to up-to-date then return the latest voter. fun calculate_and_update_delegator_voter_internal( - pool: &DelegationPool, governance_records: &mut GovernanceRecords, delegator: address + pool: &DelegationPool, + governance_records: &mut GovernanceRecords, + delegator: address ): address { - let vote_delegation = update_and_borrow_mut_delegator_vote_delegation(pool, - governance_records, delegator); + let vote_delegation = + update_and_borrow_mut_delegator_vote_delegation( + pool, governance_records, delegator + ); vote_delegation.voter } @@ -1113,61 +1298,83 @@ module supra_framework::pbo_delegation_pool { fun calculate_and_update_delegated_votes( pool: &DelegationPool, governance_records: &mut GovernanceRecords, voter: address ): u64 { - let delegated_votes = update_and_borrow_mut_delegated_votes(pool, governance_records, - voter); + let delegated_votes = + update_and_borrow_mut_delegated_votes(pool, governance_records, voter); calculate_total_voting_power(pool, delegated_votes) } /// Allows an owner to change the operator of the underlying stake pool. - public entry fun set_operator(owner: &signer, new_operator: address) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun set_operator( + owner: &signer, new_operator: address + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { let pool_address = get_owned_pool_address(signer::address_of(owner)); // synchronize delegation and stake pools before any user operation // ensure the old operator is paid its uncommitted commission rewards synchronize_delegation_pool(pool_address); - stake::set_operator(&retrieve_stake_pool_owner(borrow_global( - pool_address - )), new_operator); + stake::set_operator( + &retrieve_stake_pool_owner(borrow_global(pool_address)), + new_operator + ); } /// Allows an operator to change its beneficiary. Any existing unpaid commission rewards will be paid to the new /// beneficiary. To ensures payment to the current beneficiary, one should first call `synchronize_delegation_pool` /// before switching the beneficiary. An operator can set one beneficiary for delegation pools, not a separate /// one for each pool. - public entry fun set_beneficiary_for_operator(operator: &signer, new_beneficiary: address) acquires BeneficiaryForOperator { - assert!(features::operator_beneficiary_change_enabled(), - std::error::invalid_state(EOPERATOR_BENEFICIARY_CHANGE_NOT_SUPPORTED)); + public entry fun set_beneficiary_for_operator( + operator: &signer, new_beneficiary: address + ) acquires BeneficiaryForOperator { + assert!( + features::operator_beneficiary_change_enabled(), + std::error::invalid_state(EOPERATOR_BENEFICIARY_CHANGE_NOT_SUPPORTED) + ); // The beneficiay address of an operator is stored under the operator's address. // So, the operator does not need to be validated with respect to a staking pool. let operator_addr = signer::address_of(operator); let old_beneficiary = beneficiary_for_operator(operator_addr); if (exists(operator_addr)) { borrow_global_mut(operator_addr).beneficiary_for_operator = - new_beneficiary; + new_beneficiary; } else { - move_to(operator, BeneficiaryForOperator { - beneficiary_for_operator: new_beneficiary - }); + move_to( + operator, + BeneficiaryForOperator { beneficiary_for_operator: new_beneficiary } + ); }; - emit(SetBeneficiaryForOperator { + emit( + SetBeneficiaryForOperator { operator: operator_addr, old_beneficiary, - new_beneficiary, - }); + new_beneficiary + } + ); } /// Allows an owner to update the commission percentage for the operator of the underlying stake pool. - public entry fun update_commission_percentage(owner: &signer, new_commission_percentage: u64) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { - assert!(features::commission_change_delegation_pool_enabled(), - error::invalid_state(ECOMMISSION_RATE_CHANGE_NOT_SUPPORTED)); - assert!(new_commission_percentage <= MAX_FEE, - error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE)); + public entry fun update_commission_percentage( + owner: &signer, new_commission_percentage: u64 + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + assert!( + features::commission_change_delegation_pool_enabled(), + error::invalid_state(ECOMMISSION_RATE_CHANGE_NOT_SUPPORTED) + ); + assert!( + new_commission_percentage <= MAX_FEE, + error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE) + ); let owner_address = signer::address_of(owner); let pool_address = get_owned_pool_address(owner_address); - assert!(operator_commission_percentage(pool_address) + MAX_COMMISSION_INCREASE >= new_commission_percentage, - error::invalid_argument(ETOO_LARGE_COMMISSION_INCREASE)); - assert!(stake::get_remaining_lockup_secs(pool_address) >= min_remaining_secs_for_commission_change(), - error::invalid_state(ETOO_LATE_COMMISSION_CHANGE)); + assert!( + operator_commission_percentage(pool_address) + MAX_COMMISSION_INCREASE + >= new_commission_percentage, + error::invalid_argument(ETOO_LARGE_COMMISSION_INCREASE) + ); + assert!( + stake::get_remaining_lockup_secs(pool_address) + >= min_remaining_secs_for_commission_change(), + error::invalid_state(ETOO_LATE_COMMISSION_CHANGE) + ); // synchronize delegation and stake pools before any user operation. this ensures: // (1) the operator is paid its uncommitted commission rewards with the old commission percentage, and @@ -1175,41 +1382,52 @@ module supra_framework::pbo_delegation_pool { synchronize_delegation_pool(pool_address); if (exists(pool_address)) { - let commission_percentage = borrow_global_mut( - pool_address - ); + let commission_percentage = + borrow_global_mut(pool_address); commission_percentage.commission_percentage_next_lockup_cycle = new_commission_percentage; commission_percentage.effective_after_secs = stake::get_lockup_secs( pool_address ); } else { let delegation_pool = borrow_global(pool_address); - let pool_signer = account::create_signer_with_capability(&delegation_pool.stake_pool_signer_cap); - move_to(&pool_signer, + let pool_signer = + account::create_signer_with_capability( + &delegation_pool.stake_pool_signer_cap + ); + move_to( + &pool_signer, NextCommissionPercentage { commission_percentage_next_lockup_cycle: new_commission_percentage, - effective_after_secs: stake::get_lockup_secs(pool_address), - }); + effective_after_secs: stake::get_lockup_secs(pool_address) + } + ); }; - event::emit(CommissionPercentageChange { + event::emit( + CommissionPercentageChange { pool_address, owner: owner_address, - commission_percentage_next_lockup_cycle: new_commission_percentage, - }); + commission_percentage_next_lockup_cycle: new_commission_percentage + } + ); } /// Allows an owner to change the delegated voter of the underlying stake pool. - public entry fun set_delegated_voter(owner: &signer, new_voter: address) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun set_delegated_voter( + owner: &signer, new_voter: address + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { // No one can change delegated_voter once the partial governance voting feature is enabled. - assert!(!features::delegation_pool_partial_governance_voting_enabled(), - error::invalid_state(EDEPRECATED_FUNCTION)); + assert!( + !features::delegation_pool_partial_governance_voting_enabled(), + error::invalid_state(EDEPRECATED_FUNCTION) + ); let pool_address = get_owned_pool_address(signer::address_of(owner)); // synchronize delegation and stake pools before any user operation synchronize_delegation_pool(pool_address); - stake::set_delegated_voter(&retrieve_stake_pool_owner(borrow_global( - pool_address - )), new_voter); + stake::set_delegated_voter( + &retrieve_stake_pool_owner(borrow_global(pool_address)), + new_voter + ); } /// Allows a delegator to delegate its voting power to a voter. If this delegator already has a delegated voter, @@ -1225,41 +1443,48 @@ module supra_framework::pbo_delegation_pool { let delegator_address = signer::address_of(delegator); let delegation_pool = borrow_global(pool_address); let governance_records = borrow_global_mut(pool_address); - let delegator_vote_delegation = update_and_borrow_mut_delegator_vote_delegation( - delegation_pool, governance_records, delegator_address - ); + let delegator_vote_delegation = + update_and_borrow_mut_delegator_vote_delegation( + delegation_pool, governance_records, delegator_address + ); let pending_voter: address = delegator_vote_delegation.pending_voter; // No need to update if the voter doesn't really change. if (pending_voter != new_voter) { delegator_vote_delegation.pending_voter = new_voter; - let active_shares = get_delegator_active_shares(delegation_pool, - delegator_address); + let active_shares = + get_delegator_active_shares(delegation_pool, delegator_address); // of -= // of += - let pending_delegated_votes = update_and_borrow_mut_delegated_votes( - delegation_pool, governance_records, pending_voter - ); + let pending_delegated_votes = + update_and_borrow_mut_delegated_votes( + delegation_pool, governance_records, pending_voter + ); pending_delegated_votes.active_shares_next_lockup = pending_delegated_votes.active_shares_next_lockup - active_shares; - let new_delegated_votes = update_and_borrow_mut_delegated_votes(delegation_pool, - governance_records, new_voter); + let new_delegated_votes = + update_and_borrow_mut_delegated_votes( + delegation_pool, governance_records, new_voter + ); new_delegated_votes.active_shares_next_lockup = new_delegated_votes.active_shares_next_lockup + active_shares; }; - event::emit_event(&mut governance_records.delegate_voting_power_events, + event::emit_event( + &mut governance_records.delegate_voting_power_events, DelegateVotingPowerEvent { pool_address, delegator: delegator_address, - voter: new_voter, + voter: new_voter } ); } /// Add `amount` of coins to the delegation pool `pool_address` during initialization of pool. - fun add_stake_initialization(delegator_address: address, pool_address: address, amount: u64) acquires DelegationPool, GovernanceRecords { + fun add_stake_initialization( + delegator_address: address, pool_address: address, amount: u64 + ) acquires DelegationPool, GovernanceRecords { // short-circuit if amount to add is 0 so no event is emitted if (amount == 0) { return }; @@ -1271,8 +1496,12 @@ module supra_framework::pbo_delegation_pool { assert_min_active_balance(pool, delegator_address); } - /// Add `amount` of coins to the delegation pool `pool_address`. - public entry fun add_stake(delegator: &signer, pool_address: address, amount: u64) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + fun fund_delegator_stake( + funder: &signer, + pool_address: address, + delegator_address: address, + amount: u64 + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { // short-circuit if amount to add is 0 so no event is emitted if (amount == 0) { return }; // synchronize delegation and stake pools before any user operation @@ -1281,11 +1510,10 @@ module supra_framework::pbo_delegation_pool { // fee to be charged for adding `amount` stake on this delegation pool at this epoch let add_stake_fee = get_add_stake_fee(pool_address, amount); + supra_account::transfer(funder, pool_address, amount); let pool = borrow_global_mut(pool_address); - let delegator_address = signer::address_of(delegator); // stake the entire amount to the stake pool - supra_account::transfer(delegator, pool_address, amount); stake::add_stake(&retrieve_stake_pool_owner(pool), amount); // but buy shares for delegator just for the remaining amount after fee @@ -1298,18 +1526,34 @@ module supra_framework::pbo_delegation_pool { // in order to appreciate all shares on the active pool atomically buy_in_active_shares(pool, NULL_SHAREHOLDER, add_stake_fee); - event::emit_event(&mut pool.add_stake_events, + event::emit_event( + &mut pool.add_stake_events, AddStakeEvent { pool_address, delegator_address, amount_added: amount, - add_stake_fee, - }, + add_stake_fee + } ); + + } + + /// Add `amount` of coins to the delegation pool `pool_address`. + public entry fun add_stake( + delegator: &signer, pool_address: address, amount: u64 + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + fund_delegator_stake( + delegator, + pool_address, + signer::address_of(delegator), + amount + ) } fun replace_in_smart_tables( - table: &mut SmartTable, old_entry: Key, new_entry: Key + table: &mut SmartTable, + old_entry: Key, + new_entry: Key ) { if (smart_table::contains(table, old_entry)) { let val = smart_table::remove(table, old_entry); @@ -1322,43 +1566,61 @@ module supra_framework::pbo_delegation_pool { /// owner of `new_delegator` , Only for those stakeholders which were added at the time of creation /// This does not apply to anyone who added stake later or operator public entry fun replace_delegator( - multisig_admin: &signer, pool_address: address, old_delegator: address, new_delegator: address + multisig_admin: &signer, + pool_address: address, + old_delegator: address, + new_delegator: address ) acquires DelegationPool, GovernanceRecords { + //Ensure that authorized admin is calling + let admin_addr = signer::address_of(multisig_admin); + assert!( + is_admin(admin_addr, pool_address), + error::permission_denied(ENOT_AUTHORIZED) + ); //Ensure replacement address is different - assert!(old_delegator != new_delegator, - error::invalid_argument(ENEW_IS_SAME_AS_OLD_DELEGATOR)); + assert!( + old_delegator != new_delegator, + error::invalid_argument(ENEW_IS_SAME_AS_OLD_DELEGATOR) + ); //Ensure it is a valid `pool_addres` - assert!(exists(pool_address), - error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST)); + assert!( + exists(pool_address), + error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST) + ); let pool: &mut DelegationPool = borrow_global_mut(pool_address); - let admin_addr = signer::address_of(multisig_admin); - //Ensure that authorized admin is calling - assert!(admin_addr != @0x0, error::invalid_argument(EADMIN_ADDRESS_CANNOT_BE_ZERO)); - assert!(admin_addr == option::get_with_default(&pool.multisig_admin, @0x0), - error::permission_denied(ENOT_AUTHORIZED)); - //Ensure `old_delegator` is part of original principle stakers before commencing the replacement - assert!(table::contains(&pool.principle_stake, old_delegator), - error::unavailable(EDELEGATOR_DOES_NOT_EXIST)); + assert!( + table::contains(&pool.principle_stake, old_delegator), + error::unavailable(EDELEGATOR_DOES_NOT_EXIST) + ); //replace in `active_shares` pool { let active_pool = &mut pool.active_shares; let active_shares = pool_u64::shares(active_pool, old_delegator); - pool_u64::transfer_shares(active_pool, old_delegator, new_delegator, - active_shares); + pool_u64::transfer_shares( + active_pool, + old_delegator, + new_delegator, + active_shares + ); }; //replace in `inactive_shares` pool - let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists(pool, - old_delegator); + let (withdrawal_exists, withdrawal_olc) = + pending_withdrawal_exists(pool, old_delegator); if (withdrawal_exists) { - let inactive_pool = table::borrow_mut(&mut pool.inactive_shares, withdrawal_olc); + let inactive_pool = + table::borrow_mut(&mut pool.inactive_shares, withdrawal_olc); let inactive_shares = pool_u64::shares(inactive_pool, old_delegator); - pool_u64::transfer_shares(inactive_pool, old_delegator, new_delegator, - inactive_shares); + pool_u64::transfer_shares( + inactive_pool, + old_delegator, + new_delegator, + inactive_shares + ); //replace in `pending_withdrawals` { @@ -1373,28 +1635,39 @@ module supra_framework::pbo_delegation_pool { { if (features::partial_governance_voting_enabled()) { let grecords = borrow_global_mut(pool_address); - replace_in_smart_tables(&mut grecords.vote_delegation, old_delegator, - new_delegator); - replace_in_smart_tables(&mut grecords.delegated_votes, old_delegator, - new_delegator); + replace_in_smart_tables( + &mut grecords.vote_delegation, old_delegator, new_delegator + ); + replace_in_smart_tables( + &mut grecords.delegated_votes, old_delegator, new_delegator + ); let old_keys: vector = vector::empty(); let new_keys: vector = vector::empty(); - smart_table::for_each_ref(&grecords.votes, + smart_table::for_each_ref( + &grecords.votes, |key, _val| { let VotingRecordKey { voter, proposal_id } = *key; if (voter == old_delegator) { - vector::push_back(&mut new_keys, VotingRecordKey { + vector::push_back( + &mut new_keys, + VotingRecordKey { voter: new_delegator, proposal_id: proposal_id - }); + } + ); vector::push_back(&mut old_keys, *key); }; - }); + } + ); - vector::zip_ref(&old_keys, &new_keys, |old, new| { + vector::zip_ref( + &old_keys, + &new_keys, + |old, new| { replace_in_smart_tables(&mut grecords.votes, *old, *new); - }); + } + ); } }; // replace in principle_stake table @@ -1403,66 +1676,112 @@ module supra_framework::pbo_delegation_pool { table::add(&mut pool.principle_stake, new_delegator, val); }; - event::emit(DelegatorReplacemendEvent { pool_address, old_delegator, new_delegator },); + event::emit( + DelegatorReplacemendEvent { pool_address, old_delegator, new_delegator } + ); + + } + + #[view] + public fun is_principle_stakeholder( + delegator_addr: address, pool_addr: address + ): bool acquires DelegationPool { + let pool = borrow_global(pool_addr); + table::contains(&pool.principle_stake, delegator_addr) + } + #[view] + public fun get_principle_stake( + delegator_addr: address, pool_addr: address + ): u64 acquires DelegationPool { + let pool = borrow_global(pool_addr); + if (!table::contains(&pool.principle_stake, delegator_addr)) { 0 } + else { + *table::borrow(&pool.principle_stake, delegator_addr) + } } #[view] /// Provides how much amount is unlockable based on `principle_unlock_schedule.cumulative_unlocked_fraction` /// Note that `cumulative_unlocked_fraction` is not updated in this function so the information may not be /// accurate as time passes - public fun cached_unlockable_balance(delegator_addr: address, pool_addr: address): u64 acquires DelegationPool { - assert!(exists(pool_addr), - error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST)); + public fun cached_unlockable_balance( + delegator_addr: address, pool_addr: address + ): u64 acquires DelegationPool { + assert!( + exists(pool_addr), + error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST) + ); let pool = borrow_global(pool_addr); - let delegator_active_balance = pool_u64::balance(&pool.active_shares, delegator_addr); - let unlockable_fraction = pool.principle_unlock_schedule.cumulative_unlocked_fraction; - let delegator_principle_stake = *table::borrow(&pool.principle_stake, delegator_addr); + let delegator_active_balance = + pool_u64::balance(&pool.active_shares, delegator_addr); + let unlockable_fraction = + pool.principle_unlock_schedule.cumulative_unlocked_fraction; + let delegator_principle_stake = + *table::borrow(&pool.principle_stake, delegator_addr); //To avoid problem even if fraction is slightly above 1 - let unlockable_principle_stake = (math128::min(fixed_point64::multiply_u128( - (delegator_principle_stake as u128), unlockable_fraction - ), - (delegator_principle_stake as u128)) as u64); + let unlockable_principle_stake = + ( + math128::min( + fixed_point64::multiply_u128( + (delegator_principle_stake as u128), unlockable_fraction + ), + (delegator_principle_stake as u128) + ) as u64 + ); let locked_amount = delegator_principle_stake - unlockable_principle_stake; - assert!(delegator_active_balance >= locked_amount, - error::invalid_state(EDELEGATOR_ACTIVE_BALANCE_TOO_LOW)); + assert!( + delegator_active_balance >= locked_amount, + error::invalid_state(EDELEGATOR_ACTIVE_BALANCE_TOO_LOW) + ); delegator_active_balance - locked_amount } - public fun can_principle_unlock(delegator_addr: address, pool_address: address, amount: u64) - : bool acquires DelegationPool { + /// Note: this does not synchronize with stake pool, therefore the answer may be conservative + // This function may return `false` even if the amount is indeed `unlockable` + public fun can_principle_unlock( + delegator_addr: address, pool_address: address, amount: u64 + ): bool acquires DelegationPool { - let principle_stake_table = &borrow_global(pool_address).principle_stake; + let principle_stake_table = + &borrow_global(pool_address).principle_stake; if (!table::contains(principle_stake_table, delegator_addr)) { - return true + return false }; - let unlock_schedule = &mut borrow_global_mut(pool_address).principle_unlock_schedule; + let unlock_schedule = + &mut borrow_global_mut(pool_address).principle_unlock_schedule; let one = fixed_point64::create_from_rational(1, 1); - if (fixed_point64::greater_or_equal(unlock_schedule.cumulative_unlocked_fraction, one)) { + if (fixed_point64::greater_or_equal( + unlock_schedule.cumulative_unlocked_fraction, one + )) { return true }; if (unlock_schedule.start_timestamp_secs > timestamp::now_seconds()) { - let unlockable_amount = cached_unlockable_balance(delegator_addr, pool_address); + let unlockable_amount = + cached_unlockable_balance(delegator_addr, pool_address); return amount <= unlockable_amount }; //subtraction safety due to check above - let unlock_periods_passed = (timestamp::now_seconds() - unlock_schedule.start_timestamp_secs) - / unlock_schedule.period_duration; + let unlock_periods_passed = + (timestamp::now_seconds() - unlock_schedule.start_timestamp_secs) + / unlock_schedule.period_duration; let last_unlocked_period = unlock_schedule.last_unlock_period; let schedule_length = vector::length(&unlock_schedule.schedule); let cfraction = unlock_schedule.cumulative_unlocked_fraction; - while (last_unlocked_period < unlock_periods_passed && fixed_point64::less( - cfraction, one - )) { - let next_fraction = if (schedule_length <= last_unlocked_period) { - *vector::borrow(&unlock_schedule.schedule, schedule_length - 1) - } else { *vector::borrow(&unlock_schedule.schedule, last_unlocked_period) }; + while (last_unlocked_period < unlock_periods_passed + && fixed_point64::less(cfraction, one)) { + let next_fraction = + if (schedule_length <= last_unlocked_period) { + *vector::borrow(&unlock_schedule.schedule, schedule_length - 1) + } else { + *vector::borrow(&unlock_schedule.schedule, last_unlocked_period) + }; cfraction = fixed_point64::add(cfraction, next_fraction); last_unlocked_period = last_unlocked_period + 1; @@ -1477,40 +1796,57 @@ module supra_framework::pbo_delegation_pool { /// Unlock `amount` from the active + pending_active stake of `delegator` or /// at most how much active stake there is on the stake pool. - public entry fun unlock(delegator: &signer, pool_address: address, amount: u64) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun unlock( + delegator: &signer, pool_address: address, amount: u64 + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { // short-circuit if amount to unlock is 0 so no event is emitted if (amount == 0) { return }; // fail unlock of more stake than `active` on the stake pool let (active, _, _, _) = stake::get_stake(pool_address); - assert!(amount <= active, - error::invalid_argument(ENOT_ENOUGH_ACTIVE_STAKE_TO_UNLOCK)); + assert!( + amount <= active, + error::invalid_argument(ENOT_ENOUGH_ACTIVE_STAKE_TO_UNLOCK) + ); // synchronize delegation and stake pools before any user operation synchronize_delegation_pool(pool_address); let delegator_address = signer::address_of(delegator); // fail if the amount after withdraw is less than the principle stake and the lockup time is not expired - assert!(can_principle_unlock(delegator_address, pool_address, amount), - error::invalid_argument(EAMOUNT_REQUESTED_NOT_UNLOCKABLE)); + if (is_principle_stakeholder(delegator_address, pool_address)) { + assert!( + can_principle_unlock(delegator_address, pool_address, amount), + error::invalid_argument(EAMOUNT_REQUESTED_NOT_UNLOCKABLE) + ); + }; let pool = borrow_global_mut(pool_address); - amount = coins_to_transfer_to_ensure_min_stake(&pool.active_shares, - pending_inactive_shares_pool(pool), delegator_address, amount,); + amount = coins_to_transfer_to_ensure_min_stake( + &pool.active_shares, + pending_inactive_shares_pool(pool), + delegator_address, + amount + ); amount = redeem_active_shares(pool, delegator_address, amount); stake::unlock(&retrieve_stake_pool_owner(pool), amount); buy_in_pending_inactive_shares(pool, delegator_address, amount); assert_min_pending_inactive_balance(pool, delegator_address); - event::emit_event(&mut pool.unlock_stake_events, - UnlockStakeEvent { pool_address, delegator_address, amount_unlocked: amount, }, + event::emit_event( + &mut pool.unlock_stake_events, + UnlockStakeEvent { pool_address, delegator_address, amount_unlocked: amount } ); let (active_stake, _, pending_active, _) = stake::get_stake(pool_address); - assert!(active_stake + pending_active == pool_u64::total_coins(&pool.active_shares), - error::invalid_state(EACTIVE_COIN_VALUE_NOT_SAME_STAKE_DELEGATION_POOL)); + assert!( + active_stake + pending_active == pool_u64::total_coins(&pool.active_shares), + error::invalid_state(EACTIVE_COIN_VALUE_NOT_SAME_STAKE_DELEGATION_POOL) + ); } /// Move `amount` of coins from pending_inactive to active. - public entry fun reactivate_stake(delegator: &signer, pool_address: address, amount: u64) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun reactivate_stake( + delegator: &signer, pool_address: address, amount: u64 + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { // short-circuit if amount to reactivate is 0 so no event is emitted if (amount == 0) { return }; // synchronize delegation and stake pools before any user operation @@ -1519,50 +1855,81 @@ module supra_framework::pbo_delegation_pool { let pool = borrow_global_mut(pool_address); let delegator_address = signer::address_of(delegator); - amount = coins_to_transfer_to_ensure_min_stake(pending_inactive_shares_pool(pool), &pool - .active_shares, delegator_address, amount,); + amount = coins_to_transfer_to_ensure_min_stake( + pending_inactive_shares_pool(pool), + &pool.active_shares, + delegator_address, + amount + ); let observed_lockup_cycle = pool.observed_lockup_cycle; - amount = redeem_inactive_shares(pool, delegator_address, amount, - observed_lockup_cycle); + amount = redeem_inactive_shares( + pool, + delegator_address, + amount, + observed_lockup_cycle + ); stake::reactivate_stake(&retrieve_stake_pool_owner(pool), amount); buy_in_active_shares(pool, delegator_address, amount); assert_min_active_balance(pool, delegator_address); - event::emit_event(&mut pool.reactivate_stake_events, - ReactivateStakeEvent { pool_address, delegator_address, amount_reactivated: amount, }, + event::emit_event( + &mut pool.reactivate_stake_events, + ReactivateStakeEvent { + pool_address, + delegator_address, + amount_reactivated: amount + } ); } /// Withdraw `amount` of owned inactive stake from the delegation pool at `pool_address`. - public entry fun withdraw(delegator: &signer, pool_address: address, amount: u64) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun withdraw( + delegator: &signer, pool_address: address, amount: u64 + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { assert!(amount > 0, error::invalid_argument(EWITHDRAW_ZERO_STAKE)); // synchronize delegation and stake pools before any user operation synchronize_delegation_pool(pool_address); - withdraw_internal(borrow_global_mut(pool_address), - signer::address_of(delegator), amount); + withdraw_internal( + borrow_global_mut(pool_address), + signer::address_of(delegator), + amount + ); } - fun withdraw_internal(pool: &mut DelegationPool, delegator_address: address, amount: u64) acquires GovernanceRecords { + fun withdraw_internal( + pool: &mut DelegationPool, delegator_address: address, amount: u64 + ) acquires GovernanceRecords { // TODO: recycle storage when a delegator fully exits the delegation pool. // short-circuit if amount to withdraw is 0 so no event is emitted if (amount == 0) { return }; let pool_address = get_pool_address(pool); - let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists(pool, - delegator_address); + let (withdrawal_exists, withdrawal_olc) = + pending_withdrawal_exists(pool, delegator_address); // exit if no withdrawal or (it is pending and cannot withdraw pending_inactive stake from stake pool) - if (!(withdrawal_exists - && (withdrawal_olc.index < pool.observed_lockup_cycle.index || can_withdraw_pending_inactive( - pool_address - )))) { return }; + if (!( + withdrawal_exists + && ( + withdrawal_olc.index < pool.observed_lockup_cycle.index + || can_withdraw_pending_inactive(pool_address) + ) + )) { return }; if (withdrawal_olc.index == pool.observed_lockup_cycle.index) { - amount = coins_to_redeem_to_ensure_min_stake(pending_inactive_shares_pool(pool), - delegator_address, amount,) + amount = coins_to_redeem_to_ensure_min_stake( + pending_inactive_shares_pool(pool), + delegator_address, + amount + ) }; - amount = redeem_inactive_shares(pool, delegator_address, amount, withdrawal_olc); + amount = redeem_inactive_shares( + pool, + delegator_address, + amount, + withdrawal_olc + ); let stake_pool_owner = &retrieve_stake_pool_owner(pool); // stake pool will inactivate entire pending_inactive stake at `stake::withdraw` to make it withdrawable @@ -1591,20 +1958,23 @@ module supra_framework::pbo_delegation_pool { let (_, inactive, _, _) = stake::get_stake(pool_address); pool.total_coins_inactive = inactive; - event::emit_event(&mut pool.withdraw_stake_events, - WithdrawStakeEvent { pool_address, delegator_address, amount_withdrawn: amount, }, + event::emit_event( + &mut pool.withdraw_stake_events, + WithdrawStakeEvent { pool_address, delegator_address, amount_withdrawn: amount } ); } /// Return the unique observed lockup cycle where delegator `delegator_address` may have /// unlocking (or already unlocked) stake to be withdrawn from delegation pool `pool`. /// A bool is returned to signal if a pending withdrawal exists at all. - fun pending_withdrawal_exists(pool: &DelegationPool, delegator_address: address) - : (bool, - ObservedLockupCycle) { + fun pending_withdrawal_exists( + pool: &DelegationPool, delegator_address: address + ): (bool, ObservedLockupCycle) { if (table::contains(&pool.pending_withdrawals, delegator_address)) { (true, *table::borrow(&pool.pending_withdrawals, delegator_address)) - } else { (false, olc_with_index(0)) } + } else { + (false, olc_with_index(0)) + } } /// Return a mutable reference to the shares pool of `pending_inactive` stake on the @@ -1622,18 +1992,22 @@ module supra_framework::pbo_delegation_pool { /// if existing and already inactive to allow the creation of a new one. /// `pending_inactive` stake would be left untouched even if withdrawable and should /// be explicitly withdrawn by delegator - fun execute_pending_withdrawal(pool: &mut DelegationPool, delegator_address: address) acquires GovernanceRecords { - let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists(pool, - delegator_address); - if (withdrawal_exists && withdrawal_olc.index < pool.observed_lockup_cycle.index) { + fun execute_pending_withdrawal( + pool: &mut DelegationPool, delegator_address: address + ) acquires GovernanceRecords { + let (withdrawal_exists, withdrawal_olc) = + pending_withdrawal_exists(pool, delegator_address); + if (withdrawal_exists + && withdrawal_olc.index < pool.observed_lockup_cycle.index) { withdraw_internal(pool, delegator_address, MAX_U64); } } /// Buy shares into the active pool on behalf of delegator `shareholder` who /// deposited `coins_amount`. This function doesn't make any coin transfer. - fun buy_in_active_shares(pool: &mut DelegationPool, shareholder: address, coins_amount: u64,) - : u128 acquires GovernanceRecords { + fun buy_in_active_shares( + pool: &mut DelegationPool, shareholder: address, coins_amount: u64 + ): u128 acquires GovernanceRecords { let new_shares = pool_u64::amount_to_shares(&pool.active_shares, coins_amount); // No need to buy 0 shares. if (new_shares == 0) { @@ -1643,8 +2017,9 @@ module supra_framework::pbo_delegation_pool { // Always update governance records before any change to the shares pool. let pool_address = get_pool_address(pool); if (partial_governance_voting_enabled(pool_address)) { - update_governance_records_for_buy_in_active_shares(pool, pool_address, - new_shares, shareholder); + update_governance_records_for_buy_in_active_shares( + pool, pool_address, new_shares, shareholder + ); }; pool_u64::buy_in(&mut pool.active_shares, shareholder, coins_amount); @@ -1656,10 +2031,12 @@ module supra_framework::pbo_delegation_pool { /// If delegator's pending withdrawal exists and has been inactivated, execute it firstly /// to ensure there is always only one withdrawal request. fun buy_in_pending_inactive_shares( - pool: &mut DelegationPool, shareholder: address, coins_amount: u64, + pool: &mut DelegationPool, shareholder: address, coins_amount: u64 ): u128 acquires GovernanceRecords { - let new_shares = pool_u64::amount_to_shares(pending_inactive_shares_pool(pool), - coins_amount); + let new_shares = + pool_u64::amount_to_shares( + pending_inactive_shares_pool(pool), coins_amount + ); // never create a new pending withdrawal unless delegator owns some pending_inactive shares if (new_shares == 0) { return 0 @@ -1668,21 +2045,27 @@ module supra_framework::pbo_delegation_pool { // Always update governance records before any change to the shares pool. let pool_address = get_pool_address(pool); if (partial_governance_voting_enabled(pool_address)) { - update_governance_records_for_buy_in_pending_inactive_shares(pool, pool_address, - new_shares, shareholder); + update_governance_records_for_buy_in_pending_inactive_shares( + pool, pool_address, new_shares, shareholder + ); }; // cannot buy inactive shares, only pending_inactive at current lockup cycle - pool_u64::buy_in(pending_inactive_shares_pool_mut(pool), shareholder, coins_amount); + pool_u64::buy_in( + pending_inactive_shares_pool_mut(pool), shareholder, coins_amount + ); // execute the pending withdrawal if exists and is inactive before creating a new one execute_pending_withdrawal(pool, shareholder); // save observed lockup cycle for the new pending withdrawal let observed_lockup_cycle = pool.observed_lockup_cycle; - assert!(*table::borrow_mut_with_default(&mut pool.pending_withdrawals, shareholder, - observed_lockup_cycle) == observed_lockup_cycle, - error::invalid_state(EPENDING_WITHDRAWAL_EXISTS)); + assert!( + *table::borrow_mut_with_default( + &mut pool.pending_withdrawals, shareholder, observed_lockup_cycle + ) == observed_lockup_cycle, + error::invalid_state(EPENDING_WITHDRAWAL_EXISTS) + ); new_shares } @@ -1690,7 +2073,7 @@ module supra_framework::pbo_delegation_pool { /// Convert `coins_amount` of coins to be redeemed from shares pool `shares_pool` /// to the exact number of shares to redeem in order to achieve this. fun amount_to_shares_to_redeem( - shares_pool: &pool_u64::Pool, shareholder: address, coins_amount: u64, + shares_pool: &pool_u64::Pool, shareholder: address, coins_amount: u64 ): u128 { if (coins_amount >= pool_u64::balance(shares_pool, shareholder)) { // cap result at total shares of shareholder to pass `EINSUFFICIENT_SHARES` on subsequent redeem @@ -1704,18 +2087,23 @@ module supra_framework::pbo_delegation_pool { /// wants to unlock `coins_amount` of its active stake. /// Extracted coins will be used to buy shares into the pending_inactive pool and /// be available for withdrawal when current OLC ends. - fun redeem_active_shares(pool: &mut DelegationPool, shareholder: address, coins_amount: u64,) - : u64 acquires GovernanceRecords { - let shares_to_redeem = amount_to_shares_to_redeem(&pool.active_shares, shareholder, - coins_amount); + fun redeem_active_shares( + pool: &mut DelegationPool, shareholder: address, coins_amount: u64 + ): u64 acquires GovernanceRecords { + let shares_to_redeem = + amount_to_shares_to_redeem(&pool.active_shares, shareholder, coins_amount); // silently exit if not a shareholder otherwise redeem would fail with `ESHAREHOLDER_NOT_FOUND` if (shares_to_redeem == 0) return 0; // Always update governance records before any change to the shares pool. let pool_address = get_pool_address(pool); if (partial_governance_voting_enabled(pool_address)) { - update_governanace_records_for_redeem_active_shares(pool, pool_address, - shares_to_redeem, shareholder); + update_governanace_records_for_redeem_active_shares( + pool, + pool_address, + shares_to_redeem, + shareholder + ); }; pool_u64::redeem_shares(&mut pool.active_shares, shareholder, shares_to_redeem) @@ -1731,26 +2119,34 @@ module supra_framework::pbo_delegation_pool { pool: &mut DelegationPool, shareholder: address, coins_amount: u64, - lockup_cycle: ObservedLockupCycle, + lockup_cycle: ObservedLockupCycle ): u64 acquires GovernanceRecords { - let shares_to_redeem = amount_to_shares_to_redeem(table::borrow(&pool.inactive_shares, - lockup_cycle), shareholder, coins_amount); + let shares_to_redeem = + amount_to_shares_to_redeem( + table::borrow(&pool.inactive_shares, lockup_cycle), + shareholder, + coins_amount + ); // silently exit if not a shareholder otherwise redeem would fail with `ESHAREHOLDER_NOT_FOUND` if (shares_to_redeem == 0) return 0; // Always update governance records before any change to the shares pool. let pool_address = get_pool_address(pool); // Only redeem shares from the pending_inactive pool at `lockup_cycle` == current OLC. - if (partial_governance_voting_enabled(pool_address) && lockup_cycle.index == pool.observed_lockup_cycle - .index) { - update_governanace_records_for_redeem_pending_inactive_shares(pool, pool_address, - shares_to_redeem, shareholder); + if (partial_governance_voting_enabled(pool_address) + && lockup_cycle.index == pool.observed_lockup_cycle.index) { + update_governanace_records_for_redeem_pending_inactive_shares( + pool, + pool_address, + shares_to_redeem, + shareholder + ); }; let inactive_shares = table::borrow_mut(&mut pool.inactive_shares, lockup_cycle); // 1. reaching here means delegator owns inactive/pending_inactive shares at OLC `lockup_cycle` - let redeemed_coins = pool_u64::redeem_shares(inactive_shares, shareholder, - shares_to_redeem); + let redeemed_coins = + pool_u64::redeem_shares(inactive_shares, shareholder, shares_to_redeem); // if entirely reactivated pending_inactive stake or withdrawn inactive one, // re-enable unlocking for delegator by deleting this pending withdrawal @@ -1760,8 +2156,11 @@ module supra_framework::pbo_delegation_pool { table::remove(&mut pool.pending_withdrawals, shareholder); }; // destroy inactive shares pool of past OLC if all its stake has been withdrawn - if (lockup_cycle.index < pool.observed_lockup_cycle.index && total_coins(inactive_shares) == 0) { - pool_u64::destroy_empty(table::remove(&mut pool.inactive_shares, lockup_cycle)); + if (lockup_cycle.index < pool.observed_lockup_cycle.index + && total_coins(inactive_shares) == 0) { + pool_u64::destroy_empty( + table::remove(&mut pool.inactive_shares, lockup_cycle) + ); }; redeemed_coins @@ -1771,10 +2170,12 @@ module supra_framework::pbo_delegation_pool { /// capture the rewards earned in the meantime, resulted operator commission and /// whether the lockup expired on the stake pool. fun calculate_stake_pool_drift(pool: &DelegationPool): (bool, u64, u64, u64, u64) { - let (active, inactive, pending_active, pending_inactive) = stake::get_stake( - get_pool_address(pool)); - assert!(inactive >= pool.total_coins_inactive, - error::invalid_state(ESLASHED_INACTIVE_STAKE_ON_PAST_OLC)); + let (active, inactive, pending_active, pending_inactive) = + stake::get_stake(get_pool_address(pool)); + assert!( + inactive >= pool.total_coins_inactive, + error::invalid_state(ESLASHED_INACTIVE_STAKE_ON_PAST_OLC) + ); // determine whether a new lockup cycle has been ended on the stake pool and // inactivated SOME `pending_inactive` stake which should stop earning rewards now, // thus requiring separation of the `pending_inactive` stake on current observed lockup @@ -1797,32 +2198,52 @@ module supra_framework::pbo_delegation_pool { // operator `active` rewards not persisted yet to the active shares pool let pool_active = total_coins(&pool.active_shares); - let commission_active = if (active > pool_active) { - math64::mul_div(active - pool_active, pool.operator_commission_percentage, - MAX_FEE) - } else { - // handle any slashing applied to `active` stake - 0 }; + let commission_active = + if (active > pool_active) { + math64::mul_div( + active - pool_active, pool.operator_commission_percentage, MAX_FEE + ) + } else { + // handle any slashing applied to `active` stake + 0 + }; // operator `pending_inactive` rewards not persisted yet to the pending_inactive shares pool let pool_pending_inactive = total_coins(pending_inactive_shares_pool(pool)); - let commission_pending_inactive = if (pending_inactive > pool_pending_inactive) { - math64::mul_div(pending_inactive - pool_pending_inactive, pool.operator_commission_percentage, - MAX_FEE) - } else { - // handle any slashing applied to `pending_inactive` stake - 0 }; + let commission_pending_inactive = + if (pending_inactive > pool_pending_inactive) { + math64::mul_div( + pending_inactive - pool_pending_inactive, + pool.operator_commission_percentage, + MAX_FEE + ) + } else { + // handle any slashing applied to `pending_inactive` stake + 0 + }; - (lockup_cycle_ended, active, pending_inactive, commission_active, - commission_pending_inactive) + ( + lockup_cycle_ended, + active, + pending_inactive, + commission_active, + commission_pending_inactive + ) } /// Synchronize delegation and stake pools: distribute yet-undetected rewards to the corresponding internal /// shares pools, assign commission to operator and eventually prepare delegation pool for a new lockup cycle. - public entry fun synchronize_delegation_pool(pool_address: address) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun synchronize_delegation_pool( + pool_address: address + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { assert_delegation_pool_exists(pool_address); let pool = borrow_global_mut(pool_address); - let (lockup_cycle_ended, active, pending_inactive, commission_active, - commission_pending_inactive) = calculate_stake_pool_drift(pool); + let ( + lockup_cycle_ended, + active, + pending_inactive, + commission_active, + commission_pending_inactive + ) = calculate_stake_pool_drift(pool); // zero `pending_active` stake indicates that either there are no `add_stake` fees or // previous epoch has ended and should release the shares owning the existing fees @@ -1839,35 +2260,49 @@ module supra_framework::pbo_delegation_pool { // update total coins accumulated by `active` + `pending_active` shares // redeemed `add_stake` fees are restored and distributed to the rest of the pool as rewards - pool_u64::update_total_coins(&mut pool.active_shares, active - commission_active); + pool_u64::update_total_coins(&mut pool.active_shares, active + - commission_active); // update total coins accumulated by `pending_inactive` shares at current observed lockup cycle - pool_u64::update_total_coins(pending_inactive_shares_pool_mut(pool), - pending_inactive - commission_pending_inactive); + pool_u64::update_total_coins( + pending_inactive_shares_pool_mut(pool), + pending_inactive - commission_pending_inactive + ); // reward operator its commission out of uncommitted active rewards (`add_stake` fees already excluded) - buy_in_active_shares(pool, - beneficiary_for_operator(stake::get_operator(pool_address)), commission_active); + buy_in_active_shares( + pool, + beneficiary_for_operator(stake::get_operator(pool_address)), + commission_active + ); // reward operator its commission out of uncommitted pending_inactive rewards - buy_in_pending_inactive_shares(pool, + buy_in_pending_inactive_shares( + pool, beneficiary_for_operator(stake::get_operator(pool_address)), - commission_pending_inactive); + commission_pending_inactive + ); - event::emit_event(&mut pool.distribute_commission_events, + event::emit_event( + &mut pool.distribute_commission_events, DistributeCommissionEvent { pool_address, operator: stake::get_operator(pool_address), commission_active, - commission_pending_inactive, - },); + commission_pending_inactive + } + ); if (features::operator_beneficiary_change_enabled()) { - emit(DistributeCommission { + emit( + DistributeCommission { pool_address, operator: stake::get_operator(pool_address), - beneficiary: beneficiary_for_operator(stake::get_operator(pool_address)), + beneficiary: beneficiary_for_operator( + stake::get_operator(pool_address) + ), commission_active, - commission_pending_inactive, - }) + commission_pending_inactive + } + ) }; // advance lockup cycle on delegation pool if already ended on stake pool (AND stake explicitly inactivated) @@ -1879,9 +2314,11 @@ module supra_framework::pbo_delegation_pool { // advance lockup cycle on the delegation pool pool.observed_lockup_cycle.index = pool.observed_lockup_cycle.index + 1; // start new lockup cycle with a fresh shares pool for `pending_inactive` stake - table::add(&mut pool.inactive_shares, + table::add( + &mut pool.inactive_shares, pool.observed_lockup_cycle, - pool_u64::create_with_scaling_factor(SHARES_SCALING_FACTOR)); + pool_u64::create_with_scaling_factor(SHARES_SCALING_FACTOR) + ); }; if (is_next_commission_percentage_effective(pool_address)) { @@ -1892,81 +2329,115 @@ module supra_framework::pbo_delegation_pool { } fun update_governance_records_for_buy_in_active_shares( - pool: &DelegationPool, pool_address: address, new_shares: u128, shareholder: address + pool: &DelegationPool, + pool_address: address, + new_shares: u128, + shareholder: address ) acquires GovernanceRecords { // of += ----> // of += // of += let governance_records = borrow_global_mut(pool_address); - let vote_delegation = update_and_borrow_mut_delegator_vote_delegation(pool, - governance_records, shareholder); + let vote_delegation = + update_and_borrow_mut_delegator_vote_delegation( + pool, governance_records, shareholder + ); let current_voter = vote_delegation.voter; let pending_voter = vote_delegation.pending_voter; - let current_delegated_votes = update_and_borrow_mut_delegated_votes(pool, - governance_records, current_voter); - current_delegated_votes.active_shares = current_delegated_votes.active_shares + new_shares; + let current_delegated_votes = + update_and_borrow_mut_delegated_votes( + pool, governance_records, current_voter + ); + current_delegated_votes.active_shares = current_delegated_votes.active_shares + + new_shares; if (pending_voter == current_voter) { current_delegated_votes.active_shares_next_lockup = current_delegated_votes.active_shares_next_lockup + new_shares; } else { - let pending_delegated_votes = update_and_borrow_mut_delegated_votes(pool, - governance_records, pending_voter); + let pending_delegated_votes = + update_and_borrow_mut_delegated_votes( + pool, governance_records, pending_voter + ); pending_delegated_votes.active_shares_next_lockup = pending_delegated_votes.active_shares_next_lockup + new_shares; }; } fun update_governance_records_for_buy_in_pending_inactive_shares( - pool: &DelegationPool, pool_address: address, new_shares: u128, shareholder: address + pool: &DelegationPool, + pool_address: address, + new_shares: u128, + shareholder: address ) acquires GovernanceRecords { // of += ----> // of += // no impact on of let governance_records = borrow_global_mut(pool_address); - let current_voter = calculate_and_update_delegator_voter_internal(pool, - governance_records, shareholder); - let current_delegated_votes = update_and_borrow_mut_delegated_votes(pool, - governance_records, current_voter); + let current_voter = + calculate_and_update_delegator_voter_internal( + pool, governance_records, shareholder + ); + let current_delegated_votes = + update_and_borrow_mut_delegated_votes( + pool, governance_records, current_voter + ); current_delegated_votes.pending_inactive_shares = current_delegated_votes.pending_inactive_shares + new_shares; } fun update_governanace_records_for_redeem_active_shares( - pool: &DelegationPool, pool_address: address, shares_to_redeem: u128, shareholder: address + pool: &DelegationPool, + pool_address: address, + shares_to_redeem: u128, + shareholder: address ) acquires GovernanceRecords { // of -= ----> // of -= // of -= let governance_records = borrow_global_mut(pool_address); - let vote_delegation = update_and_borrow_mut_delegator_vote_delegation(pool, - governance_records, shareholder); + let vote_delegation = + update_and_borrow_mut_delegator_vote_delegation( + pool, governance_records, shareholder + ); let current_voter = vote_delegation.voter; let pending_voter = vote_delegation.pending_voter; - let current_delegated_votes = update_and_borrow_mut_delegated_votes(pool, - governance_records, current_voter); - current_delegated_votes.active_shares = current_delegated_votes.active_shares - shares_to_redeem; + let current_delegated_votes = + update_and_borrow_mut_delegated_votes( + pool, governance_records, current_voter + ); + current_delegated_votes.active_shares = current_delegated_votes.active_shares + - shares_to_redeem; if (current_voter == pending_voter) { current_delegated_votes.active_shares_next_lockup = current_delegated_votes.active_shares_next_lockup - shares_to_redeem; } else { - let pending_delegated_votes = update_and_borrow_mut_delegated_votes(pool, - governance_records, pending_voter); + let pending_delegated_votes = + update_and_borrow_mut_delegated_votes( + pool, governance_records, pending_voter + ); pending_delegated_votes.active_shares_next_lockup = pending_delegated_votes.active_shares_next_lockup - shares_to_redeem; }; } fun update_governanace_records_for_redeem_pending_inactive_shares( - pool: &DelegationPool, pool_address: address, shares_to_redeem: u128, shareholder: address + pool: &DelegationPool, + pool_address: address, + shares_to_redeem: u128, + shareholder: address ) acquires GovernanceRecords { // of -= ----> // of -= // no impact on of let governance_records = borrow_global_mut(pool_address); - let current_voter = calculate_and_update_delegator_voter_internal(pool, - governance_records, shareholder); - let current_delegated_votes = update_and_borrow_mut_delegated_votes(pool, - governance_records, current_voter); + let current_voter = + calculate_and_update_delegator_voter_internal( + pool, governance_records, shareholder + ); + let current_delegated_votes = + update_and_borrow_mut_delegated_votes( + pool, governance_records, current_voter + ); current_delegated_votes.pending_inactive_shares = current_delegated_votes.pending_inactive_shares - shares_to_redeem; } @@ -2025,14 +2496,30 @@ module supra_framework::pbo_delegation_pool { #[test_only] public fun initialize_for_test(supra_framework: &signer) { - initialize_for_test_custom(supra_framework, 100 * ONE_SUPRA, 100000000000 * ONE_SUPRA, - LOCKUP_CYCLE_SECONDS, true, 1, 100, 1000000); + initialize_for_test_custom( + supra_framework, + 100 * ONE_SUPRA, + 100000000000 * ONE_SUPRA, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 100, + 1000000 + ); } #[test_only] public fun initialize_for_test_no_reward(supra_framework: &signer) { - initialize_for_test_custom(supra_framework, 100 * ONE_SUPRA, 10000000 * ONE_SUPRA, - LOCKUP_CYCLE_SECONDS, true, 0, 100, 1000000); + initialize_for_test_custom( + supra_framework, + 100 * ONE_SUPRA, + 10000000 * ONE_SUPRA, + LOCKUP_CYCLE_SECONDS, + true, + 0, + 100, + 1000000 + ); } #[test_only] @@ -2044,26 +2531,30 @@ module supra_framework::pbo_delegation_pool { allow_validator_set_change: bool, rewards_rate_numerator: u64, rewards_rate_denominator: u64, - voting_power_increase_limit: u64, + voting_power_increase_limit: u64 ) { account::create_account_for_test(signer::address_of(supra_framework)); - stake::initialize_for_test_custom(supra_framework, + stake::initialize_for_test_custom( + supra_framework, minimum_stake, maximum_stake, recurring_lockup_secs, allow_validator_set_change, rewards_rate_numerator, rewards_rate_denominator, - voting_power_increase_limit, + voting_power_increase_limit ); reconfiguration::initialize_for_test(supra_framework); - features::change_feature_flags_for_testing(supra_framework, + features::change_feature_flags_for_testing( + supra_framework, vector[ DELEGATION_POOLS, MODULE_EVENT, OPERATOR_BENEFICIARY_CHANGE, - COMMISSION_CHANGE_DELEGATION_POOL], - vector[]); + COMMISSION_CHANGE_DELEGATION_POOL + ], + vector[] + ); } #[test_only] @@ -2087,7 +2578,8 @@ module supra_framework::pbo_delegation_pool { account::create_account_for_test(validator_address); }; - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, multisig_admin, commission_percentage, vector::empty(), @@ -2097,7 +2589,8 @@ module supra_framework::pbo_delegation_pool { unlock_numerators, unlock_denominator, principle_lockup_time, - unlock_duration); + unlock_duration + ); let pool_address = get_owned_pool_address(validator_address); stake::rotate_consensus_key(validator, pool_address, CONSENSUS_KEY_1); @@ -2117,7 +2610,9 @@ module supra_framework::pbo_delegation_pool { } #[test_only] - fun unlock_with_min_stake_disabled(delegator: &signer, pool_address: address, amount: u64) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + fun unlock_with_min_stake_disabled( + delegator: &signer, pool_address: address, amount: u64 + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { synchronize_delegation_pool(pool_address); let pool = borrow_global_mut(pool_address); @@ -2130,15 +2625,20 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x3000A, location = Self)] - public entry fun test_delegation_pools_disabled(supra_framework: &signer, validator: &signer,) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_delegation_pools_disabled( + supra_framework: &signer, validator: &signer + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x111]; let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 0; - features::change_feature_flags_for_testing(supra_framework, vector[], vector[DELEGATION_POOLS]); + features::change_feature_flags_for_testing( + supra_framework, vector[], vector[DELEGATION_POOLS] + ); - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, option::none(), 0, vector::empty(), @@ -2148,12 +2648,13 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12) + 12 + ) } #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_set_operator_and_delegated_voter( - supra_framework: &signer, validator: &signer, + supra_framework: &signer, validator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x111]; @@ -2161,7 +2662,8 @@ module supra_framework::pbo_delegation_pool { let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 0; let validator_address = signer::address_of(validator); - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, option::none(), 0, vector::empty(), @@ -2171,7 +2673,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let pool_address = get_owned_pool_address(validator_address); assert!(stake::get_operator(pool_address) == @0x123, 1); @@ -2186,7 +2689,9 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x60001, location = Self)] - public entry fun test_cannot_set_operator(supra_framework: &signer, validator: &signer,) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_cannot_set_operator( + supra_framework: &signer, validator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); // account does not own any delegation pool set_operator(validator, @0x111); @@ -2194,7 +2699,9 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x60001, location = Self)] - public entry fun test_cannot_set_delegated_voter(supra_framework: &signer, validator: &signer,) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_cannot_set_delegated_voter( + supra_framework: &signer, validator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); // account does not own any delegation pool set_delegated_voter(validator, @0x112); @@ -2202,13 +2709,16 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x80002, location = Self)] - public entry fun test_already_owns_delegation_pool(supra_framework: &signer, validator: &signer,) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_already_owns_delegation_pool( + supra_framework: &signer, validator: &signer + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x111]; let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 0; - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, option::none(), 0, x"00", @@ -2218,9 +2728,11 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let coin = stake::mint_coins(100 * ONE_SUPRA); - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, option::none(), 0, x"01", @@ -2230,18 +2742,22 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, 0, - 12); + 12 + ); } #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x1000B, location = Self)] - public entry fun test_cannot_withdraw_zero_stake(supra_framework: &signer, validator: &signer,) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_cannot_withdraw_zero_stake( + supra_framework: &signer, validator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x111]; let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 0; - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, option::none(), 0, x"00", @@ -2251,19 +2767,23 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); withdraw(validator, get_owned_pool_address(signer::address_of(validator)), 0); } #[test(supra_framework = @supra_framework, validator = @0x123)] - public entry fun test_initialize_delegation_pool(supra_framework: &signer, validator: &signer,) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_initialize_delegation_pool( + supra_framework: &signer, validator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[]; let principle_stake = vector[]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; let validator_address = signer::address_of(validator); - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, option::none(), 1234, vector::empty(), @@ -2273,7 +2793,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); assert_owner_cap_exists(validator_address); let pool_address = get_owned_pool_address(validator_address); @@ -2290,24 +2811,40 @@ module supra_framework::pbo_delegation_pool { stake::assert_stake_pool(pool_address, 0, 0, 0, 0); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator1 = @0x010, + delegator2 = @0x020 + ) + ] public entry fun test_add_stake_fee( supra_framework: &signer, validator: &signer, delegator1: &signer, - delegator2: &signer, + delegator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { - initialize_for_test_custom(supra_framework, 100 * ONE_SUPRA, 10000000 * ONE_SUPRA, - LOCKUP_CYCLE_SECONDS, true, 1, 100, 1000000); - let delegator_address = vector[@0x010, @0x020]; - let principle_stake = vector[0, 0]; - let coin = stake::mint_coins(0); + initialize_for_test_custom( + supra_framework, + 100 * ONE_SUPRA, + 10000000 * ONE_SUPRA, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 100, + 1000000 + ); + let delegator_address = vector[@0x010, @0x020]; + let principle_stake = vector[0, 0]; + let coin = stake::mint_coins(0); let principle_lockup_time = 0; let validator_address = signer::address_of(validator); account::create_account_for_test(validator_address); // create delegation pool with 37.35% operator commission - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, option::none(), 3735, vector::empty(), @@ -2317,13 +2854,17 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let pool_address = get_owned_pool_address(validator_address); stake::rotate_consensus_key(validator, pool_address, CONSENSUS_KEY_1); // zero `add_stake` fee as validator is not producing rewards this epoch - assert!(get_add_stake_fee(pool_address, 1000000 * ONE_SUPRA) == 0, 0); + assert!( + get_add_stake_fee(pool_address, 1000000 * ONE_SUPRA) == 0, + 0 + ); // add 1M SUPRA, join the validator set and activate this stake stake::mint(validator, 1000000 * ONE_SUPRA); @@ -2339,7 +2880,10 @@ module supra_framework::pbo_delegation_pool { account::create_account_for_test(delegator2_address); // `add_stake` fee for 100000 coins: 100000 * 0.006265 / (1 + 0.006265) - assert!(get_add_stake_fee(pool_address, 100000 * ONE_SUPRA) == 62259941466, 0); + assert!( + get_add_stake_fee(pool_address, 100000 * ONE_SUPRA) == 62259941466, + 0 + ); // add pending_active stake from multiple delegators stake::mint(delegator1, 100000 * ONE_SUPRA); @@ -2349,8 +2893,20 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // delegators should own the same amount as initially deposited - assert_delegation(delegator1_address, pool_address, 10000000000000, 0, 0); - assert_delegation(delegator2_address, pool_address, 1000000000000, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + 10000000000000, + 0, + 0 + ); + assert_delegation( + delegator2_address, + pool_address, + 1000000000000, + 0, + 0 + ); // add more stake from delegator 1 stake::mint(delegator1, 10000 * ONE_SUPRA); @@ -2358,11 +2914,22 @@ module supra_framework::pbo_delegation_pool { add_stake(delegator1, pool_address, 10000 * ONE_SUPRA); let fee = get_add_stake_fee(pool_address, 10000 * ONE_SUPRA); - assert_delegation(delegator1_address, pool_address, delegator1_active + 10000 * ONE_SUPRA - - fee, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + delegator1_active + 10000 * ONE_SUPRA - fee, + 0, + 0 + ); // delegator 2 should not benefit in any way from this new stake - assert_delegation(delegator2_address, pool_address, 1000000000000, 0, 0); + assert_delegation( + delegator2_address, + pool_address, + 1000000000000, + 0, + 0 + ); // add more stake from delegator 2 stake::mint(delegator2, 100000 * ONE_SUPRA); @@ -2371,21 +2938,57 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // delegators should own the same amount as initially deposited + any rewards produced // 10000000000000 * 1% * (100 - 37.35)% - assert_delegation(delegator1_address, pool_address, 11062650000001, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + 11062650000001, + 0, + 0 + ); // 1000000000000 * 1% * (100 - 37.35)% - assert_delegation(delegator2_address, pool_address, 11006265000001, 0, 0); + assert_delegation( + delegator2_address, + pool_address, + 11006265000001, + 0, + 0 + ); // in-flight operator commission rewards do not automatically restake/compound synchronize_delegation_pool(pool_address); // stakes should remain the same - `Self::get_stake` correctly calculates them - assert_delegation(delegator1_address, pool_address, 11062650000001, 0, 0); - assert_delegation(delegator2_address, pool_address, 11006265000001, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + 11062650000001, + 0, + 0 + ); + assert_delegation( + delegator2_address, + pool_address, + 11006265000001, + 0, + 0 + ); end_aptos_epoch(); // delegators should own previous stake * 1.006265 - assert_delegation(delegator1_address, pool_address, 11131957502251, 0, 0); - assert_delegation(delegator2_address, pool_address, 11075219250226, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + 11131957502251, + 0, + 0 + ); + assert_delegation( + delegator2_address, + pool_address, + 11075219250226, + 0, + 0 + ); // add more stake from delegator 1 stake::mint(delegator1, 20000 * ONE_SUPRA); @@ -2393,72 +2996,106 @@ module supra_framework::pbo_delegation_pool { add_stake(delegator1, pool_address, 20000 * ONE_SUPRA); fee = get_add_stake_fee(pool_address, 20000 * ONE_SUPRA); - assert_delegation(delegator1_address, pool_address, delegator1_active + 20000 * ONE_SUPRA - - fee, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + delegator1_active + 20000 * ONE_SUPRA - fee, + 0, + 0 + ); // delegator 1 unlocks his entire newly added stake unlock(delegator1, pool_address, 20000 * ONE_SUPRA - fee); end_aptos_epoch(); // delegator 1 should own previous 11131957502250 active * 1.006265 and 20000 coins pending_inactive - assert_delegation(delegator1_address, pool_address, 11201699216002, 0, - 2000000000000); + assert_delegation( + delegator1_address, + pool_address, + 11201699216002, + 0, + 2000000000000 + ); // stakes should remain the same - `Self::get_stake` correctly calculates them synchronize_delegation_pool(pool_address); - assert_delegation(delegator1_address, pool_address, 11201699216002, 0, - 2000000000000); + assert_delegation( + delegator1_address, + pool_address, + 11201699216002, + 0, + 2000000000000 + ); let reward_period_start_time_in_sec = timestamp::now_seconds(); // Enable rewards rate decrease. Initially rewards rate is still 1% every epoch. Rewards rate halves every year. let one_year_in_secs: u64 = 31536000; - staking_config::initialize_rewards(supra_framework, + staking_config::initialize_rewards( + supra_framework, fixed_point64::create_from_rational(2, 100), fixed_point64::create_from_rational(6, 1000), one_year_in_secs, reward_period_start_time_in_sec, - fixed_point64::create_from_rational(50, 100),); - features::change_feature_flags_for_testing(supra_framework, vector[features::get_periodical_reward_rate_decrease_feature()], - vector[]); + fixed_point64::create_from_rational(50, 100) + ); + features::change_feature_flags_for_testing( + supra_framework, + vector[features::get_periodical_reward_rate_decrease_feature()], + vector[] + ); // add more stake from delegator 1 stake::mint(delegator1, 20000 * ONE_SUPRA); let delegator1_pending_inactive: u64; - (delegator1_active, _, delegator1_pending_inactive) = get_stake(pool_address, - delegator1_address); + (delegator1_active, _, delegator1_pending_inactive) = get_stake( + pool_address, delegator1_address + ); fee = get_add_stake_fee(pool_address, 20000 * ONE_SUPRA); add_stake(delegator1, pool_address, 20000 * ONE_SUPRA); - assert_delegation(delegator1_address, + assert_delegation( + delegator1_address, pool_address, delegator1_active + 20000 * ONE_SUPRA - fee, 0, - delegator1_pending_inactive); + delegator1_pending_inactive + ); // delegator 1 unlocks his entire newly added stake unlock(delegator1, pool_address, 20000 * ONE_SUPRA - fee); end_aptos_epoch(); // delegator 1 should own previous 11201699216002 active * ~1.01253 and 20000 * ~1.01253 + 20000 coins pending_inactive - assert_delegation(delegator1_address, pool_address, 11342056366822, 0, - 4025059974939); + assert_delegation( + delegator1_address, + pool_address, + 11342056366822, + 0, + 4025059974939 + ); // stakes should remain the same - `Self::get_stake` correctly calculates them synchronize_delegation_pool(pool_address); - assert_delegation(delegator1_address, pool_address, 11342056366822, 0, - 4025059974939); + assert_delegation( + delegator1_address, + pool_address, + 11342056366822, + 0, + 4025059974939 + ); fast_forward_seconds(one_year_in_secs); } #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] public entry fun test_never_create_pending_withdrawal_if_no_shares_bought( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, validator: &signer, delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010]; let principle_stake = vector[0 * ONE_SUPRA]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1000 * ONE_SUPRA, true, false, @@ -2470,7 +3107,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -2491,22 +3129,61 @@ module supra_framework::pbo_delegation_pool { unlock_with_min_stake_disabled(delegator, pool_address, 1); // request 1 coins * 910 / 919.1 = 0.99 shares to redeem * 1.01 price -> 0 coins out // 1 coins lost at redeem due to 0.99 shares being burned - assert_delegation(delegator_address, pool_address, 1009999999, 0, 0); - assert_pending_withdrawal(delegator_address, pool_address, false, 0, false, 0); + assert_delegation( + delegator_address, + pool_address, + 1009999999, + 0, + 0 + ); + assert_pending_withdrawal( + delegator_address, + pool_address, + false, + 0, + false, + 0 + ); unlock_with_min_stake_disabled(delegator, pool_address, 2); // request 2 coins * 909.99 / 919.1 = 1.98 shares to redeem * 1.01 price -> 1 coins out // with 1 coins buy 1 * 100 / 101 = 0.99 shares in pending_inactive pool * 1.01 -> 0 coins in // 1 coins lost at redeem due to 1.98 - 1.01 shares being burned + 1 coins extracted synchronize_delegation_pool(pool_address); - assert_delegation(delegator_address, pool_address, 1009999997, 0, 0); + assert_delegation( + delegator_address, + pool_address, + 1009999997, + 0, + 0 + ); // the pending withdrawal has been created as > 0 pending_inactive shares have been bought - assert_pending_withdrawal(delegator_address, pool_address, true, 0, false, 0); + assert_pending_withdrawal( + delegator_address, + pool_address, + true, + 0, + false, + 0 + ); // successfully delete the pending withdrawal (redeem all owned shares even worth 0 coins) reactivate_stake(delegator, pool_address, 1); - assert_delegation(delegator_address, pool_address, 1009999997, 0, 0); - assert_pending_withdrawal(delegator_address, pool_address, false, 0, false, 0); + assert_delegation( + delegator_address, + pool_address, + 1009999997, + 0, + 0 + ); + assert_pending_withdrawal( + delegator_address, + pool_address, + false, + 0, + false, + 0 + ); // unlock min coins to own some pending_inactive balance (have to disable min-balance checks) unlock_with_min_stake_disabled(delegator, pool_address, 3); @@ -2514,26 +3191,55 @@ module supra_framework::pbo_delegation_pool { // with 2 coins buy 2 * 100 / 101 = 1.98 shares in pending_inactive pool * 1.01 -> 1 coins in // 1 coins lost at redeem due to 2.97 - 2 * 1.01 shares being burned + 2 coins extracted synchronize_delegation_pool(pool_address); - assert_delegation(delegator_address, pool_address, 1009999994, 0, 1); + assert_delegation( + delegator_address, + pool_address, + 1009999994, + 0, + 1 + ); // the pending withdrawal has been created as > 0 pending_inactive shares have been bought - assert_pending_withdrawal(delegator_address, pool_address, true, 0, false, 1); + assert_pending_withdrawal( + delegator_address, + pool_address, + true, + 0, + false, + 1 + ); reactivate_stake(delegator, pool_address, 1); // redeem 1 coins >= delegator balance -> all shares are redeemed and pending withdrawal is deleted - assert_delegation(delegator_address, pool_address, 1009999995, 0, 0); + assert_delegation( + delegator_address, + pool_address, + 1009999995, + 0, + 0 + ); // the pending withdrawal has been deleted as delegator has 0 pending_inactive shares now - assert_pending_withdrawal(delegator_address, pool_address, false, 0, false, 0); + assert_pending_withdrawal( + delegator_address, + pool_address, + false, + 0, + false, + 0 + ); } #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x10008, location = Self)] - public entry fun test_add_stake_min_amount(supra_framework: &signer, validator: &signer,) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_add_stake_min_amount( + supra_framework: &signer, validator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x111]; let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, MIN_COINS_ON_SHARES_POOL - 1, false, false, @@ -2545,17 +3251,21 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); } #[test(supra_framework = @supra_framework, validator = @0x123)] - public entry fun test_add_stake_single(supra_framework: &signer, validator: &signer,) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_add_stake_single( + supra_framework: &signer, validator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[]; let principle_stake = vector[]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1000 * ONE_SUPRA, false, false, @@ -2567,17 +3277,27 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); // validator is inactive => added stake is `active` by default stake::assert_stake_pool(pool_address, 1000 * ONE_SUPRA, 0, 0, 0); - assert_delegation(validator_address, pool_address, 1000 * ONE_SUPRA, 0, 0); + assert_delegation( + validator_address, + pool_address, + 1000 * ONE_SUPRA, + 0, + 0 + ); // zero `add_stake` fee as validator is not producing rewards this epoch - assert!(get_add_stake_fee(pool_address, 250 * ONE_SUPRA) == 0, 0); + assert!( + get_add_stake_fee(pool_address, 250 * ONE_SUPRA) == 0, + 0 + ); // check `add_stake` increases `active` stakes of delegator and stake pool stake::mint(validator, 300 * ONE_SUPRA); @@ -2585,9 +3305,18 @@ module supra_framework::pbo_delegation_pool { add_stake(validator, pool_address, 250 * ONE_SUPRA); // check added stake have been transferred out of delegator account - assert!(coin::balance(validator_address) == balance - 250 * ONE_SUPRA, 0); + assert!( + coin::balance(validator_address) == balance - 250 * ONE_SUPRA, + 0 + ); // zero `add_stake` fee charged from added stake - assert_delegation(validator_address, pool_address, 1250 * ONE_SUPRA, 0, 0); + assert_delegation( + validator_address, + pool_address, + 1250 * ONE_SUPRA, + 0, + 0 + ); // zero `add_stake` fee transferred to null shareholder assert_delegation(NULL_SHAREHOLDER, pool_address, 0, 0, 0); // added stake is automatically `active` on inactive validator @@ -2602,33 +3331,66 @@ module supra_framework::pbo_delegation_pool { add_stake(validator, pool_address, 250 * ONE_SUPRA); let fee1 = get_add_stake_fee(pool_address, 250 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 1500 * ONE_SUPRA - fee1, 0, 0); + assert_delegation( + validator_address, + pool_address, + 1500 * ONE_SUPRA - fee1, + 0, + 0 + ); // check `add_stake` fee has been transferred to the null shareholder assert_delegation(NULL_SHAREHOLDER, pool_address, fee1, 0, 0); - stake::assert_stake_pool(pool_address, 1250 * ONE_SUPRA, 0, 250 * ONE_SUPRA, 0); + stake::assert_stake_pool( + pool_address, + 1250 * ONE_SUPRA, + 0, + 250 * ONE_SUPRA, + 0 + ); // add 100 additional coins being pending_active until next epoch stake::mint(validator, 100 * ONE_SUPRA); add_stake(validator, pool_address, 100 * ONE_SUPRA); let fee2 = get_add_stake_fee(pool_address, 100 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 1600 * ONE_SUPRA - fee1 - fee2, 0, - 0); + assert_delegation( + validator_address, + pool_address, + 1600 * ONE_SUPRA - fee1 - fee2, + 0, + 0 + ); // check `add_stake` fee has been transferred to the null shareholder assert_delegation(NULL_SHAREHOLDER, pool_address, fee1 + fee2, 0, 0); - stake::assert_stake_pool(pool_address, 1250 * ONE_SUPRA, 0, 350 * ONE_SUPRA, 0); + stake::assert_stake_pool( + pool_address, + 1250 * ONE_SUPRA, + 0, + 350 * ONE_SUPRA, + 0 + ); end_aptos_epoch(); // delegator got its `add_stake` fees back + 1250 * 1% * (100% - 0%) active rewards - assert_delegation(validator_address, pool_address, 161250000000, 0, 0); + assert_delegation( + validator_address, + pool_address, + 161250000000, + 0, + 0 + ); stake::assert_stake_pool(pool_address, 161250000000, 0, 0, 0); // check that shares of null shareholder have been released assert_delegation(NULL_SHAREHOLDER, pool_address, 0, 0, 0); synchronize_delegation_pool(pool_address); - assert!(pool_u64::shares(&borrow_global(pool_address).active_shares, - NULL_SHAREHOLDER) == 0, - 0); + assert!( + pool_u64::shares( + &borrow_global(pool_address).active_shares, + NULL_SHAREHOLDER + ) == 0, + 0 + ); assert_delegation(NULL_SHAREHOLDER, pool_address, 0, 0, 0); // add 200 coins being pending_active until next epoch @@ -2636,35 +3398,52 @@ module supra_framework::pbo_delegation_pool { add_stake(validator, pool_address, 200 * ONE_SUPRA); fee1 = get_add_stake_fee(pool_address, 200 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 181250000000 - fee1, 0, 0); + assert_delegation( + validator_address, + pool_address, + 181250000000 - fee1, + 0, + 0 + ); // check `add_stake` fee has been transferred to the null shareholder assert_delegation(NULL_SHAREHOLDER, pool_address, fee1 - 1, 0, 0); stake::assert_stake_pool(pool_address, 161250000000, 0, 20000000000, 0); end_aptos_epoch(); // delegator got its `add_stake` fee back + 161250000000 * 1% active rewards - assert_delegation(validator_address, pool_address, 182862500000, 0, 0); + assert_delegation( + validator_address, + pool_address, + 182862500000, + 0, + 0 + ); stake::assert_stake_pool(pool_address, 182862500000, 0, 0, 0); // check that shares of null shareholder have been released assert_delegation(NULL_SHAREHOLDER, pool_address, 0, 0, 0); synchronize_delegation_pool(pool_address); - assert!(pool_u64::shares(&borrow_global(pool_address).active_shares, - NULL_SHAREHOLDER) == 0, - 0); + assert!( + pool_u64::shares( + &borrow_global(pool_address).active_shares, + NULL_SHAREHOLDER + ) == 0, + 0 + ); assert_delegation(NULL_SHAREHOLDER, pool_address, 0, 0, 0); } #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] public entry fun test_add_stake_many( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, validator: &signer, delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010]; let principle_stake = vector[0]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1000 * ONE_SUPRA, true, true, @@ -2676,7 +3455,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -2685,62 +3465,147 @@ module supra_framework::pbo_delegation_pool { account::create_account_for_test(delegator_address); stake::assert_stake_pool(pool_address, 1000 * ONE_SUPRA, 0, 0, 0); - assert_delegation(validator_address, pool_address, 1000 * ONE_SUPRA, 0, 0); + assert_delegation( + validator_address, + pool_address, + 1000 * ONE_SUPRA, + 0, + 0 + ); // add 250 coins from second account stake::mint(delegator, 250 * ONE_SUPRA); add_stake(delegator, pool_address, 250 * ONE_SUPRA); let fee1 = get_add_stake_fee(pool_address, 250 * ONE_SUPRA); - assert_delegation(delegator_address, pool_address, 250 * ONE_SUPRA - fee1, 0, 0); - assert_delegation(validator_address, pool_address, 1000 * ONE_SUPRA, 0, 0); - stake::assert_stake_pool(pool_address, 1000 * ONE_SUPRA, 0, 250 * ONE_SUPRA, 0); + assert_delegation( + delegator_address, + pool_address, + 250 * ONE_SUPRA - fee1, + 0, + 0 + ); + assert_delegation( + validator_address, + pool_address, + 1000 * ONE_SUPRA, + 0, + 0 + ); + stake::assert_stake_pool( + pool_address, + 1000 * ONE_SUPRA, + 0, + 250 * ONE_SUPRA, + 0 + ); end_aptos_epoch(); // 1000 * 1.01 active stake + 250 pending_active stake stake::assert_stake_pool(pool_address, 1260 * ONE_SUPRA, 0, 0, 0); // delegator got its `add_stake` fee back - assert_delegation(delegator_address, pool_address, 250 * ONE_SUPRA, 0, 0); + assert_delegation( + delegator_address, + pool_address, + 250 * ONE_SUPRA, + 0, + 0 + ); // actual active rewards have been distributed to their earner(s) - assert_delegation(validator_address, pool_address, 100999999999, 0, 0); + assert_delegation( + validator_address, + pool_address, + 100999999999, + 0, + 0 + ); // add another 250 coins from first account stake::mint(validator, 250 * ONE_SUPRA); add_stake(validator, pool_address, 250 * ONE_SUPRA); fee1 = get_add_stake_fee(pool_address, 250 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 125999999999 - fee1, 0, 0); - assert_delegation(delegator_address, pool_address, 250 * ONE_SUPRA, 0, 0); - stake::assert_stake_pool(pool_address, 1260 * ONE_SUPRA, 0, 250 * ONE_SUPRA, 0); + assert_delegation( + validator_address, + pool_address, + 125999999999 - fee1, + 0, + 0 + ); + assert_delegation( + delegator_address, + pool_address, + 250 * ONE_SUPRA, + 0, + 0 + ); + stake::assert_stake_pool( + pool_address, + 1260 * ONE_SUPRA, + 0, + 250 * ONE_SUPRA, + 0 + ); // add another 100 coins from second account stake::mint(delegator, 100 * ONE_SUPRA); add_stake(delegator, pool_address, 100 * ONE_SUPRA); let fee2 = get_add_stake_fee(pool_address, 100 * ONE_SUPRA); - assert_delegation(delegator_address, pool_address, 350 * ONE_SUPRA - fee2, 0, 0); - assert_delegation(validator_address, pool_address, 125999999999 - fee1, 0, 0); - stake::assert_stake_pool(pool_address, 1260 * ONE_SUPRA, 0, 350 * ONE_SUPRA, 0); + assert_delegation( + delegator_address, + pool_address, + 350 * ONE_SUPRA - fee2, + 0, + 0 + ); + assert_delegation( + validator_address, + pool_address, + 125999999999 - fee1, + 0, + 0 + ); + stake::assert_stake_pool( + pool_address, + 1260 * ONE_SUPRA, + 0, + 350 * ONE_SUPRA, + 0 + ); end_aptos_epoch(); // both delegators got their `add_stake` fees back // 250 * 1.01 active stake + 100 pending_active stake - assert_delegation(delegator_address, pool_address, 35250000001, 0, 0); + assert_delegation( + delegator_address, + pool_address, + 35250000001, + 0, + 0 + ); // 1010 * 1.01 active stake + 250 pending_active stake - assert_delegation(validator_address, pool_address, 127009999998, 0, 0); + assert_delegation( + validator_address, + pool_address, + 127009999998, + 0, + 0 + ); stake::assert_stake_pool(pool_address, 162260000000, 0, 0, 0); } #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] public entry fun test_unlock_single( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, validator: &signer, delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address_vec = vector[@0x010]; let principle_stake = vector[0]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 100 * ONE_SUPRA, true, true, @@ -2752,7 +3617,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -2765,61 +3631,175 @@ module supra_framework::pbo_delegation_pool { add_stake(validator, pool_address, 200 * ONE_SUPRA); let fee = get_add_stake_fee(pool_address, 200 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 300 * ONE_SUPRA - fee, 0, 0); - stake::assert_stake_pool(pool_address, 100 * ONE_SUPRA, 0, 200 * ONE_SUPRA, 0); + assert_delegation( + validator_address, + pool_address, + 300 * ONE_SUPRA - fee, + 0, + 0 + ); + stake::assert_stake_pool( + pool_address, + 100 * ONE_SUPRA, + 0, + 200 * ONE_SUPRA, + 0 + ); // cannot unlock pending_active stake (only 100/300 stake can be displaced) unlock(validator, pool_address, 100 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 200 * ONE_SUPRA - fee, 0, 100 * ONE_SUPRA); - assert_pending_withdrawal(validator_address, pool_address, true, 0, false, 100 * ONE_SUPRA); - stake::assert_stake_pool(pool_address, 0, 0, 200 * ONE_SUPRA, 100 * ONE_SUPRA); + assert_delegation( + validator_address, + pool_address, + 200 * ONE_SUPRA - fee, + 0, + 100 * ONE_SUPRA + ); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 0, + false, + 100 * ONE_SUPRA + ); + stake::assert_stake_pool( + pool_address, + 0, + 0, + 200 * ONE_SUPRA, + 100 * ONE_SUPRA + ); assert_inactive_shares_pool(pool_address, 0, true, 100 * ONE_SUPRA); // reactivate entire pending_inactive stake progressively reactivate_stake(validator, pool_address, 50 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 250 * ONE_SUPRA - fee, 0, 50 * ONE_SUPRA); - assert_pending_withdrawal(validator_address, pool_address, true, 0, false, 50 * ONE_SUPRA); - stake::assert_stake_pool(pool_address, 50 * ONE_SUPRA, 0, 200 * ONE_SUPRA, 50 * ONE_SUPRA); + assert_delegation( + validator_address, + pool_address, + 250 * ONE_SUPRA - fee, + 0, + 50 * ONE_SUPRA + ); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 0, + false, + 50 * ONE_SUPRA + ); + stake::assert_stake_pool( + pool_address, + 50 * ONE_SUPRA, + 0, + 200 * ONE_SUPRA, + 50 * ONE_SUPRA + ); reactivate_stake(validator, pool_address, 50 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 300 * ONE_SUPRA - fee, 0, 0); - assert_pending_withdrawal(validator_address, pool_address, false, 0, false, 0); - stake::assert_stake_pool(pool_address, 100 * ONE_SUPRA, 0, 200 * ONE_SUPRA, 0); + assert_delegation( + validator_address, + pool_address, + 300 * ONE_SUPRA - fee, + 0, + 0 + ); + assert_pending_withdrawal( + validator_address, + pool_address, + false, + 0, + false, + 0 + ); + stake::assert_stake_pool( + pool_address, + 100 * ONE_SUPRA, + 0, + 200 * ONE_SUPRA, + 0 + ); // pending_inactive shares pool has not been deleted (as can still `unlock` this OLC) assert_inactive_shares_pool(pool_address, 0, true, 0); end_aptos_epoch(); // 10000000000 * 1.01 active stake + 20000000000 pending_active stake - assert_delegation(validator_address, pool_address, 301 * ONE_SUPRA, 0, 0); + assert_delegation( + validator_address, + pool_address, + 301 * ONE_SUPRA, + 0, + 0 + ); stake::assert_stake_pool(pool_address, 301 * ONE_SUPRA, 0, 0, 0); // can unlock more than at previous epoch as the pending_active stake became active unlock(validator, pool_address, 150 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 15100000001, 0, 14999999999); + assert_delegation( + validator_address, + pool_address, + 15100000001, + 0, + 14999999999 + ); stake::assert_stake_pool(pool_address, 15100000001, 0, 0, 14999999999); - assert_pending_withdrawal(validator_address, pool_address, true, 0, false, - 14999999999); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 0, + false, + 14999999999 + ); - assert!(stake::get_remaining_lockup_secs(pool_address) == LOCKUP_CYCLE_SECONDS - EPOCH_DURATION, - 0); + assert!( + stake::get_remaining_lockup_secs(pool_address) + == LOCKUP_CYCLE_SECONDS - EPOCH_DURATION, + 0 + ); end_aptos_epoch(); // additionally forwards EPOCH_DURATION seconds // pending_inactive stake should have not been inactivated // 15100000001 * 1.01 active stake + 14999999999 pending_inactive * 1.01 stake - assert_delegation(validator_address, pool_address, 15251000001, 0, 15149999998); - assert_pending_withdrawal(validator_address, pool_address, true, 0, false, - 15149999998); + assert_delegation( + validator_address, + pool_address, + 15251000001, + 0, + 15149999998 + ); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 0, + false, + 15149999998 + ); stake::assert_stake_pool(pool_address, 15251000001, 0, 0, 15149999998); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS - 3 * EPOCH_DURATION); end_aptos_epoch(); // additionally forwards EPOCH_DURATION seconds and expires lockup cycle // 15251000001 * 1.01 active stake + 15149999998 * 1.01 pending_inactive(now inactive) stake - assert_delegation(validator_address, pool_address, 15403510001, 15301499997, 0); - assert_pending_withdrawal(validator_address, pool_address, true, 0, true, - 15301499997); + assert_delegation( + validator_address, + pool_address, + 15403510001, + 15301499997, + 0 + ); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 0, + true, + 15301499997 + ); stake::assert_stake_pool(pool_address, 15403510001, 15301499997, 0, 0); // add 50 coins from another account @@ -2830,9 +3810,27 @@ module supra_framework::pbo_delegation_pool { assert!(observed_lockup_cycle(pool_address) == 1, 0); fee = get_add_stake_fee(pool_address, 50 * ONE_SUPRA); - assert_delegation(delegator_address, pool_address, 4999999999 - fee, 0, 0); - assert_delegation(validator_address, pool_address, 15403510001, 15301499997, 0); - stake::assert_stake_pool(pool_address, 15403510001, 15301499997, 50 * ONE_SUPRA, 0); + assert_delegation( + delegator_address, + pool_address, + 4999999999 - fee, + 0, + 0 + ); + assert_delegation( + validator_address, + pool_address, + 15403510001, + 15301499997, + 0 + ); + stake::assert_stake_pool( + pool_address, + 15403510001, + 15301499997, + 50 * ONE_SUPRA, + 0 + ); // cannot withdraw stake unlocked by others withdraw(delegator, pool_address, 50 * ONE_SUPRA); @@ -2841,35 +3839,87 @@ module supra_framework::pbo_delegation_pool { // withdraw own unlocked stake withdraw(validator, pool_address, 15301499997); assert!(coin::balance(validator_address) == 15301499997, 0); - assert_delegation(validator_address, pool_address, 15403510001, 0, 0); + assert_delegation( + validator_address, + pool_address, + 15403510001, + 0, + 0 + ); // pending withdrawal has been executed and deleted - assert_pending_withdrawal(validator_address, pool_address, false, 0, false, 0); + assert_pending_withdrawal( + validator_address, + pool_address, + false, + 0, + false, + 0 + ); // inactive shares pool on OLC 0 has been deleted because its stake has been withdrawn assert_inactive_shares_pool(pool_address, 0, false, 0); // new pending withdrawal can be created on lockup cycle 1 unlock(validator, pool_address, 5403510001); - assert_delegation(validator_address, pool_address, 10000000000, 0, 5403510000); - assert_pending_withdrawal(validator_address, pool_address, true, 1, false, - 5403510000); + assert_delegation( + validator_address, + pool_address, + 10000000000, + 0, + 5403510000 + ); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 1, + false, + 5403510000 + ); // end lockup cycle 1 timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); // 10000000000 * 1.01 active stake + 5403510000 * 1.01 pending_inactive(now inactive) stake - assert_delegation(validator_address, pool_address, 10100000000, 5457545100, 0); - assert_pending_withdrawal(validator_address, pool_address, true, 1, true, - 5457545100); + assert_delegation( + validator_address, + pool_address, + 10100000000, + 5457545100, + 0 + ); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 1, + true, + 5457545100 + ); // unlock when the pending withdrawal exists and gets automatically executed let balance = coin::balance(validator_address); unlock(validator, pool_address, 10100000000); - assert!(coin::balance(validator_address) == balance + 5457545100, 0); - assert_delegation(validator_address, pool_address, 0, 0, 10100000000); + assert!( + coin::balance(validator_address) == balance + 5457545100, + 0 + ); + assert_delegation( + validator_address, + pool_address, + 0, + 0, + 10100000000 + ); // this is the new pending withdrawal replacing the executed one - assert_pending_withdrawal(validator_address, pool_address, true, 2, false, - 10100000000); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 2, + false, + 10100000000 + ); // create dummy validator to ensure the existing validator can leave the set let delegator_address_vec = vector[@0x010]; @@ -2877,9 +3927,10 @@ module supra_framework::pbo_delegation_pool { let coin = stake::mint_coins(100 * ONE_SUPRA); // lockup time updated as you see above we `fast_forward_seconds` alog with `end_aptos_epoch` - principle_lockup_time = LOCKUP_CYCLE_SECONDS + (LOCKUP_CYCLE_SECONDS - (3 * EPOCH_DURATION)) - + (5 * EPOCH_DURATION); - initialize_test_validator(delegator, + principle_lockup_time = LOCKUP_CYCLE_SECONDS + + (LOCKUP_CYCLE_SECONDS - (3 * EPOCH_DURATION)) + (5 * EPOCH_DURATION); + initialize_test_validator( + delegator, 100 * ONE_SUPRA, true, true, @@ -2891,7 +3942,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); // inactivate validator stake::leave_validator_set(validator, pool_address); end_aptos_epoch(); @@ -2908,55 +3960,116 @@ module supra_framework::pbo_delegation_pool { // stake is pending_inactive as it has not been inactivated stake::assert_stake_pool(pool_address, 5100500001, 0, 0, 10303010000); // 10100000000 * 1.01 * 1.01 pending_inactive stake - assert_delegation(validator_address, pool_address, 0, 0, 10303010000); + assert_delegation( + validator_address, + pool_address, + 0, + 0, + 10303010000 + ); // the pending withdrawal should be reported as still pending - assert_pending_withdrawal(validator_address, pool_address, true, 2, false, - 10303010000); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 2, + false, + 10303010000 + ); // validator is inactive and lockup expired => pending_inactive stake is withdrawable balance = coin::balance(validator_address); withdraw(validator, pool_address, 10303010000); - assert!(coin::balance(validator_address) == balance + 10303010000, 0); + assert!( + coin::balance(validator_address) == balance + 10303010000, + 0 + ); assert_delegation(validator_address, pool_address, 0, 0, 0); - assert_pending_withdrawal(validator_address, pool_address, false, 0, false, 0); + assert_pending_withdrawal( + validator_address, + pool_address, + false, + 0, + false, + 0 + ); stake::assert_stake_pool(pool_address, 5100500001, 0, 0, 0); // pending_inactive shares pool has not been deleted (as can still `unlock` this OLC) - assert_inactive_shares_pool(pool_address, observed_lockup_cycle(pool_address), true, - 0); + assert_inactive_shares_pool( + pool_address, + observed_lockup_cycle(pool_address), + true, + 0 + ); stake::mint(validator, 30 * ONE_SUPRA); add_stake(validator, pool_address, 30 * ONE_SUPRA); unlock(validator, pool_address, 10 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 2000000000, 0, 999999999); + assert_delegation( + validator_address, + pool_address, + 2000000000, + 0, + 999999999 + ); // the pending withdrawal should be reported as still pending - assert_pending_withdrawal(validator_address, pool_address, true, 2, false, - 999999999); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 2, + false, + 999999999 + ); balance = coin::balance(validator_address); // pending_inactive balance would be under threshold => redeem entire balance withdraw(validator, pool_address, 1); // pending_inactive balance has been withdrawn and the pending withdrawal executed - assert_delegation(validator_address, pool_address, 2000000000, 0, 999999998); - assert_pending_withdrawal(validator_address, pool_address, true, 2, false, - 999999998); - assert!(coin::balance(validator_address) == balance + 1, 0); + assert_delegation( + validator_address, + pool_address, + 2000000000, + 0, + 999999998 + ); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 2, + false, + 999999998 + ); + assert!( + coin::balance(validator_address) == balance + 1, + 0 + ); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator1 = @0x010, + delegator2 = @0x020 + ) + ] public entry fun test_total_coins_inactive( supra_framework: &signer, validator: &signer, delegator1: &signer, - delegator2: &signer, + delegator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010, @0x020]; let principle_stake = vector[0, 0]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 200 * ONE_SUPRA, true, true, @@ -2968,7 +4081,8 @@ module supra_framework::pbo_delegation_pool { vector[1], 1, principle_lockup_time, - 60); + 60 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -2985,31 +4099,73 @@ module supra_framework::pbo_delegation_pool { add_stake(delegator2, pool_address, 200 * ONE_SUPRA); end_aptos_epoch(); - assert_delegation(delegator1_address, pool_address, 100 * ONE_SUPRA, 0, 0); - assert_delegation(delegator2_address, pool_address, 200 * ONE_SUPRA, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + 100 * ONE_SUPRA, + 0, + 0 + ); + assert_delegation( + delegator2_address, + pool_address, + 200 * ONE_SUPRA, + 0, + 0 + ); // unlock some stake from delegator 1 unlock(delegator1, pool_address, 50 * ONE_SUPRA); - assert_delegation(delegator1_address, pool_address, 5000000000, 0, 4999999999); + assert_delegation( + delegator1_address, + pool_address, + 5000000000, + 0, + 4999999999 + ); // move to lockup cycle 1 timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); // delegator 1 pending_inactive stake has been inactivated - assert_delegation(delegator1_address, pool_address, 5050000000, 5049999998, 0); - assert_delegation(delegator2_address, pool_address, 202 * ONE_SUPRA, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + 5050000000, + 5049999998, + 0 + ); + assert_delegation( + delegator2_address, + pool_address, + 202 * ONE_SUPRA, + 0, + 0 + ); synchronize_delegation_pool(pool_address); assert!(total_coins_inactive(pool_address) == 5049999998, 0); // unlock some stake from delegator 2 unlock(delegator2, pool_address, 50 * ONE_SUPRA); - assert_delegation(delegator2_address, pool_address, 15200000001, 0, 4999999999); + assert_delegation( + delegator2_address, + pool_address, + 15200000001, + 0, + 4999999999 + ); // withdraw some of inactive stake of delegator 1 withdraw(delegator1, pool_address, 2049999998); - assert_delegation(delegator1_address, pool_address, 5050000000, 3000000001, 0); + assert_delegation( + delegator1_address, + pool_address, + 5050000000, + 3000000001, + 0 + ); assert!(total_coins_inactive(pool_address) == 3000000001, 0); // move to lockup cycle 2 @@ -3018,20 +4174,38 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // delegator 2 pending_inactive stake has been inactivated - assert_delegation(delegator1_address, pool_address, 5100500000, 3000000001, 0); - assert_delegation(delegator2_address, pool_address, 15352000001, 5049999998, 0); + assert_delegation( + delegator1_address, + pool_address, + 5100500000, + 3000000001, + 0 + ); + assert_delegation( + delegator2_address, + pool_address, + 15352000001, + 5049999998, + 0 + ); // total_coins_inactive remains unchanged in the absence of user operations assert!(total_coins_inactive(pool_address) == inactive, 0); synchronize_delegation_pool(pool_address); // total_coins_inactive == previous inactive stake + previous pending_inactive stake and its rewards - assert!(total_coins_inactive(pool_address) == inactive + pending_inactive + pending_inactive - / 100, 0); + assert!( + total_coins_inactive(pool_address) + == inactive + pending_inactive + pending_inactive / 100, + 0 + ); // withdraw some of inactive stake of delegator 2 let total_coins_inactive = total_coins_inactive(pool_address); withdraw(delegator2, pool_address, 3049999998); - assert!(total_coins_inactive(pool_address) == total_coins_inactive - 3049999997, 0); + assert!( + total_coins_inactive(pool_address) == total_coins_inactive - 3049999997, + 0 + ); // unlock some stake from delegator `validator` unlock(validator, pool_address, 50 * ONE_SUPRA); @@ -3041,7 +4215,8 @@ module supra_framework::pbo_delegation_pool { let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); principle_lockup_time = (2 * LOCKUP_CYCLE_SECONDS) + (4 * EPOCH_DURATION); - initialize_test_validator(delegator1, + initialize_test_validator( + delegator1, 100 * ONE_SUPRA, true, true, @@ -3053,7 +4228,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); // inactivate validator stake::leave_validator_set(validator, pool_address); end_aptos_epoch(); @@ -3087,13 +4263,16 @@ module supra_framework::pbo_delegation_pool { } #[test(supra_framework = @supra_framework, validator = @0x123)] - public entry fun test_reactivate_stake_single(supra_framework: &signer, validator: &signer,) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_reactivate_stake_single( + supra_framework: &signer, validator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[]; let principle_stake = vector[]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 200 * ONE_SUPRA, true, true, @@ -3105,39 +4284,102 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); // unlock some stake from the active one unlock(validator, pool_address, 100 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 100 * ONE_SUPRA, 0, 100 * ONE_SUPRA); - stake::assert_stake_pool(pool_address, 100 * ONE_SUPRA, 0, 0, 100 * ONE_SUPRA); - assert_pending_withdrawal(validator_address, pool_address, true, 0, false, 100 * ONE_SUPRA); + assert_delegation( + validator_address, + pool_address, + 100 * ONE_SUPRA, + 0, + 100 * ONE_SUPRA + ); + stake::assert_stake_pool( + pool_address, + 100 * ONE_SUPRA, + 0, + 0, + 100 * ONE_SUPRA + ); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 0, + false, + 100 * ONE_SUPRA + ); // add some stake to pending_active state stake::mint(validator, 150 * ONE_SUPRA); add_stake(validator, pool_address, 150 * ONE_SUPRA); let fee = get_add_stake_fee(pool_address, 150 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 250 * ONE_SUPRA - fee, 0, 100 * ONE_SUPRA); - stake::assert_stake_pool(pool_address, 100 * ONE_SUPRA, 0, 150 * ONE_SUPRA, 100 * ONE_SUPRA); + assert_delegation( + validator_address, + pool_address, + 250 * ONE_SUPRA - fee, + 0, + 100 * ONE_SUPRA + ); + stake::assert_stake_pool( + pool_address, + 100 * ONE_SUPRA, + 0, + 150 * ONE_SUPRA, + 100 * ONE_SUPRA + ); // can reactivate only pending_inactive stake reactivate_stake(validator, pool_address, 150 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 350 * ONE_SUPRA - fee, 0, 0); - stake::assert_stake_pool(pool_address, 200 * ONE_SUPRA, 0, 150 * ONE_SUPRA, 0); - assert_pending_withdrawal(validator_address, pool_address, false, 0, false, 0); + assert_delegation( + validator_address, + pool_address, + 350 * ONE_SUPRA - fee, + 0, + 0 + ); + stake::assert_stake_pool( + pool_address, + 200 * ONE_SUPRA, + 0, + 150 * ONE_SUPRA, + 0 + ); + assert_pending_withdrawal( + validator_address, + pool_address, + false, + 0, + false, + 0 + ); end_aptos_epoch(); // 20000000000 active stake * 1.01 + 15000000000 pending_active stake - assert_delegation(validator_address, pool_address, 35200000000, 0, 0); + assert_delegation( + validator_address, + pool_address, + 35200000000, + 0, + 0 + ); // unlock stake added at previous epoch (expect some imprecision when moving shares) unlock(validator, pool_address, 150 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 20200000001, 0, 14999999999); + assert_delegation( + validator_address, + pool_address, + 20200000001, + 0, + 14999999999 + ); stake::assert_stake_pool(pool_address, 20200000001, 0, 0, 14999999999); // inactivate pending_inactive stake @@ -3145,40 +4387,84 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // 20200000001 active stake * 1.01 + 14999999999 pending_inactive stake * 1.01 - assert_delegation(validator_address, pool_address, 20402000001, 15149999998, 0); - assert_pending_withdrawal(validator_address, pool_address, true, 0, true, - 15149999998); + assert_delegation( + validator_address, + pool_address, + 20402000001, + 15149999998, + 0 + ); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 0, + true, + 15149999998 + ); // cannot reactivate inactive stake reactivate_stake(validator, pool_address, 15149999998); - assert_delegation(validator_address, pool_address, 20402000001, 15149999998, 0); + assert_delegation( + validator_address, + pool_address, + 20402000001, + 15149999998, + 0 + ); // unlock stake in the new lockup cycle (the pending withdrawal is executed) unlock(validator, pool_address, 100 * ONE_SUPRA); assert!(coin::balance(validator_address) == 15149999998, 0); - assert_delegation(validator_address, pool_address, 10402000002, 0, 9999999999); - assert_pending_withdrawal(validator_address, pool_address, true, 1, false, - 9999999999); + assert_delegation( + validator_address, + pool_address, + 10402000002, + 0, + 9999999999 + ); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 1, + false, + 9999999999 + ); // reactivate the new pending withdrawal almost entirely reactivate_stake(validator, pool_address, 8999999999); - assert_pending_withdrawal(validator_address, pool_address, true, 1, false, - 1000000000); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 1, + false, + 1000000000 + ); // reactivate remaining stake of the new pending withdrawal reactivate_stake(validator, pool_address, 1000000000); - assert_pending_withdrawal(validator_address, pool_address, false, 0, false, 0); + assert_pending_withdrawal( + validator_address, + pool_address, + false, + 0, + false, + 0 + ); } #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] public entry fun test_withdraw_many( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, validator: &signer, delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010]; let principle_stake = vector[0]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1000 * ONE_SUPRA, true, true, @@ -3190,7 +4476,8 @@ module supra_framework::pbo_delegation_pool { vector[1], 1, principle_lockup_time, - 60); + 60 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -3202,46 +4489,135 @@ module supra_framework::pbo_delegation_pool { add_stake(delegator, pool_address, 200 * ONE_SUPRA); unlock(validator, pool_address, 100 * ONE_SUPRA); - assert_pending_withdrawal(validator_address, pool_address, true, 0, false, 100 * ONE_SUPRA); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 0, + false, + 100 * ONE_SUPRA + ); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - assert_delegation(delegator_address, pool_address, 200 * ONE_SUPRA, 0, 0); - assert_delegation(validator_address, pool_address, 90899999999, 10100000000, 0); - assert_pending_withdrawal(validator_address, pool_address, true, 0, true, - 10100000000); + assert_delegation( + delegator_address, + pool_address, + 200 * ONE_SUPRA, + 0, + 0 + ); + assert_delegation( + validator_address, + pool_address, + 90899999999, + 10100000000, + 0 + ); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 0, + true, + 10100000000 + ); assert_inactive_shares_pool(pool_address, 0, true, 100 * ONE_SUPRA); // check cannot withdraw inactive stake unlocked by others withdraw(delegator, pool_address, MAX_U64); - assert_delegation(delegator_address, pool_address, 200 * ONE_SUPRA, 0, 0); - assert_delegation(validator_address, pool_address, 90899999999, 10100000000, 0); + assert_delegation( + delegator_address, + pool_address, + 200 * ONE_SUPRA, + 0, + 0 + ); + assert_delegation( + validator_address, + pool_address, + 90899999999, + 10100000000, + 0 + ); unlock(delegator, pool_address, 100 * ONE_SUPRA); - assert_delegation(delegator_address, pool_address, 10000000000, 0, 9999999999); - assert_delegation(validator_address, pool_address, 90900000000, 10100000000, 0); - assert_pending_withdrawal(delegator_address, pool_address, true, 1, false, - 9999999999); + assert_delegation( + delegator_address, + pool_address, + 10000000000, + 0, + 9999999999 + ); + assert_delegation( + validator_address, + pool_address, + 90900000000, + 10100000000, + 0 + ); + assert_pending_withdrawal( + delegator_address, + pool_address, + true, + 1, + false, + 9999999999 + ); // check cannot withdraw inactive stake unlocked by others even if owning pending_inactive withdraw(delegator, pool_address, MAX_U64); - assert_delegation(delegator_address, pool_address, 10000000000, 0, 9999999999); - assert_delegation(validator_address, pool_address, 90900000000, 10100000000, 0); + assert_delegation( + delegator_address, + pool_address, + 10000000000, + 0, + 9999999999 + ); + assert_delegation( + validator_address, + pool_address, + 90900000000, + 10100000000, + 0 + ); // withdraw entire owned inactive stake let balance = coin::balance(validator_address); withdraw(validator, pool_address, MAX_U64); - assert!(coin::balance(validator_address) == balance + 10100000000, 0); - assert_pending_withdrawal(validator_address, pool_address, false, 0, false, 0); + assert!( + coin::balance(validator_address) == balance + 10100000000, + 0 + ); + assert_pending_withdrawal( + validator_address, + pool_address, + false, + 0, + false, + 0 + ); assert_inactive_shares_pool(pool_address, 0, false, 0); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - assert_delegation(delegator_address, pool_address, 10100000000, 10099999998, 0); - assert_pending_withdrawal(delegator_address, pool_address, true, 1, true, - 10099999998); + assert_delegation( + delegator_address, + pool_address, + 10100000000, + 10099999998, + 0 + ); + assert_pending_withdrawal( + delegator_address, + pool_address, + true, + 1, + true, + 10099999998 + ); assert_inactive_shares_pool(pool_address, 1, true, 9999999999); // use too small of an unlock amount to actually transfer shares to the pending_inactive pool @@ -3249,30 +4625,56 @@ module supra_framework::pbo_delegation_pool { stake::assert_stake_pool(pool_address, 101909000001, 10099999998, 0, 0); unlock_with_min_stake_disabled(delegator, pool_address, 1); stake::assert_stake_pool(pool_address, 101909000001, 10099999998, 0, 0); - assert_delegation(delegator_address, pool_address, 10100000000, 10099999998, 0); - assert_pending_withdrawal(delegator_address, pool_address, true, 1, true, - 10099999998); - + assert_delegation( + delegator_address, + pool_address, + 10100000000, + 10099999998, + 0 + ); + assert_pending_withdrawal( + delegator_address, + pool_address, + true, + 1, + true, + 10099999998 + ); + // implicitly execute the pending withdrawal by unlocking min stake to buy 1 share unlock_with_min_stake_disabled(delegator, pool_address, 2); stake::assert_stake_pool(pool_address, 101909000000, 0, 0, 1); - assert_delegation(delegator_address, pool_address, 10099999998, 0, 1); + assert_delegation( + delegator_address, + pool_address, + 10099999998, + 0, + 1 + ); // old pending withdrawal has been replaced - assert_pending_withdrawal(delegator_address, pool_address, true, 2, false, 1); + assert_pending_withdrawal( + delegator_address, + pool_address, + true, + 2, + false, + 1 + ); assert_inactive_shares_pool(pool_address, 1, false, 0); assert_inactive_shares_pool(pool_address, 2, true, 1); } #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] public entry fun test_inactivate_no_excess_stake( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, validator: &signer, delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address_vec = vector[@0x010]; let principle_stake = vector[0]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1200 * ONE_SUPRA, true, true, @@ -3284,7 +4686,8 @@ module supra_framework::pbo_delegation_pool { vector[1], 1, principle_lockup_time, - 60); + 60 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -3313,7 +4716,8 @@ module supra_framework::pbo_delegation_pool { let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); principle_lockup_time = LOCKUP_CYCLE_SECONDS + (2 * EPOCH_DURATION); - initialize_test_validator(delegator, + initialize_test_validator( + delegator, 100 * ONE_SUPRA, true, true, @@ -3325,7 +4729,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); // inactivate validator stake::leave_validator_set(validator, pool_address); end_aptos_epoch(); @@ -3340,21 +4745,75 @@ module supra_framework::pbo_delegation_pool { assert!(observed_lockup_cycle(pool_address) == observed_lockup_cycle, 0); // pending_inactive stake has not been inactivated - stake::assert_stake_pool(pool_address, 113231100001, 20200000000, 0, 10200999997); - assert_delegation(delegator_address, pool_address, 10201000000, 0, 10200999997); - assert_delegation(validator_address, pool_address, 103030100000, 20200000000, 0); + stake::assert_stake_pool( + pool_address, + 113231100001, + 20200000000, + 0, + 10200999997 + ); + assert_delegation( + delegator_address, + pool_address, + 10201000000, + 0, + 10200999997 + ); + assert_delegation( + validator_address, + pool_address, + 103030100000, + 20200000000, + 0 + ); // withdraw some inactive stake (remaining pending_inactive is not inactivated) withdraw(validator, pool_address, 200000000); - stake::assert_stake_pool(pool_address, 113231100001, 20000000001, 0, 10200999997); - assert_delegation(delegator_address, pool_address, 10201000000, 0, 10200999997); - assert_delegation(validator_address, pool_address, 103030100000, 20000000001, 0); + stake::assert_stake_pool( + pool_address, + 113231100001, + 20000000001, + 0, + 10200999997 + ); + assert_delegation( + delegator_address, + pool_address, + 10201000000, + 0, + 10200999997 + ); + assert_delegation( + validator_address, + pool_address, + 103030100000, + 20000000001, + 0 + ); // withdraw some pending_inactive stake (remaining pending_inactive is not inactivated) withdraw(delegator, pool_address, 200999997); - stake::assert_stake_pool(pool_address, 113231100001, 20000000001, 0, 10000000001); - assert_delegation(delegator_address, pool_address, 10201000000, 0, 10000000001); - assert_delegation(validator_address, pool_address, 103030100000, 20000000001, 0); + stake::assert_stake_pool( + pool_address, + 113231100001, + 20000000001, + 0, + 10000000001 + ); + assert_delegation( + delegator_address, + pool_address, + 10201000000, + 0, + 10000000001 + ); + assert_delegation( + validator_address, + pool_address, + 103030100000, + 20000000001, + 0 + ); // no new inactive stake detected => OLC does not advance assert!(observed_lockup_cycle(pool_address) == observed_lockup_cycle, 0); @@ -3363,61 +4822,150 @@ module supra_framework::pbo_delegation_pool { withdraw(delegator, pool_address, 10201000000); assert!(observed_lockup_cycle(pool_address) == observed_lockup_cycle, 0); - assert_delegation(delegator_address, pool_address, 0, 0, 10000000002); - assert_delegation(validator_address, pool_address, 103030100001, 20000000001, 0); - assert_pending_withdrawal(validator_address, pool_address, true, 0, true, - 20000000001); - assert_pending_withdrawal(delegator_address, pool_address, true, 1, false, - 10000000002); - stake::assert_stake_pool(pool_address, 103030100001, 20000000001, 0, 10000000002); + assert_delegation( + delegator_address, + pool_address, + 0, + 0, + 10000000002 + ); + assert_delegation( + validator_address, + pool_address, + 103030100001, + 20000000001, + 0 + ); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 0, + true, + 20000000001 + ); + assert_pending_withdrawal( + delegator_address, + pool_address, + true, + 1, + false, + 10000000002 + ); + stake::assert_stake_pool( + pool_address, + 103030100001, + 20000000001, + 0, + 10000000002 + ); // reactivate validator stake::join_validator_set(validator, pool_address); - assert!(stake::get_validator_state(pool_address) == VALIDATOR_STATUS_PENDING_ACTIVE, - 0); + assert!( + stake::get_validator_state(pool_address) == VALIDATOR_STATUS_PENDING_ACTIVE, + 0 + ); end_aptos_epoch(); assert!(stake::get_validator_state(pool_address) == VALIDATOR_STATUS_ACTIVE, 0); // no rewards have been produced yet and no stake inactivated as lockup has been refreshed - stake::assert_stake_pool(pool_address, 103030100001, 20000000001, 0, 10000000002); + stake::assert_stake_pool( + pool_address, + 103030100001, + 20000000001, + 0, + 10000000002 + ); synchronize_delegation_pool(pool_address); - assert_pending_withdrawal(validator_address, pool_address, true, 0, true, - 20000000001); - assert_pending_withdrawal(delegator_address, pool_address, true, 1, false, - 10000000002); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 0, + true, + 20000000001 + ); + assert_pending_withdrawal( + delegator_address, + pool_address, + true, + 1, + false, + 10000000002 + ); assert!(observed_lockup_cycle(pool_address) == observed_lockup_cycle, 0); // cannot withdraw pending_inactive stake anymore withdraw(delegator, pool_address, 10000000002); - assert_pending_withdrawal(delegator_address, pool_address, true, 1, false, - 10000000002); + assert_pending_withdrawal( + delegator_address, + pool_address, + true, + 1, + false, + 10000000002 + ); // earning rewards is resumed from this epoch on end_aptos_epoch(); - stake::assert_stake_pool(pool_address, 104060401001, 20000000001, 0, 10100000002); + stake::assert_stake_pool( + pool_address, + 104060401001, + 20000000001, + 0, + 10100000002 + ); // new pending_inactive stake earns rewards but so does the old one unlock(validator, pool_address, 104060401001); - assert_pending_withdrawal(validator_address, pool_address, true, 1, false, - 104060401000); - assert_pending_withdrawal(delegator_address, pool_address, true, 1, false, - 10100000002); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 1, + false, + 104060401000 + ); + assert_pending_withdrawal( + delegator_address, + pool_address, + true, + 1, + false, + 10100000002 + ); end_aptos_epoch(); - assert_pending_withdrawal(validator_address, pool_address, true, 1, false, - 105101005010); - assert_pending_withdrawal(delegator_address, pool_address, true, 1, false, - 10201000002); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 1, + false, + 105101005010 + ); + assert_pending_withdrawal( + delegator_address, + pool_address, + true, + 1, + false, + 10201000002 + ); } #[test(supra_framework = @supra_framework, validator = @0x123)] - public entry fun test_active_stake_rewards(supra_framework: &signer, validator: &signer,) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_active_stake_rewards( + supra_framework: &signer, validator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[]; let principle_stake = vector[]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1000 * ONE_SUPRA, true, true, @@ -3429,29 +4977,54 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); end_aptos_epoch(); // 100000000000 active stake * 1.01 - assert_delegation(validator_address, pool_address, 1010 * ONE_SUPRA, 0, 0); + assert_delegation( + validator_address, + pool_address, + 1010 * ONE_SUPRA, + 0, + 0 + ); // add stake in pending_active state stake::mint(validator, 200 * ONE_SUPRA); add_stake(validator, pool_address, 200 * ONE_SUPRA); let fee = get_add_stake_fee(pool_address, 200 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 1210 * ONE_SUPRA - fee, 0, 0); + assert_delegation( + validator_address, + pool_address, + 1210 * ONE_SUPRA - fee, + 0, + 0 + ); end_aptos_epoch(); // 101000000000 active stake * 1.01 + 20000000000 pending_active stake with no rewards - assert_delegation(validator_address, pool_address, 122010000000, 0, 0); + assert_delegation( + validator_address, + pool_address, + 122010000000, + 0, + 0 + ); end_aptos_epoch(); // 122010000000 active stake * 1.01 - assert_delegation(validator_address, pool_address, 123230100000, 0, 0); + assert_delegation( + validator_address, + pool_address, + 123230100000, + 0, + 0 + ); // 123230100000 active stake * 1.01 end_aptos_epoch(); @@ -3463,49 +5036,91 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // 128233736212 active stake * 1.01 end_aptos_epoch(); - assert_delegation(validator_address, pool_address, 129516073574, 0, 0); + assert_delegation( + validator_address, + pool_address, + 129516073574, + 0, + 0 + ); // unlock 200 coins from delegator `validator` unlock(validator, pool_address, 200 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 109516073575, 0, 19999999999); + assert_delegation( + validator_address, + pool_address, + 109516073575, + 0, + 19999999999 + ); // end this lockup cycle timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); // 109516073575 active stake * 1.01 + 19999999999 pending_inactive stake * 1.01 - assert_delegation(validator_address, pool_address, 110611234310, 20199999998, 0); + assert_delegation( + validator_address, + pool_address, + 110611234310, + 20199999998, + 0 + ); end_aptos_epoch(); // 110611234310 active stake * 1.01 + 20199999998 inactive stake - assert_delegation(validator_address, pool_address, 111717346653, 20199999998, 0); + assert_delegation( + validator_address, + pool_address, + 111717346653, + 20199999998, + 0 + ); // add stake in pending_active state stake::mint(validator, 1000 * ONE_SUPRA); add_stake(validator, pool_address, 1000 * ONE_SUPRA); fee = get_add_stake_fee(pool_address, 1000 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 211717346653 - fee, 20199999998, - 0); + assert_delegation( + validator_address, + pool_address, + 211717346653 - fee, + 20199999998, + 0 + ); end_aptos_epoch(); // 111717346653 active stake * 1.01 + 100000000000 pending_active stake + 20199999998 inactive stake - assert_delegation(validator_address, pool_address, 212834520119, 20199999998, 0); + assert_delegation( + validator_address, + pool_address, + 212834520119, + 20199999998, + 0 + ); end_aptos_epoch(); // 212834520119 active stake * 1.01 + 20199999998 inactive stake - assert_delegation(validator_address, pool_address, 214962865320, 20199999998, 0); + assert_delegation( + validator_address, + pool_address, + 214962865320, + 20199999998, + 0 + ); } #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] public entry fun test_active_stake_rewards_multiple( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, validator: &signer, delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010]; let principle_stake = vector[0]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 200 * ONE_SUPRA, true, true, @@ -3517,7 +5132,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -3528,31 +5144,97 @@ module supra_framework::pbo_delegation_pool { add_stake(delegator, pool_address, 300 * ONE_SUPRA); let fee = get_add_stake_fee(pool_address, 300 * ONE_SUPRA); - assert_delegation(delegator_address, pool_address, 300 * ONE_SUPRA - fee, 0, 0); - assert_delegation(validator_address, pool_address, 200 * ONE_SUPRA, 0, 0); - stake::assert_stake_pool(pool_address, 200 * ONE_SUPRA, 0, 300 * ONE_SUPRA, 0); + assert_delegation( + delegator_address, + pool_address, + 300 * ONE_SUPRA - fee, + 0, + 0 + ); + assert_delegation( + validator_address, + pool_address, + 200 * ONE_SUPRA, + 0, + 0 + ); + stake::assert_stake_pool( + pool_address, + 200 * ONE_SUPRA, + 0, + 300 * ONE_SUPRA, + 0 + ); end_aptos_epoch(); // `delegator` got its `add_stake` fee back and `validator` its active stake rewards - assert_delegation(delegator_address, pool_address, 300 * ONE_SUPRA, 0, 0); - assert_delegation(validator_address, pool_address, 20199999999, 0, 0); + assert_delegation( + delegator_address, + pool_address, + 300 * ONE_SUPRA, + 0, + 0 + ); + assert_delegation( + validator_address, + pool_address, + 20199999999, + 0, + 0 + ); stake::assert_stake_pool(pool_address, 502 * ONE_SUPRA, 0, 0, 0); // delegators earn their own rewards from now on end_aptos_epoch(); - assert_delegation(delegator_address, pool_address, 303 * ONE_SUPRA, 0, 0); - assert_delegation(validator_address, pool_address, 20401999999, 0, 0); + assert_delegation( + delegator_address, + pool_address, + 303 * ONE_SUPRA, + 0, + 0 + ); + assert_delegation( + validator_address, + pool_address, + 20401999999, + 0, + 0 + ); stake::assert_stake_pool(pool_address, 50702000000, 0, 0, 0); // delegators earn their own rewards from now on end_aptos_epoch(); - assert_delegation(delegator_address, pool_address, 30603000000, 0, 0); - assert_delegation(validator_address, pool_address, 20606019999, 0, 0); + assert_delegation( + delegator_address, + pool_address, + 30603000000, + 0, + 0 + ); + assert_delegation( + validator_address, + pool_address, + 20606019999, + 0, + 0 + ); stake::assert_stake_pool(pool_address, 51209020000, 0, 0, 0); end_aptos_epoch(); - assert_delegation(delegator_address, pool_address, 30909030000, 0, 0); - assert_delegation(validator_address, pool_address, 20812080199, 0, 0); + assert_delegation( + delegator_address, + pool_address, + 30909030000, + 0, + 0 + ); + assert_delegation( + validator_address, + pool_address, + 20812080199, + 0, + 0 + ); stake::assert_stake_pool(pool_address, 51721110200, 0, 0, 0); // add more stake in pending_active state than currently active @@ -3560,26 +5242,51 @@ module supra_framework::pbo_delegation_pool { add_stake(delegator, pool_address, 1000 * ONE_SUPRA); fee = get_add_stake_fee(pool_address, 1000 * ONE_SUPRA); - assert_delegation(delegator_address, pool_address, 130909030000 - fee, 0, 0); - assert_delegation(validator_address, pool_address, 20812080199, 0, 0); + assert_delegation( + delegator_address, + pool_address, + 130909030000 - fee, + 0, + 0 + ); + assert_delegation( + validator_address, + pool_address, + 20812080199, + 0, + 0 + ); end_aptos_epoch(); // `delegator` got its `add_stake` fee back and `validator` its active stake rewards - assert_delegation(delegator_address, pool_address, 131218120300, 0, 0); - assert_delegation(validator_address, pool_address, 21020201001, 0, 0); + assert_delegation( + delegator_address, + pool_address, + 131218120300, + 0, + 0 + ); + assert_delegation( + validator_address, + pool_address, + 21020201001, + 0, + 0 + ); stake::assert_stake_pool(pool_address, 152238321302, 0, 0, 0); } #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_pending_inactive_stake_rewards( - supra_framework: &signer, validator: &signer, + supra_framework: &signer, validator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[]; let principle_stake = vector[]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1000 * ONE_SUPRA, true, true, @@ -3591,17 +5298,30 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); end_aptos_epoch(); - assert_delegation(validator_address, pool_address, 1010 * ONE_SUPRA, 0, 0); + assert_delegation( + validator_address, + pool_address, + 1010 * ONE_SUPRA, + 0, + 0 + ); // unlock 200 coins from delegator `validator` unlock(validator, pool_address, 200 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 81000000001, 0, 19999999999); + assert_delegation( + validator_address, + pool_address, + 81000000001, + 0, + 19999999999 + ); end_aptos_epoch(); // 81000000001 active stake * 1.01 + 19999999999 pending_inactive stake * 1.01 end_aptos_epoch(); // 81810000001 active stake * 1.01 + 20199999998 pending_inactive stake * 1.01 @@ -3609,40 +5329,72 @@ module supra_framework::pbo_delegation_pool { timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); // 82628100001 active stake * 1.01 + 20401999997 pending_inactive stake * 1.01 end_aptos_epoch(); // 83454381001 active stake * 1.01 + 20606019996 pending_inactive stake(now inactive) - assert_delegation(validator_address, pool_address, 84288924811, 20606019996, 0); + assert_delegation( + validator_address, + pool_address, + 84288924811, + 20606019996, + 0 + ); // unlock 200 coins from delegator `validator` which implicitly executes its pending withdrawal unlock(validator, pool_address, 200 * ONE_SUPRA); assert!(coin::balance(validator_address) == 20606019996, 0); - assert_delegation(validator_address, pool_address, 64288924812, 0, 19999999999); + assert_delegation( + validator_address, + pool_address, + 64288924812, + 0, + 19999999999 + ); // lockup cycle is not ended, pending_inactive stake is still earning end_aptos_epoch(); // 64288924812 active stake * 1.01 + 19999999999 pending_inactive stake * 1.01 end_aptos_epoch(); // 64931814060 active stake * 1.01 + 20199999998 pending_inactive stake * 1.01 end_aptos_epoch(); // 65581132200 active stake * 1.01 + 20401999997 pending_inactive stake * 1.01 end_aptos_epoch(); // 66236943522 active stake * 1.01 + 20606019996 pending_inactive stake * 1.01 - assert_delegation(validator_address, pool_address, 66899312957, 0, 20812080195); + assert_delegation( + validator_address, + pool_address, + 66899312957, + 0, + 20812080195 + ); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); // 66899312957 active stake * 1.01 + 20812080195 pending_inactive stake * 1.01 end_aptos_epoch(); // 67568306086 active stake * 1.01 + 21020200996 pending_inactive stake(now inactive) end_aptos_epoch(); // 68243989147 active stake * 1.01 + 21020200996 inactive stake - assert_delegation(validator_address, pool_address, 68926429037, 21020200996, 0); + assert_delegation( + validator_address, + pool_address, + 68926429037, + 21020200996, + 0 + ); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator1 = @0x010, + delegator2 = @0x020 + ) + ] public entry fun test_out_of_order_redeem( supra_framework: &signer, validator: &signer, delegator1: &signer, - delegator2: &signer, + delegator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x111]; let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1000 * ONE_SUPRA, true, true, @@ -3654,7 +5406,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -3675,8 +5428,14 @@ module supra_framework::pbo_delegation_pool { // create the pending withdrawal of delegator 1 in lockup cycle 0 unlock(delegator1, pool_address, 150 * ONE_SUPRA); - assert_pending_withdrawal(delegator1_address, pool_address, true, 0, false, - 14999999999); + assert_pending_withdrawal( + delegator1_address, + pool_address, + true, + 0, + false, + 14999999999 + ); // move to lockup cycle 1 timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); @@ -3684,62 +5443,134 @@ module supra_framework::pbo_delegation_pool { // create the pending withdrawal of delegator 2 in lockup cycle 1 unlock(delegator2, pool_address, 150 * ONE_SUPRA); - assert_pending_withdrawal(delegator2_address, pool_address, true, 1, false, - 14999999999); + assert_pending_withdrawal( + delegator2_address, + pool_address, + true, + 1, + false, + 14999999999 + ); // 14999999999 pending_inactive stake * 1.01 - assert_pending_withdrawal(delegator1_address, pool_address, true, 0, true, - 15149999998); + assert_pending_withdrawal( + delegator1_address, + pool_address, + true, + 0, + true, + 15149999998 + ); // move to lockup cycle 2 timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - assert_pending_withdrawal(delegator2_address, pool_address, true, 1, true, - 15149999998); - assert_pending_withdrawal(delegator1_address, pool_address, true, 0, true, - 15149999998); + assert_pending_withdrawal( + delegator2_address, + pool_address, + true, + 1, + true, + 15149999998 + ); + assert_pending_withdrawal( + delegator1_address, + pool_address, + true, + 0, + true, + 15149999998 + ); // both delegators who unlocked at different lockup cycles should be able to withdraw their stakes withdraw(delegator1, pool_address, 15149999998); withdraw(delegator2, pool_address, 5149999998); - assert_pending_withdrawal(delegator2_address, pool_address, true, 1, true, - 10000000001); - assert_pending_withdrawal(delegator1_address, pool_address, false, 0, false, 0); - assert!(coin::balance(delegator1_address) == 15149999998, 0); - assert!(coin::balance(delegator2_address) == 5149999997, 0); - - // recreate the pending withdrawal of delegator 1 in lockup cycle 2 - unlock(delegator1, pool_address, 100 * ONE_SUPRA); - - // move to lockup cycle 3 - timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + assert_pending_withdrawal( + delegator2_address, + pool_address, + true, + 1, + true, + 10000000001 + ); + assert_pending_withdrawal( + delegator1_address, + pool_address, + false, + 0, + false, + 0 + ); + assert!(coin::balance(delegator1_address) == 15149999998, 0); + assert!(coin::balance(delegator2_address) == 5149999997, 0); + + // recreate the pending withdrawal of delegator 1 in lockup cycle 2 + unlock(delegator1, pool_address, 100 * ONE_SUPRA); + + // move to lockup cycle 3 + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - assert_pending_withdrawal(delegator2_address, pool_address, true, 1, true, - 10000000001); + assert_pending_withdrawal( + delegator2_address, + pool_address, + true, + 1, + true, + 10000000001 + ); // 9999999999 pending_inactive stake * 1.01 - assert_pending_withdrawal(delegator1_address, pool_address, true, 2, true, - 10099999998); + assert_pending_withdrawal( + delegator1_address, + pool_address, + true, + 2, + true, + 10099999998 + ); // withdraw inactive stake of delegator 2 left from lockup cycle 1 in cycle 3 withdraw(delegator2, pool_address, 10000000001); assert!(coin::balance(delegator2_address) == 15149999998, 0); - assert_pending_withdrawal(delegator2_address, pool_address, false, 0, false, 0); + assert_pending_withdrawal( + delegator2_address, + pool_address, + false, + 0, + false, + 0 + ); // withdraw inactive stake of delegator 1 left from previous lockup cycle withdraw(delegator1, pool_address, 10099999998); - assert!(coin::balance(delegator1_address) == 15149999998 + 10099999998, - 0); - assert_pending_withdrawal(delegator1_address, pool_address, false, 0, false, 0); + assert!( + coin::balance(delegator1_address) == 15149999998 + 10099999998, + 0 + ); + assert_pending_withdrawal( + delegator1_address, + pool_address, + false, + 0, + false, + 0 + ); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator1 = @0x010, + delegator2 = @0x020 + ) + ] public entry fun test_operator_fee( supra_framework: &signer, validator: &signer, delegator1: &signer, - delegator2: &signer, + delegator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let validator_address = signer::address_of(validator); @@ -3750,7 +5581,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 0; // create delegation pool of commission fee 12.65% - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, option::none(), 1265, vector::empty(), @@ -3760,7 +5592,8 @@ module supra_framework::pbo_delegation_pool { vector[1], 1, principle_lockup_time, - 60); + 60 + ); let pool_address = get_owned_pool_address(validator_address); assert!(stake::get_operator(pool_address) == validator_address, 0); @@ -3792,9 +5625,21 @@ module supra_framework::pbo_delegation_pool { // 300000000 active rewards * 0.1265 assert_delegation(validator_address, pool_address, 37950000, 0, 0); // 10000000000 active stake * (1 + 1% reward-rate * 0.8735) - assert_delegation(delegator1_address, pool_address, 10087350000, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + 10087350000, + 0, + 0 + ); // 20000000000 active stake * 1.008735 - assert_delegation(delegator2_address, pool_address, 20174700000, 0, 0); + assert_delegation( + delegator2_address, + pool_address, + 20174700000, + 0, + 0 + ); end_aptos_epoch(); stake::assert_stake_pool(pool_address, 30603000000, 0, 0, 0); @@ -3804,9 +5649,21 @@ module supra_framework::pbo_delegation_pool { // because operator commission rewards are not automatically restaked compared to already owned stake assert_delegation(validator_address, pool_address, 76279500, 0, 0); // 10087350000 active stake * 1.008735 + some of the rewards of previous commission if restaked - assert_delegation(delegator1_address, pool_address, 10175573500, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + 10175573500, + 0, + 0 + ); // 20174700000 active stake * 1.008735 + some of the rewards of previous commission if restaked - assert_delegation(delegator2_address, pool_address, 20351147000, 0, 0); + assert_delegation( + delegator2_address, + pool_address, + 20351147000, + 0, + 0 + ); // restake operator commission rewards synchronize_delegation_pool(pool_address); @@ -3815,11 +5672,29 @@ module supra_framework::pbo_delegation_pool { stake::assert_stake_pool(pool_address, 30909030000, 0, 0, 0); // 306030000 active rewards * 0.1265 + 76279500 active stake * 1.008735 - assert_delegation(validator_address, pool_address, 115658596, 0, 0); + assert_delegation( + validator_address, + pool_address, + 115658596, + 0, + 0 + ); // 10175573500 active stake * 1.008735 - assert_delegation(delegator1_address, pool_address, 10264457134, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + 10264457134, + 0, + 0 + ); // 20351147000 active stake * 1.008735 - assert_delegation(delegator2_address, pool_address, 20528914269, 0, 0); + assert_delegation( + delegator2_address, + pool_address, + 20528914269, + 0, + 0 + ); // check operator is rewarded by pending_inactive stake too unlock(delegator2, pool_address, 100 * ONE_SUPRA); @@ -3828,21 +5703,52 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); stake::assert_stake_pool(pool_address, 21118120301, 0, 0, 10099999998); - assert_pending_withdrawal(validator_address, pool_address, false, 0, false, 0); + assert_pending_withdrawal( + validator_address, + pool_address, + false, + 0, + false, + 0 + ); // distribute operator pending_inactive commission rewards synchronize_delegation_pool(pool_address); // 99999999 pending_inactive rewards * 0.1265 - assert_pending_withdrawal(validator_address, pool_address, true, 0, false, - 12649998); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 0, + false, + 12649998 + ); // 209090300 active rewards * 0.1265 + 115658596 active stake * 1.008735 // 99999999 pending_inactive rewards * 0.1265 - assert_delegation(validator_address, pool_address, 143118796, 0, 12649998); + assert_delegation( + validator_address, + pool_address, + 143118796, + 0, + 12649998 + ); // 10264457134 active stake * 1.008735 - assert_delegation(delegator1_address, pool_address, 10354117168, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + 10354117168, + 0, + 0 + ); // 10528914270 active stake * 1.008735 // 9999999999 pending_inactive stake * 1.008735 - assert_delegation(delegator2_address, pool_address, 10620884336, 0, 10087349999); + assert_delegation( + delegator2_address, + pool_address, + 10620884336, + 0, + 10087349999 + ); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); @@ -3851,34 +5757,81 @@ module supra_framework::pbo_delegation_pool { // operator pending_inactive rewards on previous epoch have been inactivated // 211181203 active rewards * 0.1265 + 143118796 active stake * 1.008735 // 100999999 pending_inactive rewards * 0.1265 + 12649998 pending_inactive stake * 1.008735 - assert_delegation(validator_address, pool_address, 171083360, 25536995, 0); + assert_delegation( + validator_address, + pool_address, + 171083360, + 25536995, + 0 + ); // distribute operator pending_inactive commission rewards synchronize_delegation_pool(pool_address); - assert_pending_withdrawal(validator_address, pool_address, true, 0, true, 25536995); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 0, + true, + 25536995 + ); // check operator is not rewarded by `add_stake` fees stake::mint(delegator1, 100 * ONE_SUPRA); - assert!(get_add_stake_fee(pool_address, 100 * ONE_SUPRA) > 0, 0); + assert!( + get_add_stake_fee(pool_address, 100 * ONE_SUPRA) > 0, + 0 + ); add_stake(delegator1, pool_address, 100 * ONE_SUPRA); end_aptos_epoch(); stake::assert_stake_pool(pool_address, 31542594519, 10200999997, 0, 0); // 213293015 active rewards * 0.1265 + 171083360 active stake * 1.008735 - assert_delegation(validator_address, pool_address, 199559340, 25536995, 0); + assert_delegation( + validator_address, + pool_address, + 199559340, + 25536995, + 0 + ); // unlock some more stake to produce pending_inactive commission // 10620884336 active stake * (1.008735 ^ 2 epochs) // 10087349999 pending_inactive stake * 1.008735 - assert_delegation(delegator2_address, pool_address, 10807241561, 10175463001, 0); + assert_delegation( + delegator2_address, + pool_address, + 10807241561, + 10175463001, + 0 + ); unlock(delegator2, pool_address, 100 * ONE_SUPRA); // 10807241561 - 100 SUPRA < `MIN_COINS_ON_SHARES_POOL` thus active stake is entirely unlocked - assert_delegation(delegator2_address, pool_address, 807241561, 0, 9999999999); + assert_delegation( + delegator2_address, + pool_address, + 807241561, + 0, + 9999999999 + ); end_aptos_epoch(); // in-flight pending_inactive commission can coexist with previous inactive commission - assert_delegation(validator_address, pool_address, 228553872, 25536996, 12649999); - assert_pending_withdrawal(validator_address, pool_address, true, 0, true, 25536996); + assert_delegation( + validator_address, + pool_address, + 228553872, + 25536996, + 12649999 + ); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 0, + true, + 25536996 + ); // distribute in-flight pending_inactive commission, implicitly executing the inactive withdrawal of operator coin::register(validator); @@ -3887,17 +5840,36 @@ module supra_framework::pbo_delegation_pool { // in-flight commission has been synced, implicitly used to buy shares for operator // expect operator stake to be slightly less than previously reported by `Self::get_stake` - assert_delegation(validator_address, pool_address, 228553872, 0, 12649998); - assert_pending_withdrawal(validator_address, pool_address, true, 1, false, - 12649998); + assert_delegation( + validator_address, + pool_address, + 228553872, + 0, + 12649998 + ); + assert_pending_withdrawal( + validator_address, + pool_address, + true, + 1, + false, + 12649998 + ); } - #[test(supra_framework = @supra_framework, old_operator = @0x123, delegator = @0x010, new_operator = @0x020)] + #[ + test( + supra_framework = @supra_framework, + old_operator = @0x123, + delegator = @0x010, + new_operator = @0x020 + ) + ] public entry fun test_change_operator( supra_framework: &signer, old_operator: &signer, delegator: &signer, - new_operator: &signer, + new_operator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); @@ -3912,7 +5884,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 0; // create delegation pool of commission fee 12.65% - initialize_delegation_pool(old_operator, + initialize_delegation_pool( + old_operator, option::none(), 1265, vector::empty(), @@ -3922,7 +5895,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let pool_address = get_owned_pool_address(old_operator_address); assert!(stake::get_operator(pool_address) == old_operator_address, 0); @@ -3941,10 +5915,22 @@ module supra_framework::pbo_delegation_pool { // produce active and pending_inactive rewards end_aptos_epoch(); stake::assert_stake_pool(pool_address, 10100000000, 0, 0, 10100000000); - assert_delegation(old_operator_address, pool_address, 12650000, 0, 12650000); + assert_delegation( + old_operator_address, + pool_address, + 12650000, + 0, + 12650000 + ); end_aptos_epoch(); stake::assert_stake_pool(pool_address, 10201000000, 0, 0, 10201000000); - assert_delegation(old_operator_address, pool_address, 25426500, 0, 25426500); + assert_delegation( + old_operator_address, + pool_address, + 25426500, + 0, + 25426500 + ); // change operator set_operator(old_operator, new_operator_address); @@ -3952,9 +5938,21 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); stake::assert_stake_pool(pool_address, 10303010000, 0, 0, 10303010000); // 25426500 active stake * 1.008735 and 25426500 pending_inactive stake * 1.008735 - assert_delegation(old_operator_address, pool_address, 25648600, 0, 25648600); + assert_delegation( + old_operator_address, + pool_address, + 25648600, + 0, + 25648600 + ); // 102010000 active rewards * 0.1265 and 102010000 pending_inactive rewards * 0.1265 - assert_delegation(new_operator_address, pool_address, 12904265, 0, 12904265); + assert_delegation( + new_operator_address, + pool_address, + 12904265, + 0, + 12904265 + ); // restake `new_operator` commission rewards synchronize_delegation_pool(pool_address); @@ -3962,19 +5960,39 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); stake::assert_stake_pool(pool_address, 10406040100, 0, 0, 10406040100); // 25648600 active stake * 1.008735 and 25648600 pending_inactive stake * 1.008735 - assert_delegation(old_operator_address, pool_address, 25872641, 0, 25872641); + assert_delegation( + old_operator_address, + pool_address, + 25872641, + 0, + 25872641 + ); // 103030100 active rewards * 0.1265 and 12904265 active stake * 1.008735 // 103030100 pending_inactive rewards * 0.1265 and 12904265 pending_inactive stake * 1.008735 - assert_delegation(new_operator_address, pool_address, 26050290, 0, 26050290); + assert_delegation( + new_operator_address, + pool_address, + 26050290, + 0, + 26050290 + ); } - #[test(supra_framework = @supra_framework, operator1 = @0x123, delegator = @0x010, beneficiary = @0x020, operator2 = @0x030)] + #[ + test( + supra_framework = @supra_framework, + operator1 = @0x123, + delegator = @0x010, + beneficiary = @0x020, + operator2 = @0x030 + ) + ] public entry fun test_set_beneficiary_for_operator( supra_framework: &signer, operator1: &signer, delegator: &signer, beneficiary: &signer, - operator2: &signer, + operator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); @@ -3991,7 +6009,8 @@ module supra_framework::pbo_delegation_pool { let coin = stake::mint_coins(0); let principle_lockup_time = 0; // create delegation pool of commission fee 12.65% - initialize_delegation_pool(operator1, + initialize_delegation_pool( + operator1, option::none(), 1265, vector::empty(), @@ -4001,7 +6020,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let pool_address = get_owned_pool_address(operator1_address); assert!(stake::get_operator(pool_address) == operator1_address, 0); assert!(beneficiary_for_operator(operator1_address) == operator1_address, 0); @@ -4019,16 +6039,43 @@ module supra_framework::pbo_delegation_pool { // produce active and pending_inactive rewards end_aptos_epoch(); - stake::assert_stake_pool(pool_address, 101000000000000, 0, 0, 101000000000000); - assert_delegation(operator1_address, pool_address, 126500000000, 0, 126500000000); + stake::assert_stake_pool( + pool_address, + 101000000000000, + 0, + 0, + 101000000000000 + ); + assert_delegation( + operator1_address, + pool_address, + 126500000000, + 0, + 126500000000 + ); end_aptos_epoch(); - stake::assert_stake_pool(pool_address, 102010000000000, 0, 0, 102010000000000); - assert_delegation(operator1_address, pool_address, 254265000000, 0, 254265000000); + stake::assert_stake_pool( + pool_address, + 102010000000000, + 0, + 0, + 102010000000000 + ); + assert_delegation( + operator1_address, + pool_address, + 254265000000, + 0, + 254265000000 + ); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); withdraw(operator1, pool_address, ONE_SUPRA); - assert!(coin::balance(operator1_address) == ONE_SUPRA - 1, 0); + assert!( + coin::balance(operator1_address) == ONE_SUPRA - 1, + 0 + ); set_beneficiary_for_operator(operator1, beneficiary_address); assert!(beneficiary_for_operator(operator1_address) == beneficiary_address, 0); @@ -4039,8 +6086,14 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); withdraw(beneficiary, pool_address, ONE_SUPRA); - assert!(coin::balance(beneficiary_address) == ONE_SUPRA - 1, 0); - assert!(coin::balance(operator1_address) == ONE_SUPRA - 1, 0); + assert!( + coin::balance(beneficiary_address) == ONE_SUPRA - 1, + 0 + ); + assert!( + coin::balance(operator1_address) == ONE_SUPRA - 1, + 0 + ); // switch operator to operator2. The rewards should go to operator2 not to the beneficiay of operator1. set_operator(operator1, operator2_address); @@ -4050,13 +6103,19 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); withdraw(operator2, pool_address, ONE_SUPRA); - assert!(coin::balance(beneficiary_address) == ONE_SUPRA - 1, 0); - assert!(coin::balance(operator2_address) == ONE_SUPRA - 1, 0); + assert!( + coin::balance(beneficiary_address) == ONE_SUPRA - 1, + 0 + ); + assert!( + coin::balance(operator2_address) == ONE_SUPRA - 1, + 0 + ); } #[test(supra_framework = @supra_framework, operator = @0x123, delegator = @0x010)] public entry fun test_update_commission_percentage( - supra_framework: &signer, operator: &signer, delegator: &signer, + supra_framework: &signer, operator: &signer, delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); @@ -4067,7 +6126,8 @@ module supra_framework::pbo_delegation_pool { let coin = stake::mint_coins(0); let principle_lockup_time = 0; // create delegation pool of commission fee 12.65% - initialize_delegation_pool(operator, + initialize_delegation_pool( + operator, option::none(), 1265, vector::empty(), @@ -4077,7 +6137,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let pool_address = get_owned_pool_address(operator_address); assert!(stake::get_operator(pool_address) == operator_address, 0); @@ -4096,10 +6157,22 @@ module supra_framework::pbo_delegation_pool { // produce active and pending_inactive rewards end_aptos_epoch(); stake::assert_stake_pool(pool_address, 10100000000, 0, 0, 10100000000); - assert_delegation(operator_address, pool_address, 12650000, 0, 12650000); + assert_delegation( + operator_address, + pool_address, + 12650000, + 0, + 12650000 + ); end_aptos_epoch(); stake::assert_stake_pool(pool_address, 10201000000, 0, 0, 10201000000); - assert_delegation(operator_address, pool_address, 25426500, 0, 25426500); + assert_delegation( + operator_address, + pool_address, + 25426500, + 0, + 25426500 + ); // change the commission percentage update_commission_percentage(operator, 2265); @@ -4111,7 +6184,10 @@ module supra_framework::pbo_delegation_pool { // Test that the `get_add_stake_fee` correctly uses the new commission percentage, and returns the correct // fee amount 76756290 in the following case, not 86593604 (calculated with the old commission rate). - assert!(get_add_stake_fee(pool_address, 100 * ONE_SUPRA) == 76756290, 0); + assert!( + get_add_stake_fee(pool_address, 100 * ONE_SUPRA) == 76756290, + 0 + ); synchronize_delegation_pool(pool_address); // the commission percentage is updated to the new one. @@ -4119,17 +6195,29 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); stake::assert_stake_pool(pool_address, 10406040100, 10303010000, 0, 0); - assert_delegation(operator_address, pool_address, 62187388, 38552865, 0); + assert_delegation( + operator_address, + pool_address, + 62187388, + 38552865, + 0 + ); end_aptos_epoch(); stake::assert_stake_pool(pool_address, 10510100501, 10303010000, 0, 0); - assert_delegation(operator_address, pool_address, 86058258, 38552865, 0); + assert_delegation( + operator_address, + pool_address, + 86058258, + 38552865, + 0 + ); } #[test(supra_framework = @supra_framework, operator = @0x123, delegator = @0x010)] #[expected_failure(abort_code = 196629, location = Self)] public entry fun test_last_minute_commission_rate_change_failed( - supra_framework: &signer, operator: &signer, delegator: &signer, + supra_framework: &signer, operator: &signer, delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let operator_address = signer::address_of(operator); @@ -4139,7 +6227,8 @@ module supra_framework::pbo_delegation_pool { let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 0; // create delegation pool of commission fee 12.65% - initialize_delegation_pool(operator, + initialize_delegation_pool( + operator, option::none(), 1265, vector::empty(), @@ -4149,7 +6238,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let pool_address = get_owned_pool_address(operator_address); assert!(stake::get_operator(pool_address) == operator_address, 0); @@ -4189,19 +6279,27 @@ module supra_framework::pbo_delegation_pool { update_commission_percentage(operator, 2255); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator1 = @0x010, + delegator2 = @0x020 + ) + ] public entry fun test_min_stake_is_preserved( supra_framework: &signer, validator: &signer, delegator1: &signer, - delegator2: &signer, + delegator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x111]; let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 100 * ONE_SUPRA, true, false, @@ -4213,7 +6311,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -4233,90 +6332,232 @@ module supra_framework::pbo_delegation_pool { // validator becomes active and share price is 1 end_aptos_epoch(); - assert_delegation(delegator1_address, pool_address, 5000000000, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + 5000000000, + 0, + 0 + ); // pending_inactive balance would be under threshold => move MIN_COINS_ON_SHARES_POOL coins unlock(delegator1, pool_address, MIN_COINS_ON_SHARES_POOL - 1); - assert_delegation(delegator1_address, pool_address, 4899999999, 0, 100000001); + assert_delegation( + delegator1_address, + pool_address, + 4899999999, + 0, + 100000001 + ); // pending_inactive balance is over threshold reactivate_stake(delegator1, pool_address, 1); - assert_delegation(delegator1_address, pool_address, 4900000000, 0, 100000000); + assert_delegation( + delegator1_address, + pool_address, + 4900000000, + 0, + 100000000 + ); // pending_inactive balance would be under threshold => move entire balance reactivate_stake(delegator1, pool_address, 1); - assert_delegation(delegator1_address, pool_address, 5000000000, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + 5000000000, + 0, + 0 + ); // active balance would be under threshold => move entire balance - unlock(delegator1, pool_address, 5000000000 - (MIN_COINS_ON_SHARES_POOL - 1)); - assert_delegation(delegator1_address, pool_address, 0, 0, 5000000000); + unlock( + delegator1, + pool_address, + 5000000000 - (MIN_COINS_ON_SHARES_POOL - 1) + ); + assert_delegation( + delegator1_address, + pool_address, + 0, + 0, + 5000000000 + ); // active balance would be under threshold => move MIN_COINS_ON_SHARES_POOL coins reactivate_stake(delegator1, pool_address, 1); - assert_delegation(delegator1_address, pool_address, 100000001, 0, 4899999999); + assert_delegation( + delegator1_address, + pool_address, + 100000001, + 0, + 4899999999 + ); // active balance is over threshold unlock(delegator1, pool_address, 1); - assert_delegation(delegator1_address, pool_address, 100000000, 0, 4900000000); + assert_delegation( + delegator1_address, + pool_address, + 100000000, + 0, + 4900000000 + ); // pending_inactive balance would be under threshold => move entire balance - reactivate_stake(delegator1, pool_address, 4000000000 - (MIN_COINS_ON_SHARES_POOL - - 1)); - assert_delegation(delegator1_address, pool_address, 4000000001, 0, 999999999); + reactivate_stake( + delegator1, + pool_address, + 4000000000 - (MIN_COINS_ON_SHARES_POOL - 1) + ); + assert_delegation( + delegator1_address, + pool_address, + 4000000001, + 0, + 999999999 + ); // active + pending_inactive balance < 2 * MIN_COINS_ON_SHARES_POOL // stake can live on only one of the shares pools - assert_delegation(delegator2_address, pool_address, 16 * ONE_SUPRA, 0, 0); + assert_delegation( + delegator2_address, + pool_address, + 16 * ONE_SUPRA, + 0, + 0 + ); unlock(delegator2, pool_address, 1); - assert_delegation(delegator2_address, pool_address, 1499999999, 0, 100000001); + assert_delegation( + delegator2_address, + pool_address, + 1499999999, + 0, + 100000001 + ); reactivate_stake(delegator2, pool_address, 1); - assert_delegation(delegator2_address, pool_address, 1500000000, 0, 100000000); + assert_delegation( + delegator2_address, + pool_address, + 1500000000, + 0, + 100000000 + ); unlock(delegator2, pool_address, ONE_SUPRA); - assert_delegation(delegator2_address, pool_address, 1400000000, 0, 200000000); + assert_delegation( + delegator2_address, + pool_address, + 1400000000, + 0, + 200000000 + ); reactivate_stake(delegator2, pool_address, 2 * ONE_SUPRA); - assert_delegation(delegator2_address, pool_address, 16 * ONE_SUPRA, 0, 0); + assert_delegation( + delegator2_address, + pool_address, + 16 * ONE_SUPRA, + 0, + 0 + ); // share price becomes 1.01 on both pools unlock(delegator1, pool_address, 1); - assert_delegation(delegator1_address, pool_address, 4000000000, 0, 1000000000); + assert_delegation( + delegator1_address, + pool_address, + 4000000000, + 0, + 1000000000 + ); end_aptos_epoch(); - assert_delegation(delegator1_address, pool_address, 4040000000, 0, 1010000000); + assert_delegation( + delegator1_address, + pool_address, + 4040000000, + 0, + 1010000000 + ); // pending_inactive balance is over threshold reactivate_stake(delegator1, pool_address, 10000001); - assert_delegation(delegator1_address, pool_address, 4049999999, 0, 1000000000); + assert_delegation( + delegator1_address, + pool_address, + 4049999999, + 0, + 1000000000 + ); // 1 coin < 1.01 so no shares are redeemed reactivate_stake(delegator1, pool_address, 1); - assert_delegation(delegator1_address, pool_address, 4049999999, 0, 1000000000); + assert_delegation( + delegator1_address, + pool_address, + 4049999999, + 0, + 1000000000 + ); // pending_inactive balance is over threshold // requesting 2 coins actually redeems 1 coin from pending_inactive pool reactivate_stake(delegator1, pool_address, 2); - assert_delegation(delegator1_address, pool_address, 4050000000, 0, 999999999); + assert_delegation( + delegator1_address, + pool_address, + 4050000000, + 0, + 999999999 + ); // 1 coin < 1.01 so no shares are redeemed reactivate_stake(delegator1, pool_address, 1); - assert_delegation(delegator1_address, pool_address, 4050000000, 0, 999999999); + assert_delegation( + delegator1_address, + pool_address, + 4050000000, + 0, + 999999999 + ); // pending_inactive balance would be under threshold => move entire balance reactivate_stake(delegator1, pool_address, 2); - assert_delegation(delegator1_address, pool_address, 4050000001, 0, 999999998); + assert_delegation( + delegator1_address, + pool_address, + 4050000001, + 0, + 999999998 + ); // pending_inactive balance would be under threshold => move MIN_COINS_ON_SHARES_POOL coins unlock(delegator1, pool_address, MIN_COINS_ON_SHARES_POOL - 1); - assert_delegation(delegator1_address, pool_address, 3950000003, 0, 1099999996); + assert_delegation( + delegator1_address, + pool_address, + 3950000003, + 0, + 1099999996 + ); // pending_inactive balance would be under threshold => move entire balance reactivate_stake(delegator1, pool_address, 1); - assert_delegation(delegator1_address, pool_address, 3950000003, 0, 1099999996); + assert_delegation( + delegator1_address, + pool_address, + 3950000003, + 0, + 1099999996 + ); } #[test(staker = @0xe256f4f4e2986cada739e339895cf5585082ff247464cab8ec56eea726bd2263)] public entry fun test_get_expected_stake_pool_address(staker: address) { let pool_address = get_expected_stake_pool_address(staker, vector[0x42, 0x42]); - assert!(pool_address == @ - 0xcb5678be9ec64067c2c3f9f8de78e19509411b053d723d2788ebf1f7ba02f04b, 0); + assert!( + pool_address + == @0xcb5678be9ec64067c2c3f9f8de78e19509411b053d723d2788ebf1f7ba02f04b, + 0 + ); } #[test_only] @@ -4325,14 +6566,15 @@ module supra_framework::pbo_delegation_pool { pool_address: address, active_stake: u64, inactive_stake: u64, - pending_inactive_stake: u64, + pending_inactive_stake: u64 ) acquires DelegationPool, BeneficiaryForOperator { - let (actual_active, actual_inactive, actual_pending_inactive) = get_stake( - pool_address, delegator_address - ); + let (actual_active, actual_inactive, actual_pending_inactive) = + get_stake(pool_address, delegator_address); assert!(actual_active == active_stake, actual_active); assert!(actual_inactive == inactive_stake, actual_inactive); - assert!(actual_pending_inactive == pending_inactive_stake, actual_pending_inactive); + assert!( + actual_pending_inactive == pending_inactive_stake, actual_pending_inactive + ); } #[test_only] @@ -4342,28 +6584,33 @@ module supra_framework::pbo_delegation_pool { exists: bool, olc: u64, inactive: bool, - stake: u64, + stake: u64 ) acquires DelegationPool { assert_delegation_pool_exists(pool_address); let pool = borrow_global(pool_address); - let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists(pool, - delegator_address); + let (withdrawal_exists, withdrawal_olc) = + pending_withdrawal_exists(pool, delegator_address); assert!(withdrawal_exists == exists, 0); assert!(withdrawal_olc.index == olc, withdrawal_olc.index); - let (withdrawal_inactive, withdrawal_stake) = get_pending_withdrawal(pool_address, - delegator_address); + let (withdrawal_inactive, withdrawal_stake) = + get_pending_withdrawal(pool_address, delegator_address); assert!(withdrawal_inactive == inactive, 0); assert!(withdrawal_stake == stake, withdrawal_stake); } #[test_only] - public fun assert_inactive_shares_pool(pool_address: address, olc: u64, exists: bool, stake: u64,) acquires DelegationPool { + public fun assert_inactive_shares_pool( + pool_address: address, + olc: u64, + exists: bool, + stake: u64 + ) acquires DelegationPool { assert_delegation_pool_exists(pool_address); let pool = borrow_global(pool_address); assert!(table::contains(&pool.inactive_shares, olc_with_index(olc)) == exists, 0); if (exists) { - let actual_stake = total_coins(table::borrow(&pool.inactive_shares, - olc_with_index(olc))); + let actual_stake = + total_coins(table::borrow(&pool.inactive_shares, olc_with_index(olc))); assert!(actual_stake == stake, actual_stake); } else { assert!(0 == stake, 0); @@ -4378,14 +6625,15 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] #[expected_failure(abort_code = 65561, location = Self)] public entry fun test_withdraw_before_principle_lockup_time_fail( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, validator: &signer, delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010]; let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 1000000; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1000 * ONE_SUPRA, true, true, @@ -4397,7 +6645,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -4409,14 +6658,15 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] public entry fun test_withdraw_after_principle_lockup_time( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, validator: &signer, delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010]; let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 1000000; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1000 * ONE_SUPRA, true, true, @@ -4428,7 +6678,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -4437,19 +6688,27 @@ module supra_framework::pbo_delegation_pool { unlock(delegator, pool_address, 100 * ONE_SUPRA); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator1 = @0x010, + delegator2 = @0x020 + ) + ] public entry fun test_unlock_mutiple_delegators( supra_framework: &signer, validator: &signer, delegator1: &signer, - delegator2: &signer, + delegator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010, @0x020]; let principle_stake = vector[100 * ONE_SUPRA, 200 * ONE_SUPRA]; let coin = stake::mint_coins(300 * ONE_SUPRA); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4461,7 +6720,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); unlock(delegator1, pool_address, 11 * ONE_SUPRA); @@ -4470,7 +6730,7 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010)] public entry fun test_unlock_mutiple_times( - supra_framework: &signer, validator: &signer, delegator1: &signer, + supra_framework: &signer, validator: &signer, delegator1: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010, @0x020]; @@ -4479,7 +6739,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 1000000; let delegator1_address = signer::address_of(delegator1); supra_account::create_account(delegator1_address); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4491,7 +6752,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); stake::mint(delegator1, 1000 * ONE_SUPRA); @@ -4501,13 +6763,20 @@ module supra_framework::pbo_delegation_pool { unlock(delegator1, pool_address, 600 * ONE_SUPRA); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator1 = @0x010, + delegator2 = @0x020 + ) + ] #[expected_failure(abort_code = 65561, location = Self)] public entry fun test_multiple_users( supra_framework: &signer, validator: &signer, delegator1: &signer, - delegator2: &signer, + delegator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010]; @@ -4518,7 +6787,8 @@ module supra_framework::pbo_delegation_pool { let delegator2_address = signer::address_of(delegator2); supra_account::create_account(delegator1_address); supra_account::create_account(delegator2_address); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4530,7 +6800,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); stake::mint(delegator1, 1000 * ONE_SUPRA); @@ -4538,22 +6809,54 @@ module supra_framework::pbo_delegation_pool { stake::mint(delegator2, 1000 * ONE_SUPRA); add_stake(delegator2, pool_address, 1000 * ONE_SUPRA); end_aptos_epoch(); - assert_delegation(delegator2_address, pool_address, 1000 * ONE_SUPRA, 0, 0); - assert_delegation(delegator1_address, pool_address, 200999999999, 0, 0); + assert_delegation( + delegator2_address, + pool_address, + 1000 * ONE_SUPRA, + 0, + 0 + ); + assert_delegation( + delegator1_address, + pool_address, + 200999999999, + 0, + 0 + ); unlock(delegator2, pool_address, 1000 * ONE_SUPRA); - assert_delegation(delegator2_address, pool_address, 0, 0, 1000 * ONE_SUPRA); - unlock(delegator1, pool_address, 1000 * ONE_SUPRA); - assert_delegation(delegator1_address, pool_address, 101000000001, 0, 99999999999); + assert_delegation( + delegator2_address, + pool_address, + 0, + 0, + 1000 * ONE_SUPRA + ); + unlock(delegator1, pool_address, 1000 * ONE_SUPRA); + assert_delegation( + delegator1_address, + pool_address, + 101000000001, + 0, + 99999999999 + ); unlock(delegator1, pool_address, 1000 * ONE_SUPRA); } #[test_only] - fun generate_multisig_account(owner: &signer, addition_owner: vector
, threshold: u64) - : address { + fun generate_multisig_account( + owner: &signer, addition_owner: vector
, threshold: u64 + ): address { let owner_addr = aptos_std::signer::address_of(owner); - let multisig_addr = multisig_account::get_next_multisig_account_address(owner_addr); - multisig_account::create_with_owners(owner, addition_owner, threshold, vector[], - vector[], 300); + let multisig_addr = + multisig_account::get_next_multisig_account_address(owner_addr); + multisig_account::create_with_owners( + owner, + addition_owner, + threshold, + vector[], + vector[], + 300 + ); multisig_addr } @@ -4571,7 +6874,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 0; let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4583,11 +6887,16 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); - replace_delegator(&account::create_signer_for_test(multisig), pool_address, @0x010, @ - 0x0101); + replace_delegator( + &account::create_signer_for_test(multisig), + pool_address, + @0x010, + @0x0101 + ); } #[test(supra_framework = @supra_framework, validator = @0x123)] @@ -4603,7 +6912,8 @@ module supra_framework::pbo_delegation_pool { let coin = stake::mint_coins(300 * ONE_SUPRA); let principle_lockup_time = 0; let multisig = generate_multisig_account(validator, vector[], 1); - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, option::some(multisig), 0, vector::empty(), @@ -4613,7 +6923,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); } #[test(supra_framework = @supra_framework, validator = @0x123)] @@ -4630,7 +6941,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 0; let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4642,29 +6954,45 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); - let new_multisig = generate_multisig_account(supra_framework, vector[@0x12234], 2); + let new_multisig = generate_multisig_account( + supra_framework, vector[@0x12234], 2 + ); let multisig_signer = account::create_signer_for_test(new_multisig); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); - replace_delegator(&multisig_signer, pool_address, @0x010, @0x0101); + replace_delegator( + &multisig_signer, + pool_address, + @0x010, + @0x0101 + ); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator1 = @0x010, + delegator2 = @0x020 + ) + ] public entry fun test_lose_shares_small( supra_framework: &signer, validator: &signer, delegator1: &signer, - delegator2: &signer, + delegator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010, @0x020]; let principle_stake = vector[ONE_SUPRA, 1000 * ONE_SUPRA]; let coin = stake::mint_coins(1001 * ONE_SUPRA); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 100 * ONE_SUPRA, true, true, @@ -4676,19 +7004,22 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); stake::mint(validator, 150 * ONE_SUPRA); add_stake(validator, pool_address, 150 * ONE_SUPRA); let one_year_in_secs = 31536000; let reward_period_start_time_in_sec = timestamp::now_seconds(); - staking_config::initialize_rewards(supra_framework, + staking_config::initialize_rewards( + supra_framework, fixed_point64::create_from_rational(1, 100), fixed_point64::create_from_rational(1, 100), one_year_in_secs, reward_period_start_time_in_sec, - fixed_point64::create_from_rational(0, 100),); + fixed_point64::create_from_rational(0, 100) + ); let index = 0; while (index < 1828) { end_aptos_epoch(); @@ -4696,33 +7027,82 @@ module supra_framework::pbo_delegation_pool { }; let delegator1_address = signer::address_of(delegator1); let delegator2_address = signer::address_of(delegator2); - assert_delegation(delegator1_address, pool_address, 7933617798152065, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + 7933617798152065, + 0, + 0 + ); stake::assert_stake_pool(pool_address, 9913173264836398460, 0, 0, 0); unlock(delegator1, pool_address, 1 * ONE_SUPRA); - assert_delegation(delegator1_address, pool_address, 7933617698152064, 0, 100000000); - stake::assert_stake_pool(pool_address, 9913173264736398460, 0, 0, 100000000); + assert_delegation( + delegator1_address, + pool_address, + 7933617698152064, + 0, + 100000000 + ); + stake::assert_stake_pool( + pool_address, + 9913173264736398460, + 0, + 0, + 100000000 + ); unlock(delegator1, pool_address, 1 * ONE_SUPRA); - stake::assert_stake_pool(pool_address, 9913173264636398461, 0, 0, 199999999); - assert_delegation(delegator1_address, pool_address, 7933617598152064, 0, 199999999); - assert_delegation(delegator2_address, pool_address, 7933617798152065133, 0, 0); + stake::assert_stake_pool( + pool_address, + 9913173264636398461, + 0, + 0, + 199999999 + ); + assert_delegation( + delegator1_address, + pool_address, + 7933617598152064, + 0, + 199999999 + ); + assert_delegation( + delegator2_address, + pool_address, + 7933617798152065133, + 0, + 0 + ); unlock(delegator2, pool_address, 1000 * ONE_SUPRA); - assert_delegation(delegator2_address, pool_address, 7933617698152065134, 0, - 99999999999); + assert_delegation( + delegator2_address, + pool_address, + 7933617698152065134, + 0, + 99999999999 + ); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator1 = @0x010, + delegator2 = @0x020 + ) + ] public entry fun test_lose_shares_large( supra_framework: &signer, validator: &signer, delegator1: &signer, - delegator2: &signer, + delegator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010, @0x020]; let principle_stake = vector[ONE_SUPRA, 90000000000 * ONE_SUPRA]; let coin = stake::mint_coins(90000000001 * ONE_SUPRA); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 100 * ONE_SUPRA, true, true, @@ -4734,19 +7114,22 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); stake::mint(validator, 150 * ONE_SUPRA); add_stake(validator, pool_address, 150 * ONE_SUPRA); let one_year_in_secs = 31536000; let reward_period_start_time_in_sec = timestamp::now_seconds(); - staking_config::initialize_rewards(supra_framework, + staking_config::initialize_rewards( + supra_framework, fixed_point64::create_from_rational(1, 100), fixed_point64::create_from_rational(1, 100), one_year_in_secs, reward_period_start_time_in_sec, - fixed_point64::create_from_rational(0, 100),); + fixed_point64::create_from_rational(0, 100) + ); let index = 0; while (index < 10) { end_aptos_epoch(); @@ -4754,17 +7137,58 @@ module supra_framework::pbo_delegation_pool { }; let delegator1_address = signer::address_of(delegator1); let delegator2_address = signer::address_of(delegator2); - assert_delegation(delegator1_address, pool_address, 110462212, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + 110462212, + 0, + 0 + ); stake::assert_stake_pool(pool_address, 9941599156262803145, 0, 0, 0); unlock(delegator1, pool_address, 1 * ONE_SUPRA); - assert_delegation(delegator1_address, pool_address, 0, 0, 110462212); - stake::assert_stake_pool(pool_address, 9941599156152340933, 0, 0, 110462212); - stake::assert_stake_pool(pool_address, 9941599156152340933, 0, 0, 110462212); - assert_delegation(delegator1_address, pool_address, 0, 0, 110462212); - assert_delegation(delegator2_address, pool_address, 9941599128700840588, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + 0, + 0, + 110462212 + ); + stake::assert_stake_pool( + pool_address, + 9941599156152340933, + 0, + 0, + 110462212 + ); + stake::assert_stake_pool( + pool_address, + 9941599156152340933, + 0, + 0, + 110462212 + ); + assert_delegation( + delegator1_address, + pool_address, + 0, + 0, + 110462212 + ); + assert_delegation( + delegator2_address, + pool_address, + 9941599128700840588, + 0, + 0 + ); unlock(delegator2, pool_address, 1 * ONE_SUPRA); - assert_delegation(delegator2_address, pool_address, 9941599128600840588, 0, - 100000000); + assert_delegation( + delegator2_address, + pool_address, + 9941599128600840588, + 0, + 100000000 + ); } #[test(supra_framework = @supra_framework, validator = @0x123)] @@ -4781,7 +7205,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 0; let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4793,22 +7218,40 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let multisig_signer = account::create_signer_for_test(multisig); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); let new_delegator = @0x0101; - assert_delegation(old_delegator, pool_address, 100 * ONE_SUPRA, 0, 0); + assert_delegation( + old_delegator, + pool_address, + 100 * ONE_SUPRA, + 0, + 0 + ); - replace_delegator(&multisig_signer, pool_address, @0x010, new_delegator); - assert_delegation(new_delegator, pool_address, 100 * ONE_SUPRA, 0, 0); + replace_delegator( + &multisig_signer, + pool_address, + @0x010, + new_delegator + ); + assert_delegation( + new_delegator, + pool_address, + 100 * ONE_SUPRA, + 0, + 0 + ); } #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] /// if old_delegator has already unlocked 100, the new_delegator should be able to withdraw 100 coins public entry fun test_replace_delegation_before_withdraw_and_after_withdraw_success( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, validator: &signer, delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); account::create_account_for_test(signer::address_of(validator)); @@ -4819,7 +7262,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 0; let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4831,43 +7275,790 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); unlock(delegator, pool_address, 100 * ONE_SUPRA); - assert_delegation(delegator_address, pool_address, 200 * ONE_SUPRA, 0, 100 * ONE_SUPRA); + assert_delegation( + delegator_address, + pool_address, + 200 * ONE_SUPRA, + 0, + 100 * ONE_SUPRA + ); let multisig_signer = account::create_signer_for_test(multisig); let new_delegator_address = @0x0101; - replace_delegator(&multisig_signer, pool_address, delegator_address, - new_delegator_address); + replace_delegator( + &multisig_signer, + pool_address, + delegator_address, + new_delegator_address + ); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - withdraw(&account::create_signer_for_test(new_delegator_address), pool_address, - 100 * ONE_SUPRA); - assert!(coin::balance(new_delegator_address) == (100 * ONE_SUPRA) - 1, 0); + withdraw( + &account::create_signer_for_test(new_delegator_address), + pool_address, + 100 * ONE_SUPRA + ); + assert!( + coin::balance(new_delegator_address) == (100 * ONE_SUPRA) - 1, + 0 + ); } #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] #[expected_failure(abort_code = 65545, location = Self)] /// after replace_delegator` succeeds, old_delegator must not be able to perform unlock or withdraw or vote (if partial_voting is enable) public entry fun test_replace_delegation_after_withdraw_using_old_address_failure( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, validator: &signer, delegator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + initialize_for_test(supra_framework); + account::create_account_for_test(signer::address_of(validator)); + let delegator_address = signer::address_of(delegator); + let delegator_address_vec = vector[delegator_address, @0x020]; + let principle_stake = vector[300 * ONE_SUPRA, 200 * ONE_SUPRA]; + let coin = stake::mint_coins(500 * ONE_SUPRA); + let principle_lockup_time = 0; + let multisig = generate_multisig_account(validator, vector[@0x12134], 2); + + initialize_test_validator( + validator, + 0, + true, + true, + 0, + delegator_address_vec, + principle_stake, + coin, + option::some(multisig), + vector[2, 2, 3], + 10, + principle_lockup_time, + 12 + ); + + let validator_address = signer::address_of(validator); + let pool_address = get_owned_pool_address(validator_address); + + let multisig_signer = account::create_signer_for_test(multisig); + let new_delegator_address = @0x0101; + replace_delegator( + &multisig_signer, + pool_address, + delegator_address, + new_delegator_address + ); + + unlock(delegator, pool_address, 100 * ONE_SUPRA); + + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + + withdraw(delegator, pool_address, 100 * ONE_SUPRA); + } + + #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] + /// after replace_delegator succeeds, new_delegator should be able to perform unlock and withdraw on the funds as per unlocking schedule + public entry fun test_replace_delegation_unlock_and_withdraw_success( + supra_framework: &signer, validator: &signer, delegator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + initialize_for_test(supra_framework); + account::create_account_for_test(signer::address_of(validator)); + let delegator_address = signer::address_of(delegator); + let delegator_address_vec = vector[delegator_address, @0x020]; + let principle_stake = vector[300 * ONE_SUPRA, 200 * ONE_SUPRA]; + let coin = stake::mint_coins(500 * ONE_SUPRA); + let principle_lockup_time = 0; + let multisig = generate_multisig_account(validator, vector[@0x12134], 2); + + initialize_test_validator( + validator, + 0, + true, + true, + 0, + delegator_address_vec, + principle_stake, + coin, + option::some(multisig), + vector[2, 2, 3], + 10, + principle_lockup_time, + 12 + ); + + let validator_address = signer::address_of(validator); + let pool_address = get_owned_pool_address(validator_address); + let multisig_signer = account::create_signer_for_test(multisig); + let new_delegator_address = @0x0101; + let new_delegator_address_signer = + &account::create_signer_for_test(new_delegator_address); + replace_delegator( + &multisig_signer, + pool_address, + delegator_address, + new_delegator_address + ); + + unlock(new_delegator_address_signer, pool_address, 100 * ONE_SUPRA); + assert_delegation( + new_delegator_address, + pool_address, + 200 * ONE_SUPRA, + 0, + 100 * ONE_SUPRA + ); + + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + + withdraw(new_delegator_address_signer, pool_address, 100 * ONE_SUPRA); + assert!( + coin::balance(new_delegator_address) == (100 * ONE_SUPRA) - 1, + 0 + ); + } + + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator = @0x010, + funder = @0x999 + ) + ] + /// if delegator is not part of one of the principle stake holder, and not funded with locked stake, + /// they can unlock/withdraw without restriction + public entry fun test_unlock_withdraw_multiple_funded_delegator_not_part_of_principle_stake_success( + supra_framework: &signer, + validator: &signer, + delegator: &signer, + funder: address + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + initialize_for_test(supra_framework); + account::create_account_for_test(signer::address_of(validator)); + let delegator_address = signer::address_of(delegator); + let delegator_address_vec = vector[delegator_address, @0x020]; + let principle_stake = vector[300 * ONE_SUPRA, 200 * ONE_SUPRA]; + let coin = stake::mint_coins(500 * ONE_SUPRA); + let principle_lockup_time = 0; + let multisig = generate_multisig_account(validator, vector[@0x12134], 2); + + initialize_test_validator( + validator, + 0, + true, + true, + 0, + delegator_address_vec, + principle_stake, + coin, + option::some(multisig), + vector[2, 2, 3], + 10, + principle_lockup_time, + 12 + ); + + let validator_address = signer::address_of(validator); + let pool_address = get_owned_pool_address(validator_address); + + let new_delegator_address = @0x0215; + let new_delegator_address_signer = + account::create_account_for_test(new_delegator_address); + let new_delegator_address2 = @0x0216; + let new_delegator_address_signer2 = + account::create_account_for_test(new_delegator_address2); + let funder_signer = account::create_account_for_test(funder); + stake::mint(&funder_signer, 100 * ONE_SUPRA); + assert!( + coin::balance(funder) == (100 * ONE_SUPRA), + 0 + ); + + fund_delegators_with_stake( + &funder_signer, + pool_address, + vector[new_delegator_address, new_delegator_address2], + vector[30 * ONE_SUPRA, 70 * ONE_SUPRA] + ); + assert!(coin::balance(funder) == 0, 0); + + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + + unlock(&new_delegator_address_signer, pool_address, (30 * ONE_SUPRA)); + unlock(&new_delegator_address_signer2, pool_address, (70 * ONE_SUPRA)); + + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + withdraw(&new_delegator_address_signer, pool_address, (30 * ONE_SUPRA)); + let new_delegator_balance = coin::balance(new_delegator_address); + assert!( + new_delegator_balance == (30 * ONE_SUPRA) - 1, + new_delegator_balance + ); + withdraw(&new_delegator_address_signer2, pool_address, (70 * ONE_SUPRA)); + let new_delegator_balance2 = coin::balance(new_delegator_address2); + assert!( + new_delegator_balance2 == (70 * ONE_SUPRA) - 1, + new_delegator_balance2 + ); + } + + #[test( + supra_framework = @supra_framework, validator = @0x123, delegator = @0x010 + )] + #[expected_failure(abort_code = 327716, location = Self)] + /// Test that if a if some random person tries to add delegator locked stake, it does not get added to + /// `principle_stake` table and therefore remains outside the purview of replacement + public entry fun test_unlock_delegator_not_part_of_principle_stake_cannot_be_locked_by_strangers_failure( + supra_framework: &signer, validator: &signer, delegator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + initialize_for_test(supra_framework); + account::create_account_for_test(signer::address_of(validator)); + let delegator_address = signer::address_of(delegator); + let delegator_address_vec = vector[delegator_address, @0x020]; + let principle_stake = vector[300 * ONE_SUPRA, 200 * ONE_SUPRA]; + let coin = stake::mint_coins(500 * ONE_SUPRA); + let principle_lockup_time = 7776000; + let multisig = generate_multisig_account(validator, vector[@0x12134], 2); + + initialize_test_validator( + validator, + 0, + true, + true, + 0, + delegator_address_vec, + principle_stake, + coin, + option::some(multisig), + vector[2, 2, 3], + 10, + principle_lockup_time, + LOCKUP_CYCLE_SECONDS + ); + + let validator_address = signer::address_of(validator); + let pool_address = get_owned_pool_address(validator_address); + + let new_delegator_address = @0x0215; + let new_delegator_address_signer = + account::create_account_for_test(new_delegator_address); + let funder_signer = account::create_signer_for_test(multisig); + let funder = signer::address_of(&funder_signer); + stake::mint(&funder_signer, 100 * ONE_SUPRA); + stake::mint(&new_delegator_address_signer, 100 * ONE_SUPRA); + assert!( + coin::balance(funder) == (100 * ONE_SUPRA), + 0 + ); + + assert!( + coin::balance(new_delegator_address) == (100 * ONE_SUPRA), + 0 + ); + + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + add_stake(&new_delegator_address_signer, pool_address, 100 * ONE_SUPRA); + fund_delegators_with_locked_stake( + validator, + pool_address, + vector[new_delegator_address], + vector[1 * ONE_SUPRA] + ); + } + + #[test( + supra_framework = @supra_framework, validator = @0x123, delegator = @0x010 + )] + /// Test that if a multisig admin adds a delegator with zero stake, it does not get added to + /// `principle_stake` table and therefore remains outside the purview of replacement + public entry fun test_unlock_zero_funded_delegator_not_part_of_principle_stake_success( + supra_framework: &signer, validator: &signer, delegator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + initialize_for_test(supra_framework); + account::create_account_for_test(signer::address_of(validator)); + let delegator_address = signer::address_of(delegator); + let delegator_address_vec = vector[delegator_address, @0x020]; + let principle_stake = vector[300 * ONE_SUPRA, 200 * ONE_SUPRA]; + let coin = stake::mint_coins(500 * ONE_SUPRA); + let principle_lockup_time = 7776000; + let multisig = generate_multisig_account(validator, vector[@0x12134], 2); + + initialize_test_validator( + validator, + 0, + true, + true, + 0, + delegator_address_vec, + principle_stake, + coin, + option::some(multisig), + vector[2, 2, 3], + 10, + principle_lockup_time, + LOCKUP_CYCLE_SECONDS + ); + + let validator_address = signer::address_of(validator); + let pool_address = get_owned_pool_address(validator_address); + + let new_delegator_address = @0x0215; + let new_delegator_address_signer = + account::create_account_for_test(new_delegator_address); + let funder_signer = account::create_signer_for_test(multisig); + let funder = signer::address_of(&funder_signer); + stake::mint(&funder_signer, 100 * ONE_SUPRA); + stake::mint(&new_delegator_address_signer, 100 * ONE_SUPRA); + assert!( + coin::balance(funder) == (100 * ONE_SUPRA), + 0 + ); + + assert!( + coin::balance(new_delegator_address) == (100 * ONE_SUPRA), + 0 + ); + + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + add_stake(&new_delegator_address_signer, pool_address, 100 * ONE_SUPRA); + fund_delegators_with_locked_stake( + &funder_signer, + pool_address, + vector[new_delegator_address], + vector[0] + ); + { + // if the locked stake is zero, assert that it does not get added to `principle_stake` table + let pool = borrow_global(pool_address); + assert!(!table::contains(&pool.principle_stake, new_delegator_address), 999); + }; + + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + + unlock(&new_delegator_address_signer, pool_address, (100 * ONE_SUPRA)); + + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + withdraw(&new_delegator_address_signer, pool_address, (100 * ONE_SUPRA)); + let new_delegator_balance = coin::balance(new_delegator_address); + assert!( + new_delegator_balance == (100 * ONE_SUPRA) - 1, + new_delegator_balance + ); + } + + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator = @0x010, + funder = @0x999 + ) + ] + /// if a single delegator was not part of one of the principle stake holder, and not funded with locked stake, + /// they can unlock/withdraw without restriction + public entry fun test_unlock_withdraw_funded_delegator_not_part_of_principle_stake_success( + supra_framework: &signer, + validator: &signer, + delegator: &signer, + funder: address + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + initialize_for_test(supra_framework); + account::create_account_for_test(signer::address_of(validator)); + let delegator_address = signer::address_of(delegator); + let delegator_address_vec = vector[delegator_address, @0x020]; + let principle_stake = vector[300 * ONE_SUPRA, 200 * ONE_SUPRA]; + let coin = stake::mint_coins(500 * ONE_SUPRA); + let principle_lockup_time = 0; + let multisig = generate_multisig_account(validator, vector[@0x12134], 2); + + initialize_test_validator( + validator, + 0, + true, + true, + 0, + delegator_address_vec, + principle_stake, + coin, + option::some(multisig), + vector[2, 2, 3], + 10, + principle_lockup_time, + 12 + ); + + let validator_address = signer::address_of(validator); + let pool_address = get_owned_pool_address(validator_address); + + let new_delegator_address = @0x0215; + let new_delegator_address_signer = + account::create_account_for_test(new_delegator_address); + let funder_signer = account::create_account_for_test(funder); + stake::mint(&funder_signer, 100 * ONE_SUPRA); + assert!( + coin::balance(funder) == (100 * ONE_SUPRA), + 0 + ); + + fund_delegator_stake( + &funder_signer, + pool_address, + new_delegator_address, + 100 * ONE_SUPRA + ); + assert!(coin::balance(funder) == 0, 0); + + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + + unlock(&new_delegator_address_signer, pool_address, (100 * ONE_SUPRA)); + + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + withdraw(&new_delegator_address_signer, pool_address, (100 * ONE_SUPRA)); + let new_delegator_balance = coin::balance(new_delegator_address); + assert!( + new_delegator_balance == (100 * ONE_SUPRA) - 1, + new_delegator_balance + ); + } + + #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] + /// if delegator is not part of one of the principle stake holder, they can unlock/withdraw without restriction + public entry fun test_unlock_withdraw_delegator_not_part_of_principle_stake_success( + supra_framework: &signer, validator: &signer, delegator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + initialize_for_test(supra_framework); + account::create_account_for_test(signer::address_of(validator)); + let delegator_address = signer::address_of(delegator); + let delegator_address_vec = vector[delegator_address, @0x020]; + let principle_stake = vector[300 * ONE_SUPRA, 200 * ONE_SUPRA]; + let coin = stake::mint_coins(500 * ONE_SUPRA); + let principle_lockup_time = 0; + let multisig = generate_multisig_account(validator, vector[@0x12134], 2); + + initialize_test_validator( + validator, + 0, + true, + true, + 0, + delegator_address_vec, + principle_stake, + coin, + option::some(multisig), + vector[2, 2, 3], + 10, + principle_lockup_time, + 12 + ); + + let validator_address = signer::address_of(validator); + let pool_address = get_owned_pool_address(validator_address); + + let new_delegator_address = @0x0215; + let new_delegator_address_signer = + account::create_account_for_test(new_delegator_address); + + stake::mint(&new_delegator_address_signer, 100 * ONE_SUPRA); + assert!( + coin::balance(new_delegator_address) == (100 * ONE_SUPRA), + 0 + ); + + add_stake(&new_delegator_address_signer, pool_address, 100 * ONE_SUPRA); + assert!(coin::balance(new_delegator_address) == 0, 0); + + unlock(&new_delegator_address_signer, pool_address, (100 * ONE_SUPRA)); + + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + + withdraw(&new_delegator_address_signer, pool_address, (100 * ONE_SUPRA)); + assert!( + coin::balance(new_delegator_address) == (100 * ONE_SUPRA) - 1, + 0 + ); + } + + #[test( + supra_framework = @supra_framework, validator = @0x123, delegator = @0x010 + )] + #[expected_failure(abort_code = 65561, location = Self)] + /// say unlocking schedule is 3 month cliff, monthly unlocking of 10% and principle stake is 100 coins then + /// between 3 and 4 months, check that it's can't unlock there principal stake + public entry fun test_unlocking_before_cliff_period_funded_delegators_failure( + supra_framework: &signer, validator: &signer, delegator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + initialize_for_test(supra_framework); + account::create_account_for_test(signer::address_of(validator)); + let delegator_address = signer::address_of(delegator); + let delegator_address_vec = vector[delegator_address, @0x020]; + let principle_stake = vector[100 * ONE_SUPRA, 200 * ONE_SUPRA]; + let coin = stake::mint_coins(300 * ONE_SUPRA); + let principle_lockup_time = 7776000; // 3 month cliff + let multisig = generate_multisig_account(validator, vector[@0x12134], 2); + + initialize_test_validator( + validator, + 0, + true, + true, + 0, + delegator_address_vec, + principle_stake, + coin, + option::some(multisig), + vector[1], + 10, + principle_lockup_time, + LOCKUP_CYCLE_SECONDS // monthly unlocking + ); + let funder_signer = account::create_signer_for_test(multisig); + let funder = signer::address_of(&funder_signer); + let validator_address = signer::address_of(validator); + let pool_address = get_owned_pool_address(validator_address); + let one_year_in_secs = 31536000; + let reward_period_start_time_in_sec = timestamp::now_seconds(); + staking_config::initialize_rewards( + supra_framework, + fixed_point64::create_from_rational(1, 100), + fixed_point64::create_from_rational(1, 100), + one_year_in_secs, + reward_period_start_time_in_sec, + fixed_point64::create_from_rational(0, 100) + ); + + let new_delegator_address = @0x0215; + let new_delegator_signer = account::create_signer_for_test(new_delegator_address); + let new_delegator_address2 = @0x0216; + + stake::mint(&funder_signer, 100 * ONE_SUPRA); + assert!( + coin::balance(funder) == (100 * ONE_SUPRA), + 0 + ); + + fund_delegators_with_locked_stake( + &funder_signer, + pool_address, + vector[new_delegator_address, new_delegator_address2], + vector[30 * ONE_SUPRA, 70 * ONE_SUPRA] + ); + assert!(coin::balance(funder) == 0, 0); + + // 3 month + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + + unlock(&new_delegator_signer, pool_address, (1 * ONE_SUPRA)); + } + + #[test( + supra_framework = @supra_framework, validator = @0x123, delegator = @0x010 + )] + public entry fun test_unlocking_mixed_principle_stake_before_cliff_period_funded_delegators_success( + supra_framework: &signer, validator: &signer, delegator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + initialize_for_test(supra_framework); + account::create_account_for_test(signer::address_of(validator)); + let delegator_address = signer::address_of(delegator); + let delegator_address_vec = vector[delegator_address, @0x020]; + let principle_stake = vector[100 * ONE_SUPRA, 200 * ONE_SUPRA]; + let coin = stake::mint_coins(300 * ONE_SUPRA); + let principle_lockup_time = 7776000; // 3 month cliff + let multisig = generate_multisig_account(validator, vector[@0x12134], 2); + + initialize_test_validator( + validator, + 0, + true, + true, + 0, + delegator_address_vec, + principle_stake, + coin, + option::some(multisig), + vector[1], + 10, + principle_lockup_time, + LOCKUP_CYCLE_SECONDS // monthly unlocking + ); + let funder_signer = account::create_signer_for_test(multisig); + let funder = signer::address_of(&funder_signer); + let validator_address = signer::address_of(validator); + let pool_address = get_owned_pool_address(validator_address); + let one_year_in_secs = 31536000; + let reward_period_start_time_in_sec = timestamp::now_seconds(); + staking_config::initialize_rewards( + supra_framework, + fixed_point64::create_from_rational(1, 100), + fixed_point64::create_from_rational(1, 100), + one_year_in_secs, + reward_period_start_time_in_sec, + fixed_point64::create_from_rational(0, 100) + ); + + let new_delegator_address = @0x0215; + let new_delegator_address2 = @0x0216; + + stake::mint(&funder_signer, 200 * ONE_SUPRA); + assert!( + coin::balance(funder) == (200 * ONE_SUPRA), + 0 + ); + + fund_delegators_with_stake( + &funder_signer, + pool_address, + vector[new_delegator_address, new_delegator_address2], + vector[30 * ONE_SUPRA, 70 * ONE_SUPRA] + ); + + fund_delegators_with_locked_stake( + &funder_signer, + pool_address, + vector[new_delegator_address, new_delegator_address2], + vector[30 * ONE_SUPRA, 70 * ONE_SUPRA] + ); + assert!(coin::balance(funder) == 0, 0); + + // 3 month + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + + let new_delegator_address_signer = + account::create_signer_for_test(new_delegator_address); + unlock(&new_delegator_address_signer, pool_address, 30 * ONE_SUPRA); + unlock(&new_delegator_address_signer, pool_address, 1 * ONE_SUPRA); + } + + #[test( + supra_framework = @supra_framework, validator = @0x123, delegator = @0x010 + )] + #[expected_failure(abort_code = 65561, location = Self)] + public entry fun test_unlocking_mixed_principle_stake_before_cliff_period_funded_delegators_failure( + supra_framework: &signer, validator: &signer, delegator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + initialize_for_test(supra_framework); + account::create_account_for_test(signer::address_of(validator)); + let delegator_address = signer::address_of(delegator); + let delegator_address_vec = vector[delegator_address, @0x020]; + let principle_stake = vector[100 * ONE_SUPRA, 200 * ONE_SUPRA]; + let coin = stake::mint_coins(300 * ONE_SUPRA); + let principle_lockup_time = 7776000; // 3 month cliff + let multisig = generate_multisig_account(validator, vector[@0x12134], 2); + + initialize_test_validator( + validator, + 0, + true, + true, + 0, + delegator_address_vec, + principle_stake, + coin, + option::some(multisig), + vector[1], + 10, + principle_lockup_time, + LOCKUP_CYCLE_SECONDS // monthly unlocking + ); + let funder_signer = account::create_signer_for_test(multisig); + let funder = signer::address_of(&funder_signer); + let validator_address = signer::address_of(validator); + let pool_address = get_owned_pool_address(validator_address); + let one_year_in_secs = 31536000; + let reward_period_start_time_in_sec = timestamp::now_seconds(); + staking_config::initialize_rewards( + supra_framework, + fixed_point64::create_from_rational(1, 100), + fixed_point64::create_from_rational(1, 100), + one_year_in_secs, + reward_period_start_time_in_sec, + fixed_point64::create_from_rational(0, 100) + ); + + let new_delegator_address = @0x0215; + let new_delegator_address2 = @0x0216; + + stake::mint(&funder_signer, 200 * ONE_SUPRA); + assert!( + coin::balance(funder) == (200 * ONE_SUPRA), + 0 + ); + + fund_delegators_with_stake( + &funder_signer, + pool_address, + vector[new_delegator_address, new_delegator_address2], + vector[30 * ONE_SUPRA, 70 * ONE_SUPRA] + ); + + fund_delegators_with_locked_stake( + &funder_signer, + pool_address, + vector[new_delegator_address, new_delegator_address2], + vector[30 * ONE_SUPRA, 70 * ONE_SUPRA] + ); + assert!(coin::balance(funder) == 0, 0); + + // 3 month + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + + let new_delegator_address_signer = + account::create_signer_for_test(new_delegator_address); + unlock(&new_delegator_address_signer, pool_address, 30 * ONE_SUPRA); + unlock(&new_delegator_address_signer, pool_address, 2 * ONE_SUPRA); + } + + #[test( + supra_framework = @supra_framework, validator = @0x123, delegator = @0x010 + )] + /// say unlocking schedule is 3 month cliff, monthly unlocking of 10% and principle stake is 100 coins then + /// between 3 and 4 months, check that it's can't unlock there principal stacke + public entry fun test_unlocking_after_cliff_period_initial_and_funded_delegators_success( + supra_framework: &signer, validator: &signer, delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); account::create_account_for_test(signer::address_of(validator)); let delegator_address = signer::address_of(delegator); let delegator_address_vec = vector[delegator_address, @0x020]; - let principle_stake = vector[300 * ONE_SUPRA, 200 * ONE_SUPRA]; - let coin = stake::mint_coins(500 * ONE_SUPRA); - let principle_lockup_time = 0; + let principle_stake = vector[100 * ONE_SUPRA, 200 * ONE_SUPRA]; + let coin = stake::mint_coins(300 * ONE_SUPRA); + let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4876,42 +8067,73 @@ module supra_framework::pbo_delegation_pool { principle_stake, coin, option::some(multisig), - vector[2, 2, 3], + vector[1], 10, principle_lockup_time, - 12); - + LOCKUP_CYCLE_SECONDS // monthly unlocking + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); + let one_year_in_secs = 31536000; + let reward_period_start_time_in_sec = timestamp::now_seconds(); + staking_config::initialize_rewards( + supra_framework, + fixed_point64::create_from_rational(1, 100), + fixed_point64::create_from_rational(1, 100), + one_year_in_secs, + reward_period_start_time_in_sec, + fixed_point64::create_from_rational(0, 100) + ); - let multisig_signer = account::create_signer_for_test(multisig); - let new_delegator_address = @0x0101; - replace_delegator(&multisig_signer, pool_address, delegator_address, - new_delegator_address); - - unlock(delegator, pool_address, 100 * ONE_SUPRA); + let new_delegator_address2 = @0x0216; + let funder_signer = account::create_signer_for_test(multisig); + let funder = signer::address_of(&funder_signer); + stake::mint(&funder_signer, 100 * ONE_SUPRA); + assert!( + coin::balance(funder) == (100 * ONE_SUPRA), + 0 + ); + //fund existing delegator_address with locked state, this should still work + fund_delegators_with_locked_stake( + &funder_signer, + pool_address, + vector[delegator_address, new_delegator_address2], + vector[30 * ONE_SUPRA, 70 * ONE_SUPRA] + ); + assert!(coin::balance(funder) == 0, 0); + // 4 month timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - - withdraw(delegator, pool_address, 100 * ONE_SUPRA); + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS + 1); + end_aptos_epoch(); + //10% of 130 so 13 should be unlockable + unlock(delegator, pool_address, 13 * ONE_SUPRA); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] - /// after replace_delegator succeeds, new_delegator should be able to perform unlock and withdraw on the funds as per unlocking schedule - public entry fun test_replace_delegation_unlock_and_withdraw_success( - supra_framework: &signer, validator: &signer, delegator: &signer, + #[test( + supra_framework = @supra_framework, validator = @0x123, delegator = @0x010 + )] + /// test that delegators are indeed added to `principle_stake` table, appropriate + /// stakes they can unlock + public entry fun test_principle_stake_unlocking_success( + supra_framework: &signer, validator: &signer, delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); account::create_account_for_test(signer::address_of(validator)); let delegator_address = signer::address_of(delegator); let delegator_address_vec = vector[delegator_address, @0x020]; - let principle_stake = vector[300 * ONE_SUPRA, 200 * ONE_SUPRA]; - let coin = stake::mint_coins(500 * ONE_SUPRA); - let principle_lockup_time = 0; + let principle_stake = vector[100 * ONE_SUPRA, 200 * ONE_SUPRA]; + let coin = stake::mint_coins(300 * ONE_SUPRA); + let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4920,46 +8142,91 @@ module supra_framework::pbo_delegation_pool { principle_stake, coin, option::some(multisig), - vector[2, 2, 3], + vector[1], 10, principle_lockup_time, - 12); - + LOCKUP_CYCLE_SECONDS // monthly unlocking + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); - let multisig_signer = account::create_signer_for_test(multisig); - let new_delegator_address = @0x0101; - let new_delegator_address_signer = &account::create_signer_for_test( - new_delegator_address + let one_year_in_secs = 31536000; + let reward_period_start_time_in_sec = timestamp::now_seconds(); + staking_config::initialize_rewards( + supra_framework, + fixed_point64::create_from_rational(1, 100), + fixed_point64::create_from_rational(1, 100), + one_year_in_secs, + reward_period_start_time_in_sec, + fixed_point64::create_from_rational(0, 100) ); - replace_delegator(&multisig_signer, pool_address, delegator_address, - new_delegator_address); - - unlock(new_delegator_address_signer, pool_address, 100 * ONE_SUPRA); - assert_delegation(new_delegator_address, pool_address, 200 * ONE_SUPRA, 0, 100 * ONE_SUPRA); + let new_delegator_address2 = @0x0216; + let funder_signer = account::create_signer_for_test(multisig); + let funder = signer::address_of(&funder_signer); + stake::mint(&funder_signer, 100 * ONE_SUPRA); + assert!( + coin::balance(funder) == (100 * ONE_SUPRA), + 0 + ); + //fund existing delegator_address with locked state, this should still work + fund_delegators_with_locked_stake( + &funder_signer, + pool_address, + vector[delegator_address, new_delegator_address2], + vector[30 * ONE_SUPRA, 70 * ONE_SUPRA] + ); + assert!(coin::balance(funder) == 0, 0); + //Check that funded delegator was indeed added as a principle stake holder + assert!(is_principle_stakeholder(new_delegator_address2, pool_address), 9); + // 4 month + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + let (active_amount, _, _) = get_stake(pool_address, new_delegator_address2); + assert!(active_amount == 70 * ONE_SUPRA, active_amount); + let d2_principle_stake = get_principle_stake(new_delegator_address2, pool_address); + assert!( + active_amount == d2_principle_stake, + active_amount - d2_principle_stake + ); + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + unlock(delegator, pool_address, 13 * ONE_SUPRA); + // After 6 months + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + // 30% of 130, so 39*ONE_SUPRA should be unlockable out of which 13 were already unlocked earlier + let unlock_coin = + can_principle_unlock(delegator_address, pool_address, 26 * ONE_SUPRA); + let amount = cached_unlockable_balance(delegator_address, pool_address); + assert!(unlock_coin, amount); - withdraw(new_delegator_address_signer, pool_address, 100 * ONE_SUPRA); - assert!(coin::balance(new_delegator_address) == (100 * ONE_SUPRA) - 1, 0); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] - /// if delegator is not part of one of the principle stake holder, they can unlock/withdraw without restriction - public entry fun test_unlock_withdraw_delegator_not_part_of_principle_stake_success( + #[test( + supra_framework = @supra_framework, validator = @0x123, delegator = @0x010 + )] + /// say unlocking schedule is 3 month cliff, monthly unlocking of 10% and principle stake is 100 coins then + /// between 3 and 4 months, check that it's can't unlock there principal stacke + public entry fun test_unlocking_after_3_period_initial_and_funded_delegators_success( supra_framework: &signer, validator: &signer, delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); account::create_account_for_test(signer::address_of(validator)); let delegator_address = signer::address_of(delegator); let delegator_address_vec = vector[delegator_address, @0x020]; - let principle_stake = vector[300 * ONE_SUPRA, 200 * ONE_SUPRA]; - let coin = stake::mint_coins(500 * ONE_SUPRA); - let principle_lockup_time = 0; + let principle_stake = vector[100 * ONE_SUPRA, 200 * ONE_SUPRA]; + let coin = stake::mint_coins(300 * ONE_SUPRA); + let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4968,32 +8235,61 @@ module supra_framework::pbo_delegation_pool { principle_stake, coin, option::some(multisig), - vector[2, 2, 3], + vector[1], 10, principle_lockup_time, - 12); - + LOCKUP_CYCLE_SECONDS // monthly unlocking + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); - - let new_delegator_address = @0x0215; - let new_delegator_address_signer = account::create_account_for_test( - new_delegator_address + let one_year_in_secs = 31536000; + let reward_period_start_time_in_sec = timestamp::now_seconds(); + staking_config::initialize_rewards( + supra_framework, + fixed_point64::create_from_rational(1, 100), + fixed_point64::create_from_rational(1, 100), + one_year_in_secs, + reward_period_start_time_in_sec, + fixed_point64::create_from_rational(0, 100) ); - stake::mint(&new_delegator_address_signer, 100 * ONE_SUPRA); - assert!(coin::balance(new_delegator_address) == (100 * ONE_SUPRA), 0); - - add_stake(&new_delegator_address_signer, pool_address, 100 * ONE_SUPRA); - assert!(coin::balance(new_delegator_address) == 0, 0); + let new_delegator_address2 = @0x0216; + let funder_signer = account::create_signer_for_test(multisig); + let funder = signer::address_of(&funder_signer); + stake::mint(&funder_signer, 100 * ONE_SUPRA); + assert!( + coin::balance(funder) == (100 * ONE_SUPRA), + 0 + ); + //fund existing delegator_address with locked state, this should still work + fund_delegators_with_locked_stake( + &funder_signer, + pool_address, + vector[delegator_address, new_delegator_address2], + vector[30 * ONE_SUPRA, 70 * ONE_SUPRA] + ); + assert!(coin::balance(funder) == 0, 0); - unlock(&new_delegator_address_signer, pool_address,(100 * ONE_SUPRA)); + // 4 month + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); + unlock(delegator, pool_address, 13 * ONE_SUPRA); + // After 6 months + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); + end_aptos_epoch(); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - withdraw(&new_delegator_address_signer, pool_address,(100 * ONE_SUPRA)); - assert!(coin::balance(new_delegator_address) == (100 * ONE_SUPRA) - 1, 0); + // 30% of 130, so little bit less than 39*ONE_SUPRA should be unlockable, 13 already unlocked + unlock(delegator, pool_address, 26 * ONE_SUPRA); + } #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] @@ -5012,7 +8308,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5038,8 +8335,12 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 10); } @@ -5060,7 +8361,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5092,56 +8394,85 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(50 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(60 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (60 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 13); // after 7 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(70 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (70 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 14); // after 8 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(80 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (80 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 15); // after 9 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(90 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (90 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 16); // after 10 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(100 * ONE_SUPRA) - - 10); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (100 * ONE_SUPRA) - 10 + ); assert!(unlock_coin, 17); // after 11 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address, 100 * ONE_SUPRA); + let unlock_coin = + can_principle_unlock(delegator_address, pool_address, 100 * ONE_SUPRA); assert!(unlock_coin, 18); } @@ -5160,7 +8491,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5206,14 +8538,19 @@ module supra_framework::pbo_delegation_pool { timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(100 * ONE_SUPRA)); + let unlock_coin = + can_principle_unlock(delegator_address, pool_address, (100 * ONE_SUPRA)); assert!(unlock_coin, 11); - let unlock_schedule = borrow_global(pool_address).principle_unlock_schedule; + let unlock_schedule = + borrow_global(pool_address).principle_unlock_schedule; let cfraction_upperbound = fixed_point64::create_from_rational(3, 2); - assert!(fixed_point64::less(unlock_schedule.cumulative_unlocked_fraction, - cfraction_upperbound), - unlock_schedule.last_unlock_period); + assert!( + fixed_point64::less( + unlock_schedule.cumulative_unlocked_fraction, cfraction_upperbound + ), + unlock_schedule.last_unlock_period + ); } #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] @@ -5230,7 +8567,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5261,8 +8599,12 @@ module supra_framework::pbo_delegation_pool { timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - + 1); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) + 1 + ); assert!(unlock_coin, 20); } @@ -5280,7 +8622,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5312,15 +8655,23 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(50 * ONE_SUPRA) - + 1); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) + 1 + ); assert!(unlock_coin, 20); } @@ -5338,7 +8689,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5370,22 +8722,34 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(50 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(60 * ONE_SUPRA) - + 1); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (60 * ONE_SUPRA) + 1 + ); assert!(unlock_coin, 20); } @@ -5403,7 +8767,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5435,29 +8800,45 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(50 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(60 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (60 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 13); // after 7 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(70 * ONE_SUPRA) - + 1); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (70 * ONE_SUPRA) + 1 + ); assert!(unlock_coin, 20); } @@ -5475,7 +8856,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5507,36 +8889,56 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(50 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(60 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (60 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 13); // after 7 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(70 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (70 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 14); // after 8 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(80 * ONE_SUPRA) - + 1); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (80 * ONE_SUPRA) + 1 + ); assert!(unlock_coin, 20); } @@ -5554,7 +8956,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5586,43 +8989,67 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(50 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(60 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (60 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 13); // after 7 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(70 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (70 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 14); // after 8 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(80 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (80 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 15); // after 9 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(90 * ONE_SUPRA) - + 1); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (90 * ONE_SUPRA) + 1 + ); assert!(unlock_coin, 20); } @@ -5640,7 +9067,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5672,50 +9100,78 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(50 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(60 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (60 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 13); // after 7 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(70 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (70 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 14); // after 8 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(80 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (80 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 15); // after 9 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(90 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (90 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 16); // after 10 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(100 * ONE_SUPRA) - + 1); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (100 * ONE_SUPRA) + 1 + ); assert!(unlock_coin, 20); } @@ -5733,7 +9189,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5765,57 +9222,89 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (20 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(50 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (50 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(60 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (60 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 13); // after 7 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(70 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (70 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 14); // after 8 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(80 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (80 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 15); // after 9 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(90 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (90 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 16); // after 10 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(100 * ONE_SUPRA) - - 10); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (100 * ONE_SUPRA) - 10 + ); assert!(unlock_coin, 17); // after 11 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(100 * ONE_SUPRA) - + 1); + let unlock_coin = + can_principle_unlock( + delegator_address, + pool_address, + (100 * ONE_SUPRA) + 1 + ); assert!(unlock_coin, 20); } } diff --git a/aptos-move/framework/supra-framework/sources/stake.move b/aptos-move/framework/supra-framework/sources/stake.move index 2f3e669f6c232..47e44fb5d905b 100644 --- a/aptos-move/framework/supra-framework/sources/stake.move +++ b/aptos-move/framework/supra-framework/sources/stake.move @@ -2795,11 +2795,7 @@ module supra_framework::stake { let vci: &ValidatorConsensusInfo = obj; validator_consensus_info::get_addr(vci) }); - let vci_pks = vector::map_ref(&vci_vec_0, |obj|{ - let vci: &ValidatorConsensusInfo = obj; - validator_consensus_info::get_pk_bytes(vci) - }); - let vci_voting_powers = vector::map_ref(&vci_vec_0, |obj|{ + let vci_voting_powers = vector::map_ref(&vci_vec_0, |obj|{ let vci: &ValidatorConsensusInfo = obj; validator_consensus_info::get_voting_power(vci) }); diff --git a/aptos-move/framework/supra-framework/tests/delegation_pool_integration_tests.move b/aptos-move/framework/supra-framework/tests/delegation_pool_integration_tests.move index 8e3adf9f4a47f..68a2be0f737d3 100644 --- a/aptos-move/framework/supra-framework/tests/delegation_pool_integration_tests.move +++ b/aptos-move/framework/supra-framework/tests/delegation_pool_integration_tests.move @@ -102,8 +102,8 @@ module supra_framework::delegation_pool_integration_tests { #[test_only] public fun initialize_test_validator( - public_key: &bls12381::PublicKey, - proof_of_possession: &bls12381::ProofOfPossession, + _public_key: &bls12381::PublicKey, + _proof_of_possession: &bls12381::ProofOfPossession, validator: &signer, amount: u64, should_join_validator_set: bool, diff --git a/aptos-move/framework/supra-framework/tests/supra_coin_tests.move b/aptos-move/framework/supra-framework/tests/supra_coin_tests.move index 7d7594f9f6e06..38da10a150c6e 100644 --- a/aptos-move/framework/supra-framework/tests/supra_coin_tests.move +++ b/aptos-move/framework/supra-framework/tests/supra_coin_tests.move @@ -1,6 +1,5 @@ #[test_only] module supra_framework::supra_coin_tests { - use std::features; use supra_framework::supra_coin; use supra_framework::coin; use supra_framework::fungible_asset::{Self, FungibleStore, Metadata};