Skip to content

Commit

Permalink
Merge pull request #268 from eosnetworkfoundation/staking-docs
Browse files Browse the repository at this point in the history
Staking docs
  • Loading branch information
nsjames authored Nov 12, 2024
2 parents 5eda21e + c5019e7 commit 6f5a92d
Show file tree
Hide file tree
Showing 11 changed files with 450 additions and 0 deletions.
Binary file added images/blocksec_eos_rex_v1.0-signed.pdf
Binary file not shown.
Binary file added images/diagram_bps_multisig.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/diagram_rex_inflows.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/diagram_staking_contract_flow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/diagram_user_token_flow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 41 additions & 0 deletions native/60_advanced-topics/30_staking/01_overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
title: Overview
---

<head>
<title>Staking Overview</title>
</head>

EOS Staking is a system-level contract that allows users to stake their EOS tokens to
receive rewards from the network.

## Lockup periods

When you stake your EOS tokens you lock them up for a certain period of time.

The minimum lockup period is 21 days, but that period could be longer depending on when
you as the user decide to unstake your tokens, as the lockup period only starts when you unstake.

Otherwise, the lockup period is indefinite.

## Accounting token

When you stake your EOS tokens you get a token called REX in return.
REX is a non-transferable token that represents the amount of value you have staked.
The conversion rate between EOS and REX is dynamic and goes up as more staking rewards are
distributed into the rewards pool.

The value of REX never decreases, only increases.

## Rewards

The rewards from staking originate from a pre-allocated bucket of EOS tokens that are
designated for staking rewards and aimed at incentivizing users to stake their tokens,
growing and securing the network.

## Liquid Staking

EOS Staking is **not** a liquid staking protocol, meaning that you cannot trade your REX tokens or restake them
in other protocols. Once you stake your EOS tokens and receive REX tokens in return, you cannot trade them or
use them in any other way than to unstake them and receive EOS tokens back directly from the EOS Staking protocol.

249 changes: 249 additions & 0 deletions native/60_advanced-topics/30_staking/10_contracts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
---
title: Contracts
---

<head>
<title>Staking Contracts</title>
</head>

There are a few different contracts involved in EOS staking.

1. `eosio.system` - The system and staking contract.
2. `eosio.reward` - An intermediate reward dispersal contract.
3. `eosio.rex` - Account that holds all funds in the staking protocol.

## eosio.system

The system contract is wider than just staking and controls the entire EOS network with
capabilities like account creation, chain governance, and resource management.

The staking portions of the system contract are responsible for managing the staking
and unstaking of EOS tokens, as well as the distribution of rewards from the pre-allocated
staking rewards pool.

![Staking Contract Flow](/images/diagram_staking_contract_flow.png)

### Depositing Funds

In order to use EOS inside the staking portion of the system contract, you need to deposit them first.

```cpp
void deposit( const name& owner, const asset& amount )
```
This will transfer your funds to the `eosio.rex` account and register them as deposited into the staking protocol.
This will **not** stake them for you yet though, they are simply held within the protocol.
> **Parameters**
> The parameter `owner` is the account that is depositing the funds.
### Staking Deposited Funds
Once you have deposited funds into the staking protocol, you can stake them to receive rewards.
```cpp
void buyrex( const name& from, const asset& amount )
```

This will stake the funds that you have deposited into the staking protocol and issue you REX tokens in return.


### Staking Funds From Voting Rights

On EOS you can have your EOS staked as voting rights. You may also use those funds as a source for staking.

```cpp
void unstaketorex( const name& owner, const name& receiver, const asset& from_net, const asset& from_cpu )
```
This will move your voting rights staked funds into rewards staked funds, and issue you REX tokens in return.
You will still retain your voting rights.
> **Note**
> All staked funds within the staking protocol have voting rights attached to them.
### Unstaking Funds
```cpp
void mvfrsavings( const name& owner, const asset& rex )
```

This will move funds out of eternally locked "savings" account and begin the 21 day unstaking period. Any funds you
move out of that savings account within the same day will be attributed to the same unstaking bucket and mature within
the same 21-day period.

### Withdrawing Funds

Once the 21-day unstaking/maturation period has finished, you can sell your position and withdraw your funds.
You will need to do this in two steps.

```cpp
void sellrex( const name& from, const asset& rex )
```
This action will convert your REX tokens back into EOS and register them as available to withdraw.
```cpp
void withdraw( const name& owner, const asset& amount )
```

This action will withdraw your EOS tokens from the staking protocol and transfer them to your account.


> **Note**
> Any action you take within the staking protocol once a 21-day unstaking period has finished will trigger an
> automatic `sellrex` on your fully matured REX tokens. This will convert them back into EOS and register them as
> available to withdraw.
### Tables

The system contract has a few tables that are relevant to staking.

#### rexbal

[The `rexbal` table](https://eosauthority.com/account/eosio?network=eos&scope=eosio&table=rexbal&limit=10&index_position=1&key_type=i64&reverse=0&mode=contract&sub=tables) holds information about staked balances for users.

- `version`
- `owner`
- `vote_stake`
- `rex_balance` - the amount of REX owned
- `matured_rex` - matured REX available for selling
- `rex_maturities` - An array of maturity dates and amounts

#### rexfund

[The `rexfund` table](https://eosauthority.com/account/eosio?network=eos&scope=eosio&table=rexfund&limit=10&index_position=1&key_type=i64&reverse=0&mode=contract&sub=tables&lower_bound=)
holds information about the deposited but unstaked EOS funds for users.

- `version`
- `owner`
- `balance` - the amount of EOS deposited

#### rexmaturity

[The `rexmaturity` table](https://eosauthority.com/account/eosio?network=eos&scope=eosio&table=rexmaturity&limit=10&index_position=1&key_type=i64&reverse=0&mode=contract&sub=tables)
holds information about the maturity dates of REX tokens for users.

- `num_of_maturity_buckets` - The number of days until a position fully matures
- `sell_matured_rex` - A flag that indicates if to sell matured positions on any action
- `buy_rex_to_savings` - A flag that indicates if staked funds go directly to savings or not

#### rexpool

[The `rexpool` table](https://eosauthority.com/account/eosio?network=eos&scope=eosio&table=rexpool&limit=10&index_position=1&key_type=i64&reverse=0&mode=contract&sub=tables)
holds information about the staking pool.

- `version`
- `total_lent` - total amount of EOS in open rex_loans
- `total_unlent` - total amount of EOS available to be lent (connector)
- `total_rent` - fees received in exchange for lent (connector)
- `total_lendable` - total amount of EOS that have been lent (total_unlent + total_lent)
- `total_rex` - total number of REX shares allocated to contributors to total_lendable
- `namebid_proceeds` the amount of EOS to be transferred from namebids to REX pool
- `loan_num` increments with each new loan

This is useful if you want to calculate the price of EOS vs REX.

```typescript
static convertEosToRex(eos:number){
const pool = get(rexpool);
if(!pool) return 0;
const S0 = parseFloat(pool.total_lendable.split(' ')[0]);
const S1 = S0 + eos;
const R0 = parseFloat(pool.total_rex.split(' ')[0]);
const R1 = (S1 * R0) / S0;
return parseFloat(parseFloat((R1 - R0).toString()).toFixed(4));
}

static convertRexToEos(rex:number){
const pool = get(rexpool);
if(!pool) return 0;
const S0 = parseFloat(pool.total_lendable.split(' ')[0]);
const R0 = parseFloat(pool.total_rex.split(' ')[0]);
const R1 = R0 + rex;
const S1 = (S0 * R1) / R0;
return parseFloat(parseFloat((S1 - S0).toString()).toFixed(4));
}
```

If you'd like to view full code for this example, [see here](https://github.com/eosnetworkfoundation/rex-staking-portal/blob/6f1297bbb5cc5e4d1e39ac5e52e815ea69a29803/src/lib/wharf.ts#L142-L143).

#### rexretpool

[The `rexretpool` table](https://eosauthority.com/account/eosio?network=eos&scope=eosio&table=rexretpool&limit=10&index_position=1&key_type=i64&reverse=0&mode=contract&sub=tables)
holds information about the return pool for REX tokens.

- `version`
- `last_dist_time` - the last time proceeds from renting, ram fees, and name bids were added to the rex pool
- `pending_bucket_time` - timestamp of the pending 12-hour return bucket
- `oldest_bucket_time` - cached timestamp of the oldest 12-hour return bucket
- `pending_bucket_proceeds` proceeds in the pending 12-hour return bucket,
- `current_rate_of_increase` the current rate per dist_interval at which proceeds are added to the rex pool,
- `proceeds` the maximum amount of proceeds that can be added to the rex pool at any given time

## eosio.reward

The [reward contract](https://eosauthority.com/account/eosio.reward) ([see contract code](https://github.com/eosnetworkfoundation/eosio.reward)) is an intermediate contract
that is responsible for dispersing the rewards from the staking rewards tokenomics bucket to the various strategies
aimed at rewarding the EOS community.

It allows the EOS Network to define a [set of receivers](https://eosauthority.com/account/eosio.reward?mode=contract&sub=tables&network=eos&scope=eosio.reward&table=strategies&limit=10&index_position=1&key_type=i64&reverse=0)
that will receive rewards, and a weight for each receiver.

See the [inflows](./inflows) document for more information on how the reward contract is funded.

> **Note**
> Modifying strategies is controlled by the block producers and requires a 15/21 multisig to change.
### Adding or Updating Strategies

```cpp
void setstrategy( const name strategy, const uint16_t weight )
```
This action will set or update a strategy with a given weight. The weight is a percentage of the total rewards that
will be allocated to this strategy. For instance, if there are three strategies with weights of 1000, 2000, and 7000,
then the first strategy will receive 10% of the rewards, the second 20%, and the third 70%.
### Removing Strategies
```cpp
void delstrategy( const name strategy )
```

This will remove any strategy from the reward contract.



### Distributing Rewards

```cpp
void distribute()
```

Funds that have flowed into this contract since the last distribution will be distributed to the strategies based on their
weights. It is better to call this at a higher interval to make sure that any small amounts of funds are not lost to
rounding errors.

> **Note**
> Any account can call this action.



## eosio.rex

The [contract on the eosio.rex account](https://github.com/eosnetworkfoundation/eos-system-contracts/blob/8ecd1ac6d312085279cafc9c1a5ade6affc886da/contracts/eosio.system/src/rex.results.cpp#L1) is merely a record-keeping contract. Each of the actions
does nothing (no implmentation) and is only there to provide an identifiable record within the transactions stack that
can be tracked and filtered by external tooling such as history solutions or frontend SDKs that want more
information that normally would not be available (like the REX received for an amount of EOS in a `buyrex` action).

```cpp
void buyresult( const asset& rex_received ) { }
void sellresult( const asset& proceeds ) { }
void orderresult( const name& owner, const asset& proceeds ) { }
void rentresult( const asset& rented_tokens ) { }
```
As different actions trigger results on the `eosio.rex` account, it will add one of these identifiable records to the
transaction stack based on the calling action. For instance, if you call `buyrex`, you will see a `buyresult` record.
64 changes: 64 additions & 0 deletions native/60_advanced-topics/30_staking/20_token-flows.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
title: Token Flows
---

<head>
<title>Staking Token Flows</title>
</head>

The inflows to the EOS staking protocol travel through a few different contracts, each with their own responsibilities.
We will cover the contracts that are involved in the inflows to the staking protocol, as well as the origins of the funds.

## Tokenomics Change

[In May of 2024 the EOS network underwent a tokenomics change](https://eosnetwork.com/blog/eos-network-approves-tokenomics-proposal-ushering-in-a-new-era-for-eos/) that introduced a new bucket
of EOS tokens designated for staking rewards.

**250 million** EOS was set aside in this bucket to be emitted with a halving schedule every 4 years. Meaning that in
the first 4 years 125,000,000 EOS will be distributed as staking rewards (31,250,000 EOS per year), and in the next 4 years
62,500,000 EOS will be distributed as staking rewards (15,625,000 EOS per year), and so on.

Inflation for the chain was also shut off during that change, and the various buckets replaced that inflated EOS.
This means that instead of inflating the chain at a set rate of X% per year, the chain now distributes a percentage of the
pre-allocated reserved supply to various parts of the network, like staking rewards.

## Flow of Staking Rewards

Every time a block producer claims their rewards, they trigger a chain of events that results in the distribution of
various token allocations to target accounts.

![Staking Inflows](/images/diagram_rex_inflows.png)

The block producers claim rewards from the **System Contract**, which then flows EOS into their accounts, and
into the `eosio.saving` account that holds a contract which distributes EOS to **EOS Labs**, the **EOS Network
Foundation**, and the **Staking Rewards** buckets (these are configured in [the `eosio.saving` contract](https://eosauthority.com/account/eosio.saving?network=eos&scope=eosio.saving&table=config&limit=10&index_position=1&key_type=i64&reverse=0&mode=contract&sub=tables&action=claim#transactions)).

As the rewards flow into the `eosio.saving` account, they are immediately split up according to the distribution
configurations on that contract, which are set by a 15/21 multisig of the block producers and tallied into
[the `claimers` table](https://eosauthority.com/account/eosio.saving?network=eos&scope=eosio.saving&table=claimers&limit=10&index_position=1&key_type=i64&reverse=0&mode=contract&sub=tables&action=claim#transactions).

Once funds are available, each entity can claim their rewards by calling the `claim` action, which then sends
the funds to the account specified in the configuration.

In the case of the **Staking Rewards** bucket, the funds are sent to the `eosio.reward` contract, which sit in the
account until they are distributed to the various strategies that are configured there by an account calling the
`distribute` action.

When the `distribute` action is called, the funds aimed at EOS Staking are used in the [`donatetorex` action](https://github.com/eosnetworkfoundation/eos-system-contracts/blob/8ecd1ac6d312085279cafc9c1a5ade6affc886da/contracts/eosio.system/src/rex.cpp#L389)
back on the System Contract which adds those funds to the REX pools, and then sends the funds to `eosio.rex` for
accounting purposes.

These pathways and mechanisms allow all participants to clearly see the flow of EOS as it makes its way through the
chain's various contracts and accounts, and ensures that the funds are distributed according to the network's
governance decisions instead of being hardcoded into smart contract logic with low visibility and flexibility.

## Flow of User Tokens

![User token flow](/images/diagram_user_token_flow.png)

When a user stakes their EOS to the protocol staking system they are transferring their EOS tokens to the system
contract which then issues them REX tokens in return and forwards their EOS to the `eosio.rex` account for accounting
purposes.

Since the value of REX can never go down, the user is guaranteed to receive _at least_ the same amount of EOS back when
they unstake, sell, and withdraw their REX tokens.
Loading

0 comments on commit 6f5a92d

Please sign in to comment.