Skip to content

Commit

Permalink
stake-contract
Browse files Browse the repository at this point in the history
  • Loading branch information
herr-seppia committed Sep 6, 2024
1 parent 9348595 commit 6290a97
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 66 deletions.
64 changes: 19 additions & 45 deletions contracts/stake/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use dusk_bytes::Serializable;
use execution_core::{
signatures::bls::PublicKey as BlsPublicKey,
stake::{
next_epoch, Reward, Stake, StakeAmount, StakeData, StakeEvent,
StakeWithReceiverEvent, Withdraw, EPOCH, MINIMUM_STAKE, STAKE_CONTRACT,
next_epoch, Reward, SlashEvent, Stake, StakeAmount, StakeData,
StakeEvent, Withdraw, EPOCH, MINIMUM_STAKE, STAKE_CONTRACT,
STAKE_WARNINGS,
},
transfer::TRANSFER_CONTRACT,
Expand Down Expand Up @@ -165,14 +165,7 @@ impl StakeState {
// update the state accordingly
loaded_stake.amount = None;

rusk_abi::emit(
"unstake",
StakeWithReceiverEvent {
account,
value: withdrawal_value,
receiver: Some(*transfer_withdraw.receiver()),
},
);
rusk_abi::emit("unstake", StakeEvent { account, value });

let key = account.to_bytes();
self.previous_block_state
Expand Down Expand Up @@ -214,14 +207,7 @@ impl StakeState {

// update the state accordingly
loaded_stake.reward -= value;
rusk_abi::emit(
"withdraw",
StakeWithReceiverEvent {
account,
value,
receiver: Some(*transfer_withdraw.receiver()),
},
);
rusk_abi::emit("withdraw", StakeEvent { account, value });
}

/// Gets a reference to a stake.
Expand Down Expand Up @@ -327,14 +313,6 @@ impl StakeState {

stake_amount.eligibility =
next_epoch(rusk_abi::block_height()) + to_shift;

rusk_abi::emit(
"suspended",
StakeEvent {
account: *account,
value: stake_amount.eligibility,
},
);
}

// Slash the provided amount or calculate the percentage according to
Expand All @@ -345,12 +323,15 @@ impl StakeState {

if to_slash > 0 {
stake_amount.lock_amount(to_slash);
}

if to_slash > 0 || effective_faults > 0 {
rusk_abi::emit(
"slash",
StakeEvent {
SlashEvent {
account: *account,
value: to_slash,
next_eligibility: stake_amount.eligibility,
},
);
}
Expand Down Expand Up @@ -393,16 +374,8 @@ impl StakeState {
// The stake is shifted (aka suspended) for the rest of the current
// epoch plus hard_faults epochs
let to_shift = hard_faults * EPOCH;
stake_amount.eligibility =
next_epoch(rusk_abi::block_height()) + to_shift;

rusk_abi::emit(
"suspended",
StakeEvent {
account: *account,
value: stake_amount.eligibility,
},
);
let next_eligibility = next_epoch(rusk_abi::block_height()) + to_shift;
stake_amount.eligibility = next_eligibility;

// Slash the provided amount or calculate the percentage according to
// hard faults
Expand All @@ -417,16 +390,17 @@ impl StakeState {

// Update the total burnt amount
self.burnt_amount += to_slash;

rusk_abi::emit(
"hard_slash",
StakeEvent {
account: *account,
value: to_slash,
},
);
}

rusk_abi::emit(
"hard_slash",
SlashEvent {
account: *account,
value: to_slash,
next_eligibility,
},
);

let key = account.to_bytes();
self.previous_block_state
.entry(key)
Expand Down
47 changes: 35 additions & 12 deletions contracts/stake/tests/common/assert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rkyv::{check_archived_root, Deserialize, Infallible};

use execution_core::{
signatures::bls::PublicKey as BlsPublicKey,
stake::{Reward, StakeEvent, StakeWithReceiverEvent},
stake::{Reward, SlashEvent, StakeEvent},
Event,
};

Expand All @@ -27,17 +27,7 @@ pub fn assert_event<S>(
.find(|e| e.topic == topic)
.expect(&format!("event: {topic} should exist in the event list",));

if topic == "unstake" || topic == "withdraw" {
let staking_event_data = check_archived_root::<StakeWithReceiverEvent>(
event.data.as_slice(),
)
.expect("Stake event data should deserialize correctly");
let staking_event_data: StakeWithReceiverEvent = staking_event_data
.deserialize(&mut Infallible)
.expect("Infallible");
assert_eq!(staking_event_data.value, should_amount);
assert_eq!(staking_event_data.account.to_bytes(), should_pk.to_bytes());
} else if topic == "reward" {
if topic == "reward" {
let reward_event_data = rkyv::from_bytes::<Vec<Reward>>(&event.data)
.expect("Reward event data should deserialize correctly");

Expand All @@ -55,3 +45,36 @@ pub fn assert_event<S>(
assert_eq!(staking_event_data.account.to_bytes(), should_pk.to_bytes());
}
}

pub fn assert_slash_event<S, E: Into<Option<u64>>>(
events: &Vec<Event>,
topic: S,
should_pk: &BlsPublicKey,
should_amount: u64,
should_eligibility: E,
) where
S: AsRef<str>,
{
let topic = topic.as_ref();
let event = events
.iter()
.find(|e| e.topic == topic)
.expect(&format!("event: {topic} should exist in the event list",));

if topic == "slash" || topic == "hard_slash" {
let staking_event_data =
check_archived_root::<SlashEvent>(event.data.as_slice())
.expect("Stake event data should deserialize correctly");
let staking_event_data: SlashEvent = staking_event_data
.deserialize(&mut Infallible)
.expect("Infallible");
assert_eq!(staking_event_data.value, should_amount);
assert_eq!(staking_event_data.account.to_bytes(), should_pk.to_bytes());
let should_eligibility: Option<u64> = should_eligibility.into();
if let Some(should_eligibility) = should_eligibility {
assert_eq!(staking_event_data.next_eligibility, should_eligibility);
}
} else {
panic!("{topic} topic cannot be verified with assert_slash_event");
}
}
42 changes: 33 additions & 9 deletions contracts/stake/tests/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

pub mod common;

use common::assert::assert_slash_event;
use rand::rngs::StdRng;
use rand::SeedableRng;

Expand Down Expand Up @@ -89,7 +90,7 @@ fn reward_slash() -> Result<(), PiecrustError> {
u64::MAX,
)?;
assert!(receipt.events.len() == 1, "No shift at first warn");
assert_event(&receipt.events, "slash", &stake_pk, slash_amount);
assert_slash_event(&receipt.events, "slash", &stake_pk, slash_amount, None);
let stake_amount = stake_amount - slash_amount;

let receipt = session.call::<_, ()>(
Expand All @@ -100,8 +101,7 @@ fn reward_slash() -> Result<(), PiecrustError> {
)?;
// 10% of current amount
let slash_amount = stake_amount / 10;
assert_event(&receipt.events, "slash", &stake_pk, slash_amount);
assert_event(&receipt.events, "suspended", &stake_pk, 4320);
assert_slash_event(&receipt.events, "slash", &stake_pk, slash_amount, 4320);

let receipt = session.call::<_, ()>(
STAKE_CONTRACT,
Expand All @@ -113,8 +113,7 @@ fn reward_slash() -> Result<(), PiecrustError> {

// 20% of current amount
let slash_amount = stake_amount / 100 * 20;
assert_event(&receipt.events, "slash", &stake_pk, slash_amount);
assert_event(&receipt.events, "suspended", &stake_pk, 6480);
assert_slash_event(&receipt.events, "slash", &stake_pk, slash_amount, 6480);

Ok(())
}
Expand Down Expand Up @@ -175,7 +174,14 @@ fn stake_hard_slash() -> Result<(), PiecrustError> {
u64::MAX,
)?;
let expected_slash = stake_amount / 100 * 10;
assert_event(&receipt.events, "hard_slash", &stake_pk, expected_slash);
assert_slash_event(
&receipt.events,
"hard_slash",
&stake_pk,
expected_slash,
None,
);
println!("f1");
cur_balance -= expected_slash;

// Severe hard fault (slash 30%)
Expand All @@ -186,7 +192,13 @@ fn stake_hard_slash() -> Result<(), PiecrustError> {
u64::MAX,
)?;
let expected_slash = cur_balance / 100 * (1 + severity) * 10;
assert_event(&receipt.events, "hard_slash", &stake_pk, expected_slash);
assert_slash_event(
&receipt.events,
"hard_slash",
&stake_pk,
expected_slash,
None,
);
cur_balance -= expected_slash;

// Direct slash (slash hard_slash_amount)
Expand All @@ -196,7 +208,13 @@ fn stake_hard_slash() -> Result<(), PiecrustError> {
&(stake_pk, Some(hard_slash_amount), None::<u8>),
u64::MAX,
)?;
assert_event(&receipt.events, "hard_slash", &stake_pk, hard_slash_amount);
assert_slash_event(
&receipt.events,
"hard_slash",
&stake_pk,
hard_slash_amount,
None,
);
cur_balance -= hard_slash_amount;

let rewards = vec![Reward {
Expand All @@ -218,7 +236,13 @@ fn stake_hard_slash() -> Result<(), PiecrustError> {
u64::MAX,
)?;
let expected_slash = cur_balance / 100 * 10;
assert_event(&receipt.events, "hard_slash", &stake_pk, expected_slash);
assert_slash_event(
&receipt.events,
"hard_slash",
&stake_pk,
expected_slash,
None,
);

Ok(())
}

0 comments on commit 6290a97

Please sign in to comment.