diff --git a/docs/OpenBrush/smart-contracts/PSP22/Extensions/votes.md b/docs/OpenBrush/smart-contracts/PSP22/Extensions/votes.md new file mode 100644 index 0000000..95bf6fa --- /dev/null +++ b/docs/OpenBrush/smart-contracts/PSP22/Extensions/votes.md @@ -0,0 +1,48 @@ +--- +sidebar_position: 1 +title: PSP22 Votes +--- +This feature provides a way to use your token as a voting power. You can use it in your [Governor](../../governance/governor.md) contract. +To cast a vote in [Governor](../../governance/governor.md) contract you need to have some amount of tokens and delegate them to be used for voting. +The more tokens you have, the more voting power you have. The extension implements the [Votes](https://github.com/Brushfam/openbrush-contracts/tree/main/contracts/src/governance/utils/votes) trait which provides the ability to delegate tokens from one account to another for voting, +check the number of votes for a proposal, and check the number of votes delegated by a user. +It's a required tool to create a [Governor](../../governance/governor.md) contract. +You can check the [Compound’s Governor Alpha & Bravo](https://docs.compound.finance/v2/governance/) documentation for more information about governance. + +This page describes how to create your own [PSP22Votes](/) contract. +## Step 1: Import default implementation + +First, you should implement basic version of [PSP22](../psp22.md). + +With [default `Cargo.toml`](../../overview.md/#the-default-toml-of-your-project-with-openbrush), +you need to enable `governance` and `psp22` feature. Also, you need to use the implementation macro +for PSP22Votes and Nonces: +```rust +#[openbrush::implementation(..., PSP22Votes, Nonces, ...)] +#[openbrush::contract] +pub mod your_contract { + ... +} +``` + +You can check [this section](../../overview.md/#reuse-implementation-of-traits-from-openbrush) to understand how it works. + + +## Step 2: Set up your Storage +You need to add a storage field of type `votes::Data`, which will store the information about delegations, the number of votes at a certain time, and the total number of votes, at a certain time. +Also, you will need a storage field of type `nonces::Data`, which stores the number of nonces for each account. Nonce is a number that is incremented each time a user delegates tokens to another account. +```rust +#[ink(storage)] +#[derive(Default, Storage)] +pub struct Contract { + ... + #[storage_field] + votes: votes::Data, + #[storage_field] + nonces: nonces::Data, + ... +} +``` +That's it! Now we have a [PSP22Votes](/) contract. You can use it in your [Governor](../../governance/governor.md) contract to count your votes. + +You can check an example of the usage of [PSP22Votes](https://github.com/Brushfam/openbrush-contracts/tree/main/examples/psp22_extensions/votes) and [Governor](https://github.com/Brushfam/openbrush-contracts/tree/main/examples/governance/governor) diff --git a/docs/OpenBrush/smart-contracts/governance/Extensions/counting.md b/docs/OpenBrush/smart-contracts/governance/Extensions/counting.md new file mode 100644 index 0000000..67efc9a --- /dev/null +++ b/docs/OpenBrush/smart-contracts/governance/Extensions/counting.md @@ -0,0 +1,41 @@ +--- +sidebar_position: 1 +title: GovernorCounting +--- +This extension gives Governor contract the ability to manage and count votes of the contract. +You can see if a user has voted for a proposal, and get the number of votes for a proposal. +Also, this extension allows you to count your votes when you cast them, to see when the quorum is reached, and when the voting succeeds. +You can check the [Compound’s Governor Alpha & Bravo](https://docs.compound.finance/v2/governance/) documentation for more information about governance. + +This page describes how to connect [GovernorCounting](/) to [Governor](../governor.md) contract. + +## Step 1: Import default implementation + +With [default `Cargo.toml`](../../overview.md/#the-default-toml-of-your-project-with-openbrush), +you need to enable `governance` feature. Also, you need to use implementation macro +for GovernorCounting: +```rust +#[openbrush::implementation(..., GovernorCounting, ...)] +#[openbrush::contract] +pub mod your_contract { + ... +} +``` +You can check [this section](../../overview.md/#reuse-implementation-of-traits-from-openbrush) to understand how it works. + +## Step 2: Add GovernorCounting field in your Storage +Add a storage field of type `governor_counting::Data`, which stores the number of votes for all proposals, and information about whether a user has voted for a proposal. +```rust +#[ink(storage)] +#[derive(Default, Storage)] +pub struct Contract { + ... + #[storage_field] + governor_counting: governor_counting::Data, + ... +} +``` + +That's it! Now you can use [GovernorCounting](/) extension in your [Governor](../governor.md) contract. + +You can check an example of the usage of [Governance](https://github.com/Brushfam/openbrush-contracts/tree/main/examples/governance/governor). diff --git a/docs/OpenBrush/smart-contracts/governance/Extensions/quorum.md b/docs/OpenBrush/smart-contracts/governance/Extensions/quorum.md new file mode 100644 index 0000000..92ce624 --- /dev/null +++ b/docs/OpenBrush/smart-contracts/governance/Extensions/quorum.md @@ -0,0 +1,64 @@ +--- +sidebar_position: 1 +title: GovernorQuorum +--- +This extension gives Governor contract the ability to manage how quorum is calculated. +There are two parameters that affect quorum calculation: `quorum_numerator` and `quorum_denominator`. +Quorum is calculated as `quorum_numerator * total_votes / quorum_denominator`. +Of course, the value of total votes is not constant, it changes with every vote. +So, the quorum calculates in specific moments of time. It is possible because all votes are stored in [checkpoints]() structure, +that is updated every time when a vote is created or changed. +You can check the [Compound’s Governor Alpha & Bravo](https://docs.compound.finance/v2/governance/) documentation for more information about governance. + +This page describes how to connect [GovernorQuorum](/) to [Governor](../governor.md) contract. + +## Step 1: Import default implementation + +With [default `Cargo.toml`](../../overview.md/#the-default-toml-of-your-project-with-openbrush), +you need to enable `governance` feature. Also, you need to use implementation macro +for GovernorQuorum: +```rust +#[openbrush::implementation(..., GovernorQuorum, ...)] +#[openbrush::contract] +pub mod your_contract { + ... +} +``` +You can check [that section](../../overview.md/#reuse-implementation-of-traits-from-openbrush) to understand how it works. + +## Step 2: Include GovernorQuorum initialization in constructor + +We need to initialize [GovernorQuorum](/) extension in the constructor of [Governor](../governor.md) contract. +We are setting an initial value of quorum numerator. It can be changed. For example, by voting. + +```rust +impl Contract { + #[ink(constructor)] + pub fn new( + token: AccountId, + voting_delay: u64, + voting_period: u64, + proposal_threshold: u128, + numerator: u128, + ) -> Self { + ... + instance._init_quorum_numerator(numerator).unwrap(); + ... + } +} +``` +## Step 3: Add GovernorQuorum field in your Storage +Add a storage field of type `governor_quorum::Data`, which stores the history of quorum numerator changes. +```rust +#[ink(storage)] +#[derive(Default, Storage)] +pub struct Contract { + ... + #[storage_field] + quorum: governor_quorum::Data, + ... +} +``` +That's it! Now you can use [GovernorQuorum](/) extension in your [Governor](../governor.md) contract. + +You can check an example of the usage of [Governance](https://github.com/Brushfam/openbrush-contracts/tree/main/examples/governance/governor). diff --git a/docs/OpenBrush/smart-contracts/governance/Extensions/settings.md b/docs/OpenBrush/smart-contracts/governance/Extensions/settings.md new file mode 100644 index 0000000..59298f3 --- /dev/null +++ b/docs/OpenBrush/smart-contracts/governance/Extensions/settings.md @@ -0,0 +1,65 @@ +--- +sidebar_position: 1 +title: GovernorSettings +--- +This extension gives Governor contract the ability to set and get settings of the contract. +With this extension, you can set and get voting delay(The time between proposing and vote starting), +voting period, proposal threshold(The amount of votes required to propose a proposal). +You can check the [Compound’s Governor Alpha & Bravo](https://docs.compound.finance/v2/governance/) documentation for more information about governance. + +This page describes how to connect [GovernorSettings](/) to [Governor](../governor.md) contract. + +## Step 1: Import default implementation + +With [default `Cargo.toml`](../../overview.md/#the-default-toml-of-your-project-with-openbrush), +you need to enable `governance` feature. Also, you need to use implementation macro +for GovernorSettings: +```rust +#[openbrush::implementation(..., GovernorSettings, ...)] +#[openbrush::contract] +pub mod your_contract { + ... +} +``` +You can check [this section](../../overview.md/#reuse-implementation-of-traits-from-openbrush) to understand how it works. +## Step 2: Include GovernorSettings initialization in constructor + +We need to initialize [GovernorSettings](/) extension in the constructor of [Governor](../governor.md) contract. +We are setting an initial value of voting delay, voting period, proposal threshold. It can be changed. For example, by voting. + +```rust +impl Contract { + #[ink(constructor)] + pub fn new( + token: AccountId, + voting_delay: u64, + voting_period: u64, + proposal_threshold: u128, + numerator: u128, + ) -> Self { + ... + instance + ._init_governor_settings(voting_delay, voting_period, proposal_threshold) + .unwrap(); + ... + } +} +``` +## Step 3: Add GovernorSettings field in your Storage +Add a storage field of type `governor_settings::Data`, which stores the values of voting delay, voting period, proposal threshold. +```rust +#[ink(storage)] +#[derive(Default, Storage)] +pub struct Contract { + ... + #[storage_field] + settings: governor_settings::Data, + ... +} +``` + + +That's it! Now you can use [GovernorSettings](/) extension in your [Governor](../governor.md) contract. + + +You can check an example of the usage of [Governance](https://github.com/Brushfam/openbrush-contracts/tree/main/examples/governance/governor). diff --git a/docs/OpenBrush/smart-contracts/governance/Extensions/votes.md b/docs/OpenBrush/smart-contracts/governance/Extensions/votes.md new file mode 100644 index 0000000..e18c5fd --- /dev/null +++ b/docs/OpenBrush/smart-contracts/governance/Extensions/votes.md @@ -0,0 +1,66 @@ +--- +sidebar_position: 1 +title: GovernorVotes +--- +This extension gives Governor contract the ability to communicate with [PSP22Votes](../../PSP22/Extensions/votes.md) token. +The main purpose of this extension is to provide a way to check how much voting power a voter has. +Also, it provides the ability to delegate tokens from one account to another for voting. +You can check the [Compound’s Governor Alpha & Bravo](https://docs.compound.finance/v2/governance/) documentation for more information about governance. + +This page describes how to connect [Governor](../governor.md) with [PSP22Votes](../../PSP22/Extensions/votes.md) token using [GovernorVotes](/) extension. + +## Step 1: Import default implementation + +With [default `Cargo.toml`](../../overview.md/#the-default-toml-of-your-project-with-openbrush), +you need to enable `governance` feature. Also, you need to use implementation macro +for GovernorVotes: +```rust +#[openbrush::implementation(..., GovernorVotes, ...)] +#[openbrush::contract] +pub mod your_contract { + ... +} +``` + +You can check [this section](../../overview.md/#reuse-implementation-of-traits-from-openbrush) to understand how it works. + +The main trait is `Governor`. + +## Step 2: Include GovernorVotes initialization in constructor + +We need to initialize [GovernorVotes](/) extension in the constructor of [Governor](../governor.md) contract with the address of [PSP22Votes](../../PSP22/Extensions/votes.md) token. + +```rust +impl Contract { + #[ink(constructor)] + pub fn new( + token: AccountId, + voting_delay: u64, + voting_period: u64, + proposal_threshold: u128, + numerator: u128, + ) -> Self { + ... + instance._init_governor_votes(token).unwrap(); + ... + } +} +``` +## Step 3: Add GovernorVotes field in your Storage +Add a storage field of type `governor_votes::Data`, which stores the AccountId of [PSP22Votes](../../PSP22/Extensions/votes.md) token. +```rust +#[ink(storage)] +#[derive(Default, Storage)] +pub struct Contract { + ... + #[storage_field] + governor_votes: governor_votes::Data, + ... +} +``` + + +That's it! Now you can use [GovernorVotes](/) extension in your [Governor](../governor.md) contract. + + +You can check an example of the usage of [Governance](https://github.com/Brushfam/openbrush-contracts/tree/main/examples/governance/governor). diff --git a/docs/OpenBrush/smart-contracts/governance/governor.md b/docs/OpenBrush/smart-contracts/governance/governor.md new file mode 100644 index 0000000..248e1fa --- /dev/null +++ b/docs/OpenBrush/smart-contracts/governance/governor.md @@ -0,0 +1,80 @@ +--- +sidebar_position: 1 +title: Governance +--- +This feature provides a governance mechanism. It allows token holders to vote on proposals and change the token's parameters. +Everybody who has enough votes can create a proposal to call a method of some contract with some arguments. Then token holders can vote for or against the proposal. +When the voting period ends, the proposal can be executed if the proposal status is `Succeeded` and the quorum is reached. +This example shows how you can use the implementation of [Governance](https://github.com/Brushfam/openbrush-contracts/tree/main/contracts/src/governance) token. +You can check the [Compound’s Governor Alpha & Bravo](https://docs.compound.finance/v2/governance/) documentation for more information about governance. + +## Step 1: Import default implementation + +With [default `Cargo.toml`](../overview.md/#the-default-toml-of-your-project-with-openbrush), +you need to enable `governance` feature. Also, you need to use implementation macro +for Governor and all required extensions: +```rust +#[openbrush::implementation(Governor, GovernorVotes, GovernorSettings, GovernorCounting, GovernorQuorum)] +#[openbrush::contract] +pub mod your_contract { + ... +} +``` +You can check [this section](../overview.md/#reuse-implementation-of-traits-from-openbrush) to understand how it works. + +## Step 2: Define constructor + +Define constructor where you initialize required extensions [GovernorVotes](Extensions/votes.md), [GovernorSettings](Extensions/settings.md) and [GovernorQuorum](Extensions/quorum.md). + +```rust +impl Contract { + #[ink(constructor)] + pub fn new( + token: AccountId, + voting_delay: u64, + voting_period: u64, + proposal_threshold: u128, + numerator: u128, + ) -> Self { + let mut instance = Self::default(); + + let caller = Self::env().caller(); + + instance._init_governor_votes(token).unwrap(); + instance + ._init_governor_settings(voting_delay, voting_period, proposal_threshold) + .unwrap(); + instance._init_quorum_numerator(numerator).unwrap(); + instance.mock_timestamp = Self::env().block_timestamp(); + + instance + } +} +``` +## Step 3: Set up your Storage +It should have all fields for [Governor](/) and required extensions: [GovernorVotes](Extensions/votes.md), [GovernorSettings](Extensions/settings.md), [GovernorCounting](Extensions/counting.md), [GovernorQuorum](Extensions/quorum.md). +```rust +#[ink(storage)] + #[derive(Default, Storage)] + pub struct Contract { + #[storage_field] + governor: governor::Data, + #[storage_field] + governor_counting: governor_counting::Data, + #[storage_field] + governor_votes: governor_votes::Data, + #[storage_field] + settings: governor_settings::Data, + #[storage_field] + quorum: governor_quorum::Data, + } +``` + + +## Step 4: Make your PSP22Voting contract + +Make your PSP22Voting contract which will be used for voting. You can use [PSP22Votes](../PSP22/Extensions/votes.md) for this purpose. +The AccountId of this token will then be used as a constructor parameter of this contract. You can check our [PSP22Votes](https://github.com/Brushfam/openbrush-contracts/tree/main/examples/psp22_extensions/votes) contract example. + + +You can check an example of the usage of [Governance](https://github.com/Brushfam/openbrush-contracts/tree/main/examples/governance/governor). diff --git a/docs/OpenBrush/smart-contracts/utils/checkpoints.md b/docs/OpenBrush/smart-contracts/utils/checkpoints.md new file mode 100644 index 0000000..5e17f37 --- /dev/null +++ b/docs/OpenBrush/smart-contracts/utils/checkpoints.md @@ -0,0 +1,54 @@ +--- +sidebar_position: 1 +title: Checkpoints +--- +This structure provides the ability to store and manage checkpoints. +It allows to make a snapshot of the state of the contract at a certain moment and restore it later. +To add your value to the checkpoint, you need to call the `push` method. It has two arguments: `key`(usually it's a timestamp) and `value`. +There are several methods to get the value from the checkpoint: +- `lower_lookup` - Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if there is none. +- `upper_lookup` - Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero if there is none. +- `upper_lookup_recent` - This is a variant of `upper_lookup` that is optimised to find "recent" checkpoint (checkpoints with high keys). +- `latest` - Returns the value in the most recent checkpoint, or 0 if there are no checkpoints. +- `latest_checkpoint` - Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value in the most recent checkpoint. + +This page describes how to use Checkpoints in your contract. For example, you want to save how total supply of your token changes over time. +Then you can use Checkpoints to do it. + +## Step 1: Import checkpoints module + +```rust +use openbrush::utils::checkpoints::Checkpoints; +``` + +## Step 2: Add field in your Storage, that uses Checkpoints +Then you need to add a field in your Storage, that uses Checkpoints. +```rust +#[ink(storage)] +#[derive(Default, Storage)] +pub struct Contract { + ... + #[storage_field] + total_supply_history: Checkpoints, + ... +} +``` + +## Step 3: Use Checkpoints in your contract +Modify all functions that change the value of total supply. For example, if you want to use Checkpoints to save the total supply of your token, you need to modify `_mint` function: +```rust +impl Contract { + ... + fn _mint(&mut self, to: &AccountId, amount: Balance) -> Result<(), Error> { + ... + self.total_supply_history.push(self.total_supply(), self.env().block_timestamp()); + ... + } + ... +} +``` + + +That's it! Now you can use [Checkpoints](/) structure in your contract. + +You can check an example of the usage of [Checkpoints](https://github.com/Brushfam/openbrush-contracts/tree/main/contracts/src/utils/checkpoints) in our [Votes](https://github.com/Brushfam/openbrush-contracts/tree/main/contracts/governance/utils/votes) implementation. diff --git a/docs/OpenBrush/smart-contracts/utils/nonces.md b/docs/OpenBrush/smart-contracts/utils/nonces.md new file mode 100644 index 0000000..c3a0fd4 --- /dev/null +++ b/docs/OpenBrush/smart-contracts/utils/nonces.md @@ -0,0 +1,31 @@ +~~--- +sidebar_position: 1 +title: Nonces +--- +This utility provides tracking nonces for each user. Nonces will only increment. +For example, you can use this utility to prevent replay attacks when you use signatures. +It has three main methods: `nonces` - that just returns the next unused nonce for the user, `use_nonce` - that marks the nonce as used and increment it, and `use_check_nonce` - that checks if the right nonce is used and marks it as used. +This page describes how to use [Nonces](/) in your contract. + +## Step 1: Import default implementation + +With [default `Cargo.toml`](../../overview.md/#the-default-toml-of-your-project-with-openbrush), +you need to enable `Nonces` feature, embed modules data structures and implement them via `#[openbrush::implementation]` macro +as described in [this section](../../overview.md/#reuse-implementation-of-traits-from-openbrush). + +## Step 2: Add Nonces field in your Storage +Add a storage field of type `governor_settings::Data`, which stores nonces Mapping, which stores the next unused nonce for each user. +```rust +#[ink(storage)] +#[derive(Default, Storage)] +pub struct Contract { + ... + #[storage_field] + nonces: nonces::Data, + ... +} +``` + +That's it! Now you can use [Nonces](/) in your contract. + +You can check an example of the usage of [Nonces](https://github.com/Brushfam/openbrush-contracts/tree/main/contracts/src/utils/nonces) in our [PSP22Votes](https://github.com/Brushfam/openbrush-contracts/tree/main/examples/psp22_extensions/votes) contract example.~~