cfx_executor/state/state_object/
pos.rs1use super::State;
6use crate::{
7 internal_contract::{pos_internal_entries, IndexStatus},
8 return_if,
9};
10use cfx_math::sqrt_u256;
11use cfx_parameters::{
12 internal_contract_addresses::POS_REGISTER_CONTRACT_ADDRESS, staking::*,
13};
14use cfx_statedb::{
15 global_params::{
16 DistributablePoSInterest, InterestRate, LastDistributeBlock,
17 TotalPosStaking,
18 },
19 Result as DbResult,
20};
21use cfx_types::{Address, AddressSpaceUtil, BigEndianHash, H256, U256};
22use diem_types::term_state::MAX_TERM_POINTS;
23
24impl State {
25 pub fn inc_distributable_pos_interest(
26 &mut self, current_block_number: u64,
27 ) -> DbResult<()> {
28 assert!(self.checkpoints.get_mut().is_empty());
29
30 let next_distribute_block =
31 self.global_stat.refr::<LastDistributeBlock>().as_u64()
32 + BLOCKS_PER_HOUR;
33
34 return_if!(current_block_number > next_distribute_block);
35 return_if!(self.global_stat.refr::<TotalPosStaking>().is_zero());
36
37 let total_circulating_tokens = self.total_circulating_tokens()?;
38 let total_pos_staking_tokens =
39 self.global_stat.refr::<TotalPosStaking>();
40
41 let interest_rate_per_block = self.global_stat.refr::<InterestRate>();
44 let interest_amount = sqrt_u256(
45 total_circulating_tokens
46 * *total_pos_staking_tokens
47 * *interest_rate_per_block
48 * *interest_rate_per_block,
49 ) / (BLOCKS_PER_YEAR
50 * INVERSE_INTEREST_RATE
51 * INITIAL_INTEREST_RATE_PER_BLOCK.as_u64());
52 *self.global_stat.val::<DistributablePoSInterest>() += interest_amount;
53
54 Ok(())
55 }
56
57 pub fn pos_locked_staking(&self, address: &Address) -> DbResult<U256> {
58 let identifier = BigEndianHash::from_uint(&self.storage_at(
59 &POS_REGISTER_CONTRACT_ADDRESS.with_native_space(),
60 &pos_internal_entries::identifier_entry(address),
61 )?);
62 let current_value: IndexStatus = self
63 .storage_at(
64 &POS_REGISTER_CONTRACT_ADDRESS.with_native_space(),
65 &pos_internal_entries::index_entry(&identifier),
66 )?
67 .into();
68 Ok(*POS_VOTE_PRICE * current_value.locked())
69 }
70
71 pub fn add_pos_interest(
72 &mut self, address: &Address, interest: &U256,
73 ) -> DbResult<()> {
74 let address = address.with_native_space();
75 self.add_total_issued(*interest);
76 self.add_balance(&address, interest)?;
77 self.write_account_or_new_lock(&address)?
78 .record_interest_receive(interest);
79 Ok(())
80 }
81}
82
83pub fn distribute_pos_interest<'a, I>(
87 state: &mut State, pos_points: I, current_block_number: u64,
88) -> DbResult<Vec<(Address, H256, U256)>>
89where I: Iterator<Item = (&'a H256, u64)> + 'a {
90 assert!(state.checkpoints.get_mut().is_empty());
91
92 let distributable_pos_interest = state.distributable_pos_interest();
93
94 let mut account_rewards = Vec::new();
95 for (identifier, points) in pos_points {
96 let address_value = state.storage_at(
97 &POS_REGISTER_CONTRACT_ADDRESS.with_native_space(),
98 &pos_internal_entries::address_entry(&identifier),
99 )?;
100 let address = Address::from(H256::from_uint(&address_value));
101 let interest = distributable_pos_interest * points / MAX_TERM_POINTS;
102 account_rewards.push((address, *identifier, interest));
103 state.add_pos_interest(&address, &interest)?;
104 }
105 state.reset_pos_distribute_info(current_block_number);
106
107 Ok(account_rewards)
108}
109
110pub fn update_pos_status(
111 state: &mut State, identifier: H256, number: u64,
112) -> DbResult<()> {
113 let old_value = state.storage_at(
114 &POS_REGISTER_CONTRACT_ADDRESS.with_native_space(),
115 &pos_internal_entries::index_entry(&identifier),
116 )?;
117 assert!(
118 !old_value.is_zero(),
119 "If an identifier is unlocked, its index information must be non-zero"
120 );
121 let mut status: IndexStatus = old_value.into();
122 let new_unlocked = number - status.unlocked;
123 status.set_unlocked(number);
124 state
126 .write_native_account_lock(&POS_REGISTER_CONTRACT_ADDRESS)?
127 .change_storage_value(
128 &state.db,
129 &pos_internal_entries::index_entry(&identifier),
130 status.into(),
131 )?;
132 state.sub_total_pos_staking(*POS_VOTE_PRICE * new_unlocked);
133 Ok(())
134}