Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

staker v2: track historical total staked and historical seconds/staked #61

Open
moodysalem opened this issue Dec 1, 2024 · 2 comments · May be fixed by #63
Open

staker v2: track historical total staked and historical seconds/staked #61

moodysalem opened this issue Dec 1, 2024 · 2 comments · May be fixed by #63
Assignees
Labels
good first issue Good for newcomers

Comments

@moodysalem
Copy link
Member

we should keep track of snapshots of total staked (u64 + u128) and historical seconds per total staked

we should also allow computing the seconds per total staked at any historical point

this will allow for on-chain distribution of tokens to stakers. an external contract can take the tokens, stake them, and then when you unstake the tokens it can measure your number of stake-seconds (i.e. seconds where you have 100% stake) and reward you accordingly

keeping track of total staked is also nice because we can build a feature in the governance where if a proposal vote cannot fail it can be executed earl (technically we would need to know the total voting weight when voting started, not the total staked, which can be higher than total staked at the time the proposal was created)

we should probably make the staker upgradeable also

@moodysalem moodysalem added the good first issue Good for newcomers label Dec 1, 2024
@baitcode
Copy link

baitcode commented Dec 1, 2024

@moodysalem
I’d love to work on this task.

Approach plan

I think that all the changes should happen within staker.cairo or in other contract that is listening to staker events.

I see the task as the following:

  • Add storage for total staked amount history to the staker.cairo contract. Similar to staked. aggregate by from.
  • Add staked cumulative history data structure that holds log of cumulative staking amount changes. NOTE: this will be evergrowing.
  • Make staker contract upgradeable
  • Test new functionality
  • Populate initial data.

I would use a:

pub mod Staker {
    #[storage]
    struct Storage {
        // ....
        staked_total: Map<ContractAddress, u128>
        staked_per_second_cumulative_amount: Map<ContractAddress, Vec<(Timestamp, CumulativeStakedAmount)>>
    }
    // ....
}

fields. Every time stake, stake_amount, withdraw, withdraw_amount happens staked_per_second_cumulative_amount will be updated, new value of CumulativeStakedAmount will be added to the list with current timestamp.

AmountAtStakeBeforeEvent = self.staked_total[ContractAddress]
CumulativeStakedAmount = AmountAtStakeBeforeEvent * timedelta_since_last_event.

1 additional method will be added:

fn get_staked_per_second_cumulative_amount(addr: ContractAddress, ts: u128) -> CumulativeStakedAmount

This method will find log record before ts (log_before) and return: 0 if log_before not exist. if exists then find next log record (log_next) after ts.
If log_next does not exist then

CurrentStakedAmount = staked_total[ContractAddress]

else

CurrentStakedAmount = (log_after.CumulativeStakedAmount - log_before.CumulativeStakedAmount) / (log_after.Timestamp - log_before.Timestamp)

resulting CumulativeStakedAmount = CurrentStakedAmount * (ts - log_before.Timestamp)

Simplification at the cost of storage

This scheme can be simplified by storing total_amount as vector as well.

struct StakingLogRecord {
    timestamp: u128,
    total_staked: u64,
    cumulative_staked_per_second: u128
}

staking_log: Map<ContractAddress, Vec<StakingLogRecord>>

@moodysalem Let me know what you think and which way you prefer. I also need guidance on how to initialise staking amounts values.

@moodysalem
Copy link
Member Author

Populate initial data.

Not necessary, since the old one is not upgradeable we do not need to do any migrations. This would be a new deployment addressed in the governor that supports multiple stakers

staked_total: Map<ContractAddress, u128>

Staked total that we care about is the overall total staked across all addresses, not per address, and we probably want to use an accumulator also so we can get the total voting weight over a period

staked_per_second_cumulative_amount: Map<ContractAddress, Vec<(Timestamp, CumulativeStakedAmount)>>

Again not per address, this is at a global level, we just need historical to be able to compute the difference over any two timestamps

@baitcode baitcode linked a pull request Dec 11, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants