Skip to content

Commit

Permalink
Review fixes
Browse files Browse the repository at this point in the history
* uniform get_block_timestamp usage
* store log_record timestamp in seconds
* inline test assert for fp value
* rename HALF to TWO_POW_127
  • Loading branch information
baitcode committed Jan 13, 2025
1 parent 284ae39 commit c6102a1
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 38 deletions.
16 changes: 8 additions & 8 deletions src/staker.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@ pub mod Staker {
};
use super::{IStaker};



#[derive(Copy, Drop, PartialEq, Debug)]
pub struct DelegatedSnapshot {
pub timestamp: u64,
Expand All @@ -86,7 +84,7 @@ pub mod Staker {
const TWO_POW_64: u128 = 0x10000000000000000;
const TWO_POW_192: u256 = 0x1000000000000000000000000000000000000000000000000;
const TWO_POW_192_DIVISOR: NonZero<u256> = 0x1000000000000000000000000000000000000000000000000;
const HALF: u128 = 0x80000000000000000000000000000000_u128;
const TWO_POW_127: u128 = 0x80000000000000000000000000000000_u128;

pub(crate) impl DelegatedSnapshotStorePacking of StorePacking<DelegatedSnapshot, felt252> {
fn pack(value: DelegatedSnapshot) -> felt252 {
Expand Down Expand Up @@ -266,7 +264,7 @@ pub mod Staker {
.write(delegate, self.insert_snapshot(delegate, get_block_timestamp()) + amount);

let total_staked = self.total_staked.read();
assert(total_staked + amount >= total_staked, 'BAD AMOUNT');

self.total_staked.write(total_staked + amount);
self.staking_log.log_change(amount, total_staked);

Expand Down Expand Up @@ -357,7 +355,9 @@ pub mod Staker {
}

fn get_cumulative_seconds_per_total_staked_at(self: @ContractState, timestamp: u64) -> u256 {
if let Option::Some((log_record, idx)) = self.staking_log.find_in_change_log(timestamp) {
let timestamp_seconds = timestamp / 1000;

if let Option::Some((log_record, idx)) = self.staking_log.find_in_change_log(timestamp_seconds) {
let total_staked = if (idx == self.staking_log.len() - 1) {
// if last rescord found
self.total_staked.read()
Expand All @@ -373,7 +373,7 @@ pub mod Staker {
return 0_u64.into();
}

let diff_seconds: u128 = ((next_log_record.timestamp - log_record.timestamp) / 1000).into();
let diff_seconds: u128 = (next_log_record.timestamp - log_record.timestamp).into();

// Divide u64 by fixed point
let (total_staked_fp_medium, _) = u512_safe_div_rem_by_u256(
Expand All @@ -389,14 +389,14 @@ pub mod Staker {
assert(total_staked_fp.high < MAX_FP, 'FP_OVERFLOW');

// round value
total_staked_fp.high + if (total_staked_fp.low >= HALF) {
total_staked_fp.high + if (total_staked_fp.low >= TWO_POW_127) {
1
} else {
0
}
};

let seconds_diff = (timestamp - log_record.timestamp) / 1000;
let seconds_diff = timestamp_seconds - log_record.timestamp;

let staked_seconds: u256 = if total_staked == 0 {
0_u256
Expand Down
11 changes: 6 additions & 5 deletions src/staker_log.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ pub(crate) struct StakingLogRecord {
pub(crate) timestamp: u64,

// Only 128+32=160 bits are used
// TODO: add validation checks
pub(crate) cumulative_total_staked: u256,
pub(crate) cumulative_seconds_per_total_staked: u256,
}
Expand Down Expand Up @@ -68,10 +67,12 @@ pub impl StakingLogOperations of LogOperations {
fn log_change(self: StorageBase<Mutable<StakingLog>>, amount: u128, total_staked: u128) {
let log = self.as_path();

let block_timestamp = get_block_timestamp() / 1000;

if log.len() == 0 {
log.append().write(
StakingLogRecord {
timestamp: get_block_timestamp(),
timestamp: block_timestamp,
cumulative_total_staked: 0_u256,
cumulative_seconds_per_total_staked: 0_u64.into(),
}
Expand All @@ -84,7 +85,7 @@ pub impl StakingLogOperations of LogOperations {

let mut last_record = last_record_ptr.read();

let mut record = if last_record.timestamp == get_block_timestamp() {
let mut record = if last_record.timestamp == block_timestamp {
// update record
last_record_ptr
} else {
Expand All @@ -93,7 +94,7 @@ pub impl StakingLogOperations of LogOperations {
};

// Might be zero
let seconds_diff = (get_block_timestamp() - last_record.timestamp) / 1000;
let seconds_diff = block_timestamp - last_record.timestamp;

let total_staked_by_elapsed_seconds = total_staked.into() * seconds_diff.into();

Expand All @@ -108,7 +109,7 @@ pub impl StakingLogOperations of LogOperations {
// Add a new record.
record.write(
StakingLogRecord {
timestamp: get_block_timestamp(),
timestamp: block_timestamp,

cumulative_total_staked:
last_record.cumulative_total_staked + total_staked_by_elapsed_seconds,
Expand Down
43 changes: 18 additions & 25 deletions src/staker_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -411,8 +411,9 @@ mod staker_staked_seconds_per_total_staked_calculation {
#[test]
fn test_should_return_0_if_no_data_found() {
let (staker, _) = setup(10000);
assert_fp(staker.get_cumulative_seconds_per_total_staked_at(0), 0, 0_u128.into());
assert_fp(staker.get_cumulative_seconds_per_total_staked_at(1000), 0, 0_u128.into());

assert_eq!(staker.get_cumulative_seconds_per_total_staked_at(0), u256{ high: 0, low: 0_u128.into()});
assert_eq!(staker.get_cumulative_seconds_per_total_staked_at(1000), u256{ high: 0, low: 0_u128.into()});
}

#[test]
Expand Down Expand Up @@ -441,11 +442,6 @@ mod staker_staked_seconds_per_total_staked_calculation {
staker.withdraw_amount(delegatee, token_owner, 2000);
}

fn assert_fp(value: u256, integer: u128, fractional: u128) {
assert_eq!(value.high, integer);
assert_eq!(value.low, fractional);
}

#[test]
fn test_should_stake_10000_tokens_for_5_seconds_adding_10000_every_second_to_staked_seconds() {
let (staker, token) = setup(1000);
Expand Down Expand Up @@ -474,23 +470,20 @@ mod staker_staked_seconds_per_total_staked_calculation {
token.approve(staker.contract_address, 7);
staker.stake(delegatee); // Will transfer 7 token to contract account and setup delegatee

assert_fp(staker.get_cumulative_seconds_per_total_staked_at(0), 0, 0_u128);
assert_fp(staker.get_cumulative_seconds_per_total_staked_at(500), 0, 0_u128);
assert_fp(staker.get_cumulative_seconds_per_total_staked_at(999), 0, 0_u128);

assert_fp(staker.get_cumulative_seconds_per_total_staked_at(1000), 0, 0x80000000000000000000000000000000_u128);
assert_fp(staker.get_cumulative_seconds_per_total_staked_at(2000), 1, 0_u128);
assert_fp(staker.get_cumulative_seconds_per_total_staked_at(3000), 1, 0x80000000000000000000000000000000_u128);
assert_fp(staker.get_cumulative_seconds_per_total_staked_at(4000), 2, 0_u128);

// here value is undefined as nothing was staked.
assert_fp(staker.get_cumulative_seconds_per_total_staked_at(5000), 0, 0_u128);
assert_fp(staker.get_cumulative_seconds_per_total_staked_at(6000), 0, 0_u128);
assert_fp(staker.get_cumulative_seconds_per_total_staked_at(7000), 0, 0_u128);
assert_fp(staker.get_cumulative_seconds_per_total_staked_at(8000), 0, 0_u128);
assert_fp(staker.get_cumulative_seconds_per_total_staked_at(9000), 0, 0_u128);
assert_fp(staker.get_cumulative_seconds_per_total_staked_at(10000), 2, 0x80000000000000000000000000000000_u128);
assert_fp(staker.get_cumulative_seconds_per_total_staked_at(17000), 3, 0x80000000000000000000000000000000_u128);
assert_fp(staker.get_cumulative_seconds_per_total_staked_at(24000), 4, 0x80000000000000000000000000000000_u128);
assert_eq!(staker.get_cumulative_seconds_per_total_staked_at(0), u256 {high: 0, low: 0_u128});
assert_eq!(staker.get_cumulative_seconds_per_total_staked_at(500), u256 {high: 0, low: 0_u128});
assert_eq!(staker.get_cumulative_seconds_per_total_staked_at(999), u256 {high: 0, low: 0_u128});
assert_eq!(staker.get_cumulative_seconds_per_total_staked_at(1000), u256 {high: 0, low: 0x80000000000000000000000000000000_u128});
assert_eq!(staker.get_cumulative_seconds_per_total_staked_at(2000), u256 {high: 1, low: 0_u128});
assert_eq!(staker.get_cumulative_seconds_per_total_staked_at(3000), u256 {high: 1, low: 0x80000000000000000000000000000000_u128});
assert_eq!(staker.get_cumulative_seconds_per_total_staked_at(4000), u256 {high: 2, low: 0_u128});
assert_eq!(staker.get_cumulative_seconds_per_total_staked_at(5000), u256 {high: 0, low: 0_u128});
assert_eq!(staker.get_cumulative_seconds_per_total_staked_at(6000), u256 {high: 0, low: 0_u128});
assert_eq!(staker.get_cumulative_seconds_per_total_staked_at(7000), u256 {high: 0, low: 0_u128});
assert_eq!(staker.get_cumulative_seconds_per_total_staked_at(8000), u256 {high: 0, low: 0_u128});
assert_eq!(staker.get_cumulative_seconds_per_total_staked_at(9000), u256 {high: 0, low: 0_u128});
assert_eq!(staker.get_cumulative_seconds_per_total_staked_at(10000), u256 {high: 2, low: 0x80000000000000000000000000000000_u128});
assert_eq!(staker.get_cumulative_seconds_per_total_staked_at(17000), u256 {high: 3, low: 0x80000000000000000000000000000000_u128});
assert_eq!(staker.get_cumulative_seconds_per_total_staked_at(24000), u256 {high: 4, low: 0x80000000000000000000000000000000_u128});
}
}

0 comments on commit c6102a1

Please sign in to comment.