Skip to content

Commit

Permalink
unstake from unregistered call
Browse files Browse the repository at this point in the history
  • Loading branch information
Dinonard committed Oct 24, 2023
1 parent f2f8a5f commit 03d88f4
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 4 deletions.
79 changes: 76 additions & 3 deletions pallets/dapp-staking-v3/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,11 @@ pub mod pallet {
era: EraNumber,
amount: Balance,
},
UnstakeFromUnregistered {
account: T::AccountId,
smart_contract: T::SmartContract,
amount: Balance,
},
}

#[pallet::error]
Expand Down Expand Up @@ -295,6 +300,8 @@ pub mod pallet {
DAppRewardAlreadyClaimed,
/// An unexpected error occured while trying to claim dApp reward.
InternalClaimDAppError,
/// Contract is still active, not unregistered.
ContractStillActive,
}

/// General information about dApp staking protocol state.
Expand Down Expand Up @@ -693,9 +700,10 @@ pub mod pallet {
},
)?;

// TODO: might require some modification later on, like additional checks to ensure contract can be unregistered.

// TODO2: we should remove staked amount from appropriate entries, since contract has been 'invalidated'
// As a consequence, this means that the sum of all stakes from `ContractStake` storage won't match
// total stake in active era info. This is fine, from the logic perspective, it doesn't cause any issues.
// TODO: left as potential discussion topic, remove later.
ContractStake::<T>::remove(&smart_contract);

// TODO3: will need to add a call similar to what we have in DSv2, for stakers to 'unstake_from_unregistered_contract'

Expand Down Expand Up @@ -1289,6 +1297,71 @@ pub mod pallet {

Ok(())
}

/// TODO
#[pallet::call_index(14)]
#[pallet::weight(Weight::zero())]
pub fn unstake_from_unregistered(
origin: OriginFor<T>,
smart_contract: T::SmartContract,
) -> DispatchResult {
// TODO: this call needs to be tested
Self::ensure_pallet_enabled()?;
let account = ensure_signed(origin)?;

ensure!(
!Self::is_active(&smart_contract),
Error::<T>::ContractStillActive
);

let protocol_state = ActiveProtocolState::<T>::get();
let unstake_era = protocol_state.era;

// Extract total staked amount on the specified unregistered contract
let amount = match StakerInfo::<T>::get(&account, &smart_contract) {
Some(staking_info) => {
ensure!(
staking_info.period_number() == protocol_state.period_number(),
Error::<T>::UnstakeFromPastPeriod
);

staking_info.total_staked_amount()
}
None => {
return Err(Error::<T>::NoStakingInfo.into());
}
};

// Reduce stake amount in ledger
let mut ledger = Ledger::<T>::get(&account);
ledger
.unstake_amount(amount, unstake_era, protocol_state.period_info)
.map_err(|err| match err {
// These are all defensive checks, which should never happen since we already checked them above.
AccountLedgerError::InvalidPeriod | AccountLedgerError::InvalidEra => {
Error::<T>::UnclaimedRewardsFromPastPeriods
}
_ => Error::<T>::InternalUnstakeError,
})?;

// Update total staked amount for the next era.
// This means 'fake' stake total amount has been kept until now, even though contract was unregistered.
CurrentEraInfo::<T>::mutate(|era_info| {
era_info.unstake_amount(amount, protocol_state.period_type());
});

// Update remaining storage entries
Self::update_ledger(&account, ledger);
StakerInfo::<T>::remove(&account, &smart_contract);

Self::deposit_event(Event::<T>::UnstakeFromUnregistered {
account,
smart_contract,
amount,
});

Ok(())
}
}

impl<T: Config> Pallet<T> {
Expand Down
1 change: 1 addition & 0 deletions pallets/dapp-staking-v3/src/test/testing_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ pub(crate) fn assert_unregister(smart_contract: &MockSmartContract) {
IntegratedDApps::<Test>::get(&smart_contract).unwrap().state,
DAppState::Unregistered(pre_snapshot.active_protocol_state.era),
);
assert!(!ContractStake::<Test>::contains_key(&smart_contract));
}

/// Lock funds into dApp staking and assert success.
Expand Down
18 changes: 17 additions & 1 deletion pallets/dapp-staking-v3/src/test/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,13 +330,29 @@ fn set_dapp_owner_fails() {
}

#[test]
fn unregister_is_ok() {
fn unregister_no_stake_is_ok() {
ExtBuilder::build().execute_with(|| {
// Prepare dApp
let owner = 1;
let smart_contract = MockSmartContract::Wasm(3);
assert_register(owner, &smart_contract);

// Nothing staked on contract, just unregister it.
assert_unregister(&smart_contract);
})
}

#[test]
fn unregister_with_active_stake_is_ok() {
ExtBuilder::build().execute_with(|| {
// Prepare dApp
let owner = 1;
let smart_contract = MockSmartContract::Wasm(3);
assert_register(owner, &smart_contract);
assert_lock(owner, 100);
assert_stake(owner, &smart_contract, 100);

// Some amount is staked, unregister must still work.
assert_unregister(&smart_contract);
})
}
Expand Down

0 comments on commit 03d88f4

Please sign in to comment.