Skip to content

Commit

Permalink
[staking] add stake subsidies
Browse files Browse the repository at this point in the history
  • Loading branch information
emmazzz committed Dec 20, 2022
1 parent a057689 commit 16b1a26
Show file tree
Hide file tree
Showing 12 changed files with 124 additions and 9 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -445,4 +445,5 @@ parameters:
reference_gas_price: 0
validator_report_records:
contents: []
next_epoch_stake_subsidy: 1000000

Original file line number Diff line number Diff line change
Expand Up @@ -441,4 +441,5 @@ parameters:
reference_gas_price: 0
validator_report_records:
contents: []
next_epoch_stake_subsidy: 1000000

Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ expression: common_costs_estimate
---
{
"MergeCoin": {
"computation_cost": 6134,
"storage_cost": 9057,
"computation_cost": 6166,
"storage_cost": 9104,
"storage_rebate": 0
},
"Publish": {
"computation_cost": 6927,
"storage_cost": 10161,
"computation_cost": 6958,
"storage_cost": 10208,
"storage_rebate": 0
},
"SharedCounterAssertValue": {
Expand All @@ -29,8 +29,8 @@ expression: common_costs_estimate
"storage_rebate": 0
},
"SplitCoin": {
"computation_cost": 6112,
"storage_cost": 9024,
"computation_cost": 6144,
"storage_cost": 9071,
"storage_rebate": 0
},
"TransferPortionSuiCoin": {
Expand Down
11 changes: 11 additions & 0 deletions crates/sui-framework/docs/genesis.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ Initial value of the lower-bound on the amount of stake required to become a val



<a name="0x2_genesis_INIT_STAKE_SUBSIDY_AMOUNT"></a>

Stake subisidy to be given out in the very first epoch. Placeholder value.


<pre><code><b>const</b> <a href="genesis.md#0x2_genesis_INIT_STAKE_SUBSIDY_AMOUNT">INIT_STAKE_SUBSIDY_AMOUNT</a>: u64 = 1000000;
</code></pre>



<a name="0x2_genesis_INIT_STORAGE_FUND"></a>

The initial amount of SUI locked in the storage fund.
Expand Down Expand Up @@ -152,6 +162,7 @@ all the information we need in the system.
<a href="genesis.md#0x2_genesis_INIT_MAX_VALIDATOR_COUNT">INIT_MAX_VALIDATOR_COUNT</a>,
<a href="genesis.md#0x2_genesis_INIT_MIN_VALIDATOR_STAKE">INIT_MIN_VALIDATOR_STAKE</a>,
<a href="genesis.md#0x2_genesis_INIT_STORAGE_GAS_PRICE">INIT_STORAGE_GAS_PRICE</a>,
<a href="genesis.md#0x2_genesis_INIT_STAKE_SUBSIDY_AMOUNT">INIT_STAKE_SUBSIDY_AMOUNT</a>,
);
}
</code></pre>
Expand Down
66 changes: 65 additions & 1 deletion crates/sui-framework/docs/sui_system.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
- [Function `report_validator`](#0x2_sui_system_report_validator)
- [Function `undo_report_validator`](#0x2_sui_system_undo_report_validator)
- [Function `advance_epoch`](#0x2_sui_system_advance_epoch)
- [Function `update_stake_subsidy_amount`](#0x2_sui_system_update_stake_subsidy_amount)
- [Function `epoch`](#0x2_sui_system_epoch)
- [Function `validator_delegate_amount`](#0x2_sui_system_validator_delegate_amount)
- [Function `validator_stake_amount`](#0x2_sui_system_validator_stake_amount)
Expand Down Expand Up @@ -164,6 +165,13 @@ The top-level object containing all information of the Sui system.
them. If a validator has never been reported they don't have an entry in this map.
This map resets every epoch.
</dd>
<dt>
<code>next_epoch_stake_subsidy: u64</code>
</dt>
<dd>
The amount of stake subsidies to be given out in the next epoch, updated at
epoch boundaries.
</dd>
</dl>


Expand Down Expand Up @@ -228,6 +236,24 @@ The top-level object containing all information of the Sui system.



<a name="0x2_sui_system_STAKE_SUBSIDY_DECREASE_RATE"></a>



<pre><code><b>const</b> <a href="sui_system.md#0x2_sui_system_STAKE_SUBSIDY_DECREASE_RATE">STAKE_SUBSIDY_DECREASE_RATE</a>: u128 = 1000;
</code></pre>



<a name="0x2_sui_system_STAKE_SUBSIDY_PERIOD_LENGTH"></a>



<pre><code><b>const</b> <a href="sui_system.md#0x2_sui_system_STAKE_SUBSIDY_PERIOD_LENGTH">STAKE_SUBSIDY_PERIOD_LENGTH</a>: u64 = 30;
</code></pre>



<a name="0x2_sui_system_create"></a>

## Function `create`
Expand All @@ -236,7 +262,7 @@ Create a new SuiSystemState object and make it shared.
This function will be called only once in genesis.


<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="sui_system.md#0x2_sui_system_create">create</a>(chain_id: u8, validators: <a href="">vector</a>&lt;<a href="validator.md#0x2_validator_Validator">validator::Validator</a>&gt;, sui_supply: <a href="balance.md#0x2_balance_Supply">balance::Supply</a>&lt;<a href="sui.md#0x2_sui_SUI">sui::SUI</a>&gt;, storage_fund: <a href="balance.md#0x2_balance_Balance">balance::Balance</a>&lt;<a href="sui.md#0x2_sui_SUI">sui::SUI</a>&gt;, max_validator_candidate_count: u64, min_validator_stake: u64, storage_gas_price: u64)
<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="sui_system.md#0x2_sui_system_create">create</a>(chain_id: u8, validators: <a href="">vector</a>&lt;<a href="validator.md#0x2_validator_Validator">validator::Validator</a>&gt;, sui_supply: <a href="balance.md#0x2_balance_Supply">balance::Supply</a>&lt;<a href="sui.md#0x2_sui_SUI">sui::SUI</a>&gt;, storage_fund: <a href="balance.md#0x2_balance_Balance">balance::Balance</a>&lt;<a href="sui.md#0x2_sui_SUI">sui::SUI</a>&gt;, max_validator_candidate_count: u64, min_validator_stake: u64, storage_gas_price: u64, next_epoch_stake_subsidy: u64)
</code></pre>


Expand All @@ -253,6 +279,7 @@ This function will be called only once in genesis.
max_validator_candidate_count: u64,
min_validator_stake: u64,
storage_gas_price: u64,
next_epoch_stake_subsidy: u64,
) {
<b>assert</b>!(chain_id &gt;= 1 && chain_id &lt;= 127, 1);
<b>let</b> validators = <a href="validator_set.md#0x2_validator_set_new">validator_set::new</a>(validators);
Expand All @@ -272,6 +299,7 @@ This function will be called only once in genesis.
},
reference_gas_price,
validator_report_records: <a href="vec_map.md#0x2_vec_map_empty">vec_map::empty</a>(),
next_epoch_stake_subsidy,
};
<a href="transfer.md#0x2_transfer_share_object">transfer::share_object</a>(state);
}
Expand Down Expand Up @@ -811,6 +839,10 @@ gas coins.
<b>let</b> storage_reward = <a href="balance.md#0x2_balance_create_staking_rewards">balance::create_staking_rewards</a>(storage_charge);
<b>let</b> computation_reward = <a href="balance.md#0x2_balance_create_staking_rewards">balance::create_staking_rewards</a>(computation_charge);

// Include <a href="stake.md#0x2_stake">stake</a> subsidy in the rewards given out <b>to</b> validators and delegators.
<b>let</b> stake_subsidy = <a href="balance.md#0x2_balance_increase_supply">balance::increase_supply</a>(&<b>mut</b> self.sui_supply, self.next_epoch_stake_subsidy);
<a href="balance.md#0x2_balance_join">balance::join</a>(&<b>mut</b> computation_reward, stake_subsidy);

<b>let</b> delegation_stake = <a href="validator_set.md#0x2_validator_set_total_delegation_stake">validator_set::total_delegation_stake</a>(&self.validators);
<b>let</b> validator_stake = <a href="validator_set.md#0x2_validator_set_total_validator_stake">validator_set::total_validator_stake</a>(&self.validators);
<b>let</b> storage_fund_balance = <a href="balance.md#0x2_balance_value">balance::value</a>(&self.storage_fund);
Expand Down Expand Up @@ -856,6 +888,9 @@ gas coins.
<b>assert</b>!(<a href="balance.md#0x2_balance_value">balance::value</a>(&self.storage_fund) &gt;= storage_rebate, 0);
<a href="balance.md#0x2_balance_destroy_storage_rebates">balance::destroy_storage_rebates</a>(<a href="balance.md#0x2_balance_split">balance::split</a>(&<b>mut</b> self.storage_fund, storage_rebate));

// Update the amount of subsidy <b>to</b> be given out in the next epoch.
<a href="sui_system.md#0x2_sui_system_update_stake_subsidy_amount">update_stake_subsidy_amount</a>(self, new_epoch);

// Validator reports are only valid for the epoch.
// TODO: or do we want <b>to</b> make it persistent and validators have <b>to</b> explicitly change their scores?
self.validator_report_records = <a href="vec_map.md#0x2_vec_map_empty">vec_map::empty</a>();
Expand All @@ -879,6 +914,35 @@ Total supply of SUI shouldn't change.



</details>

<a name="0x2_sui_system_update_stake_subsidy_amount"></a>

## Function `update_stake_subsidy_amount`



<pre><code><b>fun</b> <a href="sui_system.md#0x2_sui_system_update_stake_subsidy_amount">update_stake_subsidy_amount</a>(self: &<b>mut</b> <a href="sui_system.md#0x2_sui_system_SuiSystemState">sui_system::SuiSystemState</a>, new_epoch: u64)
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>fun</b> <a href="sui_system.md#0x2_sui_system_update_stake_subsidy_amount">update_stake_subsidy_amount</a>(self: &<b>mut</b> <a href="sui_system.md#0x2_sui_system_SuiSystemState">SuiSystemState</a>, new_epoch: u64) {
// Decrease the subsidy amount only when the current period ends.
<b>if</b> (new_epoch % <a href="sui_system.md#0x2_sui_system_STAKE_SUBSIDY_PERIOD_LENGTH">STAKE_SUBSIDY_PERIOD_LENGTH</a> == 0) {
<b>let</b> decrease_amount = (self.next_epoch_stake_subsidy <b>as</b> u128)
* <a href="sui_system.md#0x2_sui_system_STAKE_SUBSIDY_DECREASE_RATE">STAKE_SUBSIDY_DECREASE_RATE</a> / <a href="sui_system.md#0x2_sui_system_BASIS_POINT_DENOMINATOR">BASIS_POINT_DENOMINATOR</a>;
self.next_epoch_stake_subsidy = self.next_epoch_stake_subsidy - (decrease_amount <b>as</b> u64)
};
}
</code></pre>



</details>

<a name="0x2_sui_system_epoch"></a>
Expand Down
4 changes: 4 additions & 0 deletions crates/sui-framework/sources/governance/genesis.move
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ module sui::genesis {
/// Initial storage gas price
const INIT_STORAGE_GAS_PRICE: u64 = 1;

/// Stake subisidy to be given out in the very first epoch. Placeholder value.
const INIT_STAKE_SUBSIDY_AMOUNT: u64 = 1000000;

/// This function will be explicitly called once at genesis.
/// It will create a singleton SuiSystemState object, which contains
/// all the information we need in the system.
Expand Down Expand Up @@ -95,6 +98,7 @@ module sui::genesis {
INIT_MAX_VALIDATOR_COUNT,
INIT_MIN_VALIDATOR_STAKE,
INIT_STORAGE_GAS_PRICE,
INIT_STAKE_SUBSIDY_AMOUNT,
);
}
}
25 changes: 25 additions & 0 deletions crates/sui-framework/sources/governance/sui_system.move
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ module sui::sui_system {
/// them. If a validator has never been reported they don't have an entry in this map.
/// This map resets every epoch.
validator_report_records: VecMap<address, VecSet<address>>,
/// The amount of stake subsidies to be given out in the next epoch, updated at
/// epoch boundaries.
next_epoch_stake_subsidy: u64,
}

// Errors
Expand All @@ -72,6 +75,10 @@ module sui::sui_system {

const BASIS_POINT_DENOMINATOR: u128 = 10000;

// Placeholder numbers for stake subsidies.
const STAKE_SUBSIDY_DECREASE_RATE: u128 = 1000; // in basis point
const STAKE_SUBSIDY_PERIOD_LENGTH: u64 = 30; // in number of epochs

// ==== functions that can only be called by genesis ====

/// Create a new SuiSystemState object and make it shared.
Expand All @@ -84,6 +91,7 @@ module sui::sui_system {
max_validator_candidate_count: u64,
min_validator_stake: u64,
storage_gas_price: u64,
next_epoch_stake_subsidy: u64,
) {
assert!(chain_id >= 1 && chain_id <= 127, 1);
let validators = validator_set::new(validators);
Expand All @@ -103,6 +111,7 @@ module sui::sui_system {
},
reference_gas_price,
validator_report_records: vec_map::empty(),
next_epoch_stake_subsidy,
};
transfer::share_object(state);
}
Expand Down Expand Up @@ -367,6 +376,10 @@ module sui::sui_system {
let storage_reward = balance::create_staking_rewards(storage_charge);
let computation_reward = balance::create_staking_rewards(computation_charge);

// Include stake subsidy in the rewards given out to validators and delegators.
let stake_subsidy = balance::increase_supply(&mut self.sui_supply, self.next_epoch_stake_subsidy);
balance::join(&mut computation_reward, stake_subsidy);

let delegation_stake = validator_set::total_delegation_stake(&self.validators);
let validator_stake = validator_set::total_validator_stake(&self.validators);
let storage_fund_balance = balance::value(&self.storage_fund);
Expand Down Expand Up @@ -412,6 +425,9 @@ module sui::sui_system {
assert!(balance::value(&self.storage_fund) >= storage_rebate, 0);
balance::destroy_storage_rebates(balance::split(&mut self.storage_fund, storage_rebate));

// Update the amount of subsidy to be given out in the next epoch.
update_stake_subsidy_amount(self, new_epoch);

// Validator reports are only valid for the epoch.
// TODO: or do we want to make it persistent and validators have to explicitly change their scores?
self.validator_report_records = vec_map::empty();
Expand All @@ -423,6 +439,15 @@ module sui::sui_system {
== old(balance::supply_value(self.sui_supply));
}

fun update_stake_subsidy_amount(self: &mut SuiSystemState, new_epoch: u64) {
// Decrease the subsidy amount only when the current period ends.
if (new_epoch % STAKE_SUBSIDY_PERIOD_LENGTH == 0) {
let decrease_amount = (self.next_epoch_stake_subsidy as u128)
* STAKE_SUBSIDY_DECREASE_RATE / BASIS_POINT_DENOMINATOR;
self.next_epoch_stake_subsidy = self.next_epoch_stake_subsidy - (decrease_amount as u64)
};
}

/// Return the current epoch number. Useful for applications that need a coarse-grained concept of time,
/// since epochs are ever-increasing and epoch changes are intended to happen every 24 hours.
public fun epoch(self: &SuiSystemState): u64 {
Expand Down
3 changes: 2 additions & 1 deletion crates/sui-framework/tests/governance_test_utils.move
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ module sui::governance_test_utils {
balance::create_for_testing<SUI>(storage_fund_amount), // storage_fund
1024, // max_validator_candidate_count
0, // min_validator_stake
1, //storage_gas_price
1, // storage_gas_price
0, // stake subsidy
)
}

Expand Down
6 changes: 6 additions & 0 deletions crates/sui-open-rpc/spec/openrpc.json
Original file line number Diff line number Diff line change
Expand Up @@ -5082,6 +5082,7 @@
"chain_id",
"epoch",
"info",
"next_epoch_stake_subsidy",
"parameters",
"reference_gas_price",
"storage_fund",
Expand All @@ -5101,6 +5102,11 @@
"info": {
"$ref": "#/components/schemas/UID"
},
"next_epoch_stake_subsidy": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
},
"parameters": {
"$ref": "#/components/schemas/SystemParameters"
},
Expand Down
1 change: 1 addition & 0 deletions crates/sui-types/src/sui_system_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ pub struct SuiSystemState {
pub parameters: SystemParameters,
pub reference_gas_price: u64,
pub validator_report_records: VecMap<SuiAddress, VecSet<SuiAddress>>,
pub next_epoch_stake_subsidy: u64,
// TODO: Use getters instead of all pub.
}

Expand Down
1 change: 1 addition & 0 deletions crates/test-utils/src/sui_system_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,6 @@ pub fn test_sui_system_state(epoch: EpochId, validators: Vec<Validator>) -> SuiS
},
reference_gas_price: 1,
validator_report_records: VecMap { contents: vec![] },
next_epoch_stake_subsidy: 0,
}
}

0 comments on commit 16b1a26

Please sign in to comment.