Skip to content

Commit

Permalink
okay, now getting the unintended file changes out of this PR, go back…
Browse files Browse the repository at this point in the history
… to master
  • Loading branch information
Barrie Byron committed Oct 25, 2021
1 parent a904357 commit 94dbc38
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 145 deletions.
38 changes: 12 additions & 26 deletions x/farming/spec/01_concepts.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,35 @@
<!-- order: 1 -->

# Concepts

## Farming Module

The `x/farming` Cosmos SDK module implements farming functionality that keeps track of staking and provides farming rewards to farmers. A primary use case of this module is to provide incentives for liquidity pool investors for their pool participation.
`x/farming` is a Cosmos SDK module that implements farming functionality that keeps track of the staking and provides farming rewards to farmers. A primary use case is to use this module to provide incentives for liquidity pool investors for their pool participation.

## Plans

There are two types of farming plans in the `farming` module:

### Public Farming Plan
There are two types of farming plans in the `farming` module as below.

A public farming plan can be created only through governance proposal. The proposal must be first agreed and passed before a public farming plan can be created.
### 1. Public Farming Plan

### Private Farming Plan
A public farming plan can only be created through governance proposal meaning that the proposal must be first agreed and passed in order to create a public plan.
### 2. Private Farming Plan

A private farming plan can be created with any account.

- The account address of the plan creator account is used as the `TerminationAddress`.
- To prevent spamming attacks, the `PlanCreationFee` fee must be paid on plan creation.
A private farming plan can be created with any account. The plan creator's account is used as `TerminationAddress`. There is a fee `PlanCreationFee` paid upon plan creation to prevent from spamming attack.

## Distribution Methods

There are two types of reward distribution methods in the `farming` module:

### Fixed Amount Plan
There are two types of distribution methods in the `farming` module as below.
### 1. Fixed Amount Plan

A `FixedAmountPlan` distributes a fixed amount of coins to farmers for every epoch day.
A `FixedAmountPlan` distributes fixed amount of coins to farmers for every epoch day. If the plan creators `FarmingPoolAddress` is depleted with distributing coins, then there is no more coins to distribute unless it is filled up again.

When the plan creator's `FarmingPoolAddress` is depleted, then there are no more coins to distribute until more coins are added to the account.
### 2. Ratio Plan

### Ratio Plan

A `RatioPlan` distributes coins to farmers by ratio distribution for every epoch day.

If the plan creator's `FarmingPoolAddress` is depleted, then there are no more coins to distribute until more coins are added to the account.
A `RatioPlan` distributes to farmers by ratio distribution for every epoch day. If the plan creators `FarmingPoolAddress` is depleted with distributing coins, then there is no more coins to distribute unless it is filled up with more coins.

## Accumulated Reward Calculation

In the farming module, farming rewards are calculated per epoch based on the distribution plan.

To calculate the rewards for a single farmer, take the total rewards for the epoch before the staking started, minus the current total rewards.

The farming module takes references from [F1 Fee Distribution](https://github.com/cosmos/cosmos-sdk/blob/master/docs/spec/fee_distribution/f1_fee_distr.pdf) that is used in the Cosmos SDK [x/distribution](https://github.com/cosmos/cosmos-sdk/blob/master/x/distribution/spec/01_concepts.md) module.
In farming module, farming rewards are calculated per epoch based on plans. The rewards for a single farmer can be calculated by taking the total rewards for the epoch before the staking started, minus the current total rewards. The farming module takes references from [F1 Fee Distribution](https://github.com/cosmos/cosmos-sdk/blob/master/docs/spec/fee_distribution/f1_fee_distr.pdf) that is used in Cosmos SDK [x/distribution](https://github.com/cosmos/cosmos-sdk/blob/master/x/distribution/spec/01_concepts.md) module.

### Accumulated Unit Reward

Expand Down
21 changes: 9 additions & 12 deletions x/farming/spec/02_state.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@

# State

The `farming` module keeps track of the staking and rewards states.
The farming module keeps track of the staking and rewards states.

## Plan Interface

The plan interface exposes methods to read and write standard farming plan information.

Note that all of these methods operate on a plan struct that confirms to the interface. In order to write the plan to the store, the plan keeper is required.
The plan interface exposes methods to read and write standard farming plan information. Note that all of these methods operate on a plan struct confirming to the interface and in order to write the plan to the store, the plan keeper will need to be used.

```go
// PlanI is an interface used to store plan records within state.
Expand Down Expand Up @@ -58,7 +56,7 @@ type PlanI interface {

## Base Plan

A base plan is the simplest and most common plan type that just stores all requisite fields directly in a struct.
A base plan is the simplest and most common plan type, which just stores all requisite fields directly in a struct.

```go
// BasePlan defines a base plan type. It contains all the necessary fields
Expand Down Expand Up @@ -113,7 +111,7 @@ const (
)
```

The parameters of the plan state are:
The parameters of the Plan state are:

- ModuleName, RouterKey, StoreKey, QuerierRoute: `farming`
- Plan: `0x11 | Id -> ProtocolBuffer(Plan)`
Expand All @@ -137,8 +135,7 @@ type Staking struct {
}
```

The parameters of the staking state are:

The parameters of the Staking state are:
- Staking: `0x21 | StakingCoinDenomLen (1 byte) | StakingCoinDenom | FarmerAddr -> ProtocolBuffer(Staking)`
- StakingIndex: `0x22 | FarmerAddrLen (1 byte) | FarmerAddr | StakingCoinDenom -> nil`

Expand All @@ -161,7 +158,7 @@ type TotalStakings struct {

## Historical Rewards

The `HistoricalRewards` struct holds the cumulative unit rewards for each epoch that are required for the reward calculation.
`HistoricalRewards` struct holds the cumulative unit rewards for each epoch which are needed for the reward calculation.

```go
type HistoricalRewards struct {
Expand All @@ -174,7 +171,7 @@ type HistoricalRewards struct {

## Outstanding Rewards

The `OutstandingRewards` struct holds outstanding (un-withdrawn) rewards for a staking denom.
`OutstandingRewards` struct holds outstanding(un-withdrawn) rewards for a staking denom.

```go
type OutstandingRewards struct {
Expand All @@ -186,7 +183,7 @@ type OutstandingRewards struct {

## Examples

An example of `FixedAmountPlan`:
An example of `FixedAmountPlan`

```json
{
Expand Down Expand Up @@ -230,7 +227,7 @@ An example of `FixedAmountPlan`:
}
```

An example of `RatioPlan`:
An example of `RatioPlan`

```json
{
Expand Down
44 changes: 20 additions & 24 deletions x/farming/spec/03_state_transitions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,11 @@

# State Transitions

This document describes the state transaction operations for the farming module.
This document describes the state transaction operations pertaining to the farming module.

## Plans

As stated in [Concepts](01_concepts.md), both public and private farming plans are available in the `farming` module:

- A public farming plan can be created only through governance proposal.
- A private farming plan can be created with any account.
## Plan

As stated in [01_concepts.md](01_concepts.md), there are public and private farming plans available in the `farming` module. Private plan can be created by any account whereas public plan can only be created through governance proposal.

```go
// PlanType enumerates the valid types of a plan.
Expand All @@ -30,35 +26,35 @@ const (

When a farmer stakes an amount of coins, the following state transitions occur:

- Reserves the amount of coins to the staking reserve pool account `StakingReservePoolAcc`
- Creates `QueuedStaking` object and stores the staking coins in `QueueStaking`, which then wait in a queue until the end of epoch to move to the `Staking` object
- Imposes more gas if the farmer already has `Staking` with the same coin denom. See [Parameters](07_params.md#DelayedStakingGasFee) for details.
- it reserves the amount of coins to the staking reserve pool account `StakingReservePoolAcc`
- it creates `QueuedStaking` object and stores the staking coins in `QueueStaking`, which are waiting in a queue until the end of epoch to move to `Staking` object
- it imposes more gas if the farmer already has `Staking` with the same coin denom(see [07_params.md](07_params.md#DelayedStakingGasFee) for details)

## Unstake

When a farmer unstakes an amount of coins, the following state transitions occur:

- Adds `Staking` and `QueueStaking` amounts to see if the unstaking amount is sufficient
- Automatically withdraws rewards for the coin denom that are accumulated over the last epochs
- Subtracts the unstaking amount of coins from `QueueStaking` first, and if not sufficient then subtracts from `Staking`
- Releases the unstaking amount of coins to the farmer
- it adds `Staking` and `QueueStaking` amounts to see if the unstaking amount is sufficient
- it automatically withdraws rewards for the coin denom which are accumulated over the last epochs
- it subtracts the unstaking amount of coins from `QueueStaking` first and if it is not sufficient then it subtracts from `Staking`
- it releases the unstaking amount of coins to the farmer

## Harvest (Reward Withdrawal)

- Calculates `CumulativeUnitRewards` in `HistoricalRewards` object in order to get the rewards for the staking coin denom that are accumulated over the last epochs
- Releases the accumulated rewards to the farmer if it is not zero and decreases the `OutstandingRewards`
- Sets `StartingEpoch` in `Staking` object
- it calculates `CumulativeUnitRewards` in `HistoricalRewards` object in order to get the rewards for the staking coin denom which are accumulated over the last epochs for the farmer
- it releases the accumulated rewards to the farmer if it is not zero and decreases the `OutstandingRewards`
- it sets `StartingEpoch` in `Staking` object

## Reward Allocation

If the sum of total calculated `EpochAmount` (or `EpochRatio` multiplied by the farming pool balance) exceeds the farming pool balance, then skip the reward allocation for that epoch.
If the sum of total calculated `EpochAmount` (or `EpochRatio` multiplied by the farming pool's balance) exceeds the farming pool's balance, then the reward allocation is skipped for that epoch.

For each [abci end block call](https://docs.cosmos.network/master/modules/staking/05_end_block.html), the operations to update the rewards allocation are:
Each abci end block call, the operations to update rewards allocation are to execute:

++ https://github.com/tendermint/farming/blob/69db071ce30b99617b8ba9bb6efac76e74cd100b/x/farming/keeper/reward.go#L363-L426

- Calculates rewards allocation information for the end of the current epoch depending on plan type `FixedAmountPlan` or `RatioPlan`
- Distributes total allocated coins from each plan’s farming pool address `FarmingPoolAddress` to the rewards reserve pool account `RewardsReserveAcc`
- Calculates staking coin weight for each denom in each plan and gets the unit rewards by denom
- Updates `HistoricalRewards` and `CurrentEpoch` based on the allocation information
- Deletes `QueueStaking` object after moving `QueueCoins` to `StakedCoins` in the `Staking` object
- it calculates rewards allocation information for the end of the current epoch depending on plan type `FixedAmountPlan` or `RatioPlan`
- it distributes total allocated coins from each plan’s farming pool address `FarmingPoolAddress` to the rewards reserve pool account `RewardsReserveAcc`
- it calculates staking coin weight for each denom in each plan and gets the unit rewards by denom
- it updates `HistoricalRewards` and `CurrentEpoch` based on the allocation information
- it deletes `QueueStaking` object after moving `QueueCoins` to `StakedCoins` in `Staking` object
46 changes: 8 additions & 38 deletions x/farming/spec/04_messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,11 @@

# Messages

Messages (Msg) are objects that trigger state transitions. Msgs are wrapped in transactions (Txs) that clients submit to the network. The Cosmos SDK wraps and unwraps `farming` module messages from transactions.
Messages (Msg) are objects that trigger state transitions. Msgs are wrapped in transactions (Txs) that clients submit to the network. The Cosmos SDK wraps and unwraps farming module messages from transactions.

## MsgCreateFixedAmountPlan

Anyone can create this private plan type message.

- A fixed amount plan distributes the amount of coins by a fixed amount that is defined in `EpochAmount`.
- Internally, `PrivatePlanFarmingPoolAddress` is generated and assigned to the plan.

The creator must query the plan and send the amount of coins to the farming pool address so that the plan distributes as intended.

**Note:** The `PlanCreationFee` must be paid on plan creation to prevent spamming attacks.
This is one of the private plan type messages that anyone can create. A fixed amount plan plans to distribute amount of coins by a fixed amount defined in `EpochAmount`. Internally, `PrivatePlanFarmingPoolAddress` is generated and assigned to the plan and the creator should query the plan and send amount of coins to the farming pool address so that the plan distributes as intended. Note that there is a fee `PlanCreationFee` paid upon plan creation to prevent from spamming attack.

```go
type MsgCreateFixedAmountPlan struct {
Expand All @@ -28,17 +21,7 @@ type MsgCreateFixedAmountPlan struct {

## MsgCreateRatioPlan

Anyone can create this private plan type message.

- A ratio plan plans to distribute amount of coins by ratio defined in `EpochRatio`.
- Internally, `PrivatePlanFarmingPoolAddress` is generated and assigned to the plan.

The creator must query the plan and send the amount of coins to the farming pool address so that the plan distributes as intended.

For a ratio plan, whichever coins the farming pool address has in balances are used every epoch.

**Note:** The `PlanCreationFee` must be paid on plan creation to prevent spamming attacks.

This is one of the private plan type messages that anyone can create. A ratio plan plans to distribute amount of coins by ratio defined in `EpochRatio`. Internally, `PrivatePlanFarmingPoolAddress` is generated and assigned to the plan and the creator should query the plan and send amount of coins to the farming pool address so that the plan distributes as intended. For a ratio plan, whichever coins that the farming pool address has in balances are used every epoch. Note that there is a fee `PlanCreationFee` paid upon plan creation to prevent from spamming attack.

```go
type MsgCreateRatioPlan struct {
Expand All @@ -53,7 +36,7 @@ type MsgCreateRatioPlan struct {

## MsgStake

A farmer must have sufficient amount of coins to stake. If a farmer stakes coin or coins that are defined in staking the coin weights of plans, then the farmer becomes eligible to receive rewards.
A farmer must have sufficient amount of coins to stake. If a farmer stakes coin(s) that are defined in staking coin weights of plans, then the farmer becomes eligible to receive rewards.

```go
type MsgStake struct {
Expand All @@ -64,11 +47,7 @@ type MsgStake struct {

## MsgUnstake

A farmer must have some staking coins to trigger this message.

In contrast to the Cosmos SDK [staking](https://github.com/cosmos/cosmos-sdk/blob/master/x/staking/spec/01_state.md) module, there is no concept of an unbonding period where some time is required to unstake coins.

All of the accumulated farming rewards are automatically withdrawn to the farmer after an unstaking event is triggered.
A farmer must have some staking coins to trigger this message. Unlike Cosmos SDK's [staking](https://github.com/cosmos/cosmos-sdk/blob/master/x/staking/spec/01_state.md) module, there is no concept of unbonding period that requires some time to unstake coins. All the accumulated farming rewards are automatically withdrawn to the farmer once unstaking event is triggered.

```go
type MsgUnstake struct {
Expand All @@ -79,9 +58,7 @@ type MsgUnstake struct {

## MsgHarvest

The farming rewards are automatically accumulated, but they are not automatically distributed.

A farmer must harvest their farming rewards. This mechanism is similar to the Cosmos SDK [distribution](https://github.com/cosmos/cosmos-sdk/blob/master/x/distribution/spec/01_concepts.md) module.
The farming rewards are automatically accumulated, but they are not automatically distributed. A farmer should harvest their farming rewards. This mechanism is similar with Cosmos SDK's [distribution](https://github.com/cosmos/cosmos-sdk/blob/master/x/distribution/spec/01_concepts.md) module.

```go
type MsgHarvest struct {
Expand All @@ -92,15 +69,8 @@ type MsgHarvest struct {

## MsgAdvanceEpoch

For testing purposes only, this custom message is used to advance epoch by 1.

To enable this message, you must build the `farmingd` binary:

```sh
make install-testing
```

When you send the `MsgAdvanceEpoch` message to the network, epoch increases by 1.
This is custom message to advance epoch by one for the testing purpose. Enabling this message is possibly only if you build `farmingd` binary with `make install-testing` command.
When you send `MsgAdvanceEpoch` to the network, it increases epoch by 1.

```go
type MsgAdvanceEpoch struct {
Expand Down
20 changes: 1 addition & 19 deletions x/farming/spec/05_end_block.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,6 @@
<!-- order: 6 -->
# End-Block

At each end-block call, the `farming` module operations are specified to execute.

++ https://github.com/tendermint/farming/blob/69db071ce3/x/farming/abci.go#L13-L46

At the end of each block:

- Terminates plans if their end time has passed over the current block time.

- Sends all remaining coins in the plan's farming pool account `FarmingPoolAddress` to the termination address `TerminationAddress`.
- Marks the plan as terminated by making `Terminated` true.
- Allocates farming rewards.
- Processes `QueueStaking` to be staked.
- Sets `LastEpochTime` to track in case of chain upgrade.

## Internal state CurrentEpochDays

Although a global parameter `NextEpochDays` exists, the farming module uses an internal state `CurrentEpochDays` to prevent impacting rewards allocation.

Suppose `NextEpochDays` is 7 and it is proposed to change the value to 1 through governance proposal. Although the proposal is passed, rewards allocation must continue to proceed with 7, not 1.

To explore internal state `CurrentEpochDays` in more detail, see the [test code](https://github.com/tendermint/farming/blob/69db071ce3/x/farming/abci_test.go#L12-L64).
At the end of each block, it terminates plans that their end time has passed over the current block time. It sends all remaining coins in the plan's farming pool account `FarmingPoolAddress` to the termination address `TerminationAddress` and mark the plan as terminated by making `Terminated` true. A global parameter `NextEpochDays` is there but the farming module uses an internal state `CurrentEpochDays` to prevent from a case where it may affect the rewards allocation. Suppose `NextEpochDays` is 7 and it is proposed to change the value to 1 through governance proposal. Although the proposal is passed, rewards allocation should continue to proceed with 7, not 1. The [test code](https://github.com/tendermint/farming/blob/69db071ce3/x/farming/abci_test.go#L12-L64) is available for you if you want to understand it in more detail. Then it allocates farming rewards, processes `QueueStaking` to be staked, and sets `LastEpochTime` to keep in track in case of the chain upgrade.
4 changes: 2 additions & 2 deletions x/farming/spec/06_events.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Events

The `farming` module emits the following events:
The farming module emits the following events:

## EndBlocker

Expand Down Expand Up @@ -82,4 +82,4 @@ The `farming` module emits the following events:

### MsgAdvanceEpoch

The `MsgAdvanceEpoch` message is for testing purposes only and requires that you build the `farmingd` binary. See [MsgAdvanceEpoch](04_messages.md#MsgAdvanceEpoch).
This message is for testing purpose. It is only available when you build `farmingd` binary by `make install-testing` command.
Loading

0 comments on commit 94dbc38

Please sign in to comment.