-
Notifications
You must be signed in to change notification settings - Fork 289
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #86 from 0xPolygon/empieichO-docs-review
Update PoS docs - added new section
- Loading branch information
Showing
15 changed files
with
1,113 additions
and
4 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
In Polygon, validators stake their MATIC tokens as collateral to work for the security of the network, and in exchange for their service, earn rewards. | ||
|
||
To leverage Polygon's economics, you should either become a validator or a delegator. | ||
|
||
To be a validator, you need to **run a full validator** node and stake MATIC. | ||
|
||
Also check the [Validator Responsibilities](/pos/design/validator/responsibilities) page. | ||
|
||
To be a delegator, you only need to **delegate MATIC to a validator** | ||
|
||
## What is the incentive? | ||
|
||
Polygon allocates 12% of its total supply of 10 billion tokens to fund the staking rewards. This is to ensure that the network is seeded well enough until transaction fees gain traction. These rewards are primarily meant to jump-start the network, while the protocol in the long run is intended to sustain itself on the basis of transaction fees. | ||
|
||
**Validator Rewards = Staking Rewards + Transaction Fees** | ||
|
||
This is allocated in a way to ensure gradual decoupling of staking rewards from being the dominant component of the validator rewards. | ||
|
||
|Year|Target Stake (30% of circulating supply)|Reward Rate for 30% Bonding|Reward Pool| | ||
|---|---|---|---| | ||
|First|1,977,909,431|20%|312,917,369| | ||
|Second|2,556,580,023|12%|275,625,675| | ||
|Third|2,890,642,855|9%|246,933,140| | ||
|Fourth|2,951,934,048|7%|204,303,976| | ||
|Fifth|2,996,518,749|5%|148,615,670 + **11,604,170**| | ||
|
||
Below is a sample snapshot of the expected annual rewards for the first 5 years considering staked supply ranging from 5% to 40% at 5% interval | ||
|
||
|% of circulating supply staked|5%|10%|15%|20%|25%|30%|35%|40%| | ||
|---|---|---|---|---|---|---|---|---| | ||
|Annual reward for year| | ||
|First|120%|60%|40%|30%|24%|20%|17.14%|15%| | ||
|Second|72%|36%|24%|18%|14.4%|12%|10.29%|9%| | ||
|Third|54%|27%|18%|13.5%|10.8%|9%|7.71%|6.75%| | ||
|Fourth|42%|21%|14%|10.5%|8.4%|7%|6%|5.25%| | ||
|Fifth|30%|15%|10%|7.5%|6%|5%|4.29%|3.75%| | ||
|
||
## Who gets the incentives? | ||
|
||
Stakers running validator nodes and stakers delegating their tokens toward a validator that they prefer. | ||
|
||
Validators have the option to charge a commission on the reward earned by delegators. | ||
|
||
The funds belonging to all stakers are locked in a contract deployed on the Ethereum mainnet. | ||
|
||
No validator holds custody over delegator tokens. | ||
|
||
## Staking rewards | ||
|
||
The yearly incentive is absolute — irrespective of the overall stake or the target bonding rate in the network, the incentive amount is given out as a reward to all signers periodically. | ||
|
||
In Polygon, there is an additional element of committing periodic checkpoints to the Ethereum mainnet. This is a major part of the validator responsibilities and they are incentivized to perform this activity. This constitutes a cost to the validator which is unique to a Layer 2 solution such as Polygon. We strive to accommodate this cost in the validator staking reward payout mechanism as a bonus to be paid to the proposer, who is responsible for committing the checkpoint. Rewards minus the bonus is to be shared among all stakers, proposer and signers, proportionally. | ||
|
||
## Encouraging the proposer to include all signatures | ||
|
||
To avail the bonus completely, the proposer must include all signatures in the checkpoint. Because the protocol desires ⅔ +1 weight of the total stake, the checkpoint is accepted even with 80% votes. However, in this case, the proposer gets only 80% of the calculated bonus. | ||
|
||
## Transaction fees | ||
|
||
Each block producer at Bor is given a certain percentage of the transaction fees collected in each block. The selection of producers for any given span is also dependent on the validator’s ratio in the overall stake. The remaining transaction fees flow through the same funnel as the rewards which get shared among all validators working at the Heimdall layer. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
This guide provides a curated list of common commands and Polygon-specific operations essential for node operators. Whether you're setting up a full node, validator node or troubleshooting, these commands will assist you in managing your Polygon PoS environment effectively. | ||
|
||
## Frequently used commands for Bor & Heimdall | ||
### Bor | ||
|
||
To execute Bor IPC commands, use the following syntax: | ||
|
||
```bash | ||
bor attach .bor/data/bor.ipc <command> | ||
``` | ||
|
||
| IPC Command | RPC Command | Description | | ||
| ----------- | ----------- | ----------- | | ||
| `admin.peers.length` | `curl -H "Content-Type: application/json" --data '{"jsonrpc": "2.0", "method": "net_peerCount", "params": [], "id": 74}' localhost:8545` | Retrieves the number of peers connected to the node. | | ||
| `admin.nodeInfo` | | Provides detailed information about the node. | | ||
| `eth.syncing` | `curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "eth_syncing","params": []}' localhost:8545` | Indicates whether the node is syncing (`true`) or not (`false`). | | ||
| `eth.syncing.highestBlock - eth.syncing.currentBlock` | | Compares the current block of your node to the highest block. | | ||
| `eth.blockNumber` | `curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "eth_blockNumber","params": []}' localhost:8545` | Returns the latest block number processed by the node. | | ||
| `debug.setHead("0x"+((eth.getBlock('latest').number) - 1000).toString(16))` | | Rewinds the blockchain to 1000 blocks prior. | | ||
| `admin.nodeInfo.enode` | | Retrieves the public enode URL of the node. | | ||
| `eth.syncing.currentBlock * 100 / eth.syncing.highestBlock` | | Calculates the remaining percentage for block synchronization. | | ||
| `eth.getBlock("latest").number` | `curl http://YourIP:8545 -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "method":"bor_getSigners", "params":["0x98b3ea"]}'` | Queries the height of the latest Bor block. | | ||
| | `curl http://YourIP:8545 -X POST -H "Content-Type: application/json" --data '{"method":"eth_chainId","params":[],"id":1,"jsonrpc":"2.0"}'` | Retrieves the `chainID`. | | ||
|
||
### Heimdall | ||
|
||
| Command | Description | | ||
| ------- | ----------- | | ||
| `curl localhost:26657/net_info?` | Returns the number of connected peers using `jq .result.n_peers`. | | ||
| `curl -s localhost:26657/status` | Retrieves Heimdall's current block height using `jq .result.sync_info.latest_block_height`. | | ||
| `curl localhost:26657/net_info` | Queries the node using its moniker with `grep moniker`. | | ||
| `curl -s localhost:26657/status` | Checks if Heimdall is in sync using `jq .result.sync_info.catching_up`. | | ||
| `curl -s localhost:26657/status` | Verifies Heimdall's sync status using `jq .result \| jq .sync_info`. | | ||
| `heimdalld unsafe-reset-all` | Resets the database in case of issues. | | ||
| `curl localhost:26657/status` | Provides comprehensive information about Heimdall. | | ||
|
||
|
||
## Node management commands | ||
|
||
| Description | Command | | ||
| ------------------------------------- | ---------------------------------------------- | | ||
| **Locate Heimdall genesis file** | `$CONFIGPATH/heimdall/config/genesis.json` | | ||
| **Locate heimdall-config.toml** | `/etc/heimdall/config/heimdall-config.toml` | | ||
| **Locate config.toml** | `/etc/heimdall/config/config.toml` | | ||
| **Locate heimdall-seeds.txt** | `$CONFIGPATH/heimdall/heimdall-seeds.txt` | | ||
| **Start Heimdall** | `$ sudo service heimdalld start` | | ||
| **Start Heimdall rest-server** | `$ sudo service heimdalld-rest-server start` | | ||
| **Start Heimdall bridge-server** | `$ sudo service heimdalld-bridge start` | | ||
| **Locate Bor genesis file** | `$CONFIGPATH/bor/genesis.json` | | ||
| **Start Bor** | `sudo service bor start` | | ||
| **Retrieve Heimdall logs** | `/var/log/matic-logs/` | | ||
| **Check Heimdall logs** | `tail -f heimdalld.log` | | ||
| **Check Heimdall rest-server logs** | `tail -f heimdalld-rest-server.log` | | ||
| **Check Heimdall bridge logs** | `tail -f heimdalld-bridge.log` | | ||
| **Check Bor logs** | `tail -f bor.log` | | ||
|
||
## Useful configuration commands | ||
|
||
### Sync status of Heimdall | ||
|
||
To check if Heimdall is synced, run: | ||
|
||
```bash | ||
curl http://localhost:26657/status | ||
``` | ||
|
||
### Latest block height on Heimdall | ||
|
||
To check the latest block height on Heimdall, run: | ||
|
||
```bash | ||
curl localhost:26657/status | ||
``` | ||
|
||
### Latest block height on Bor | ||
|
||
To check the latest block height on Bor, use: | ||
|
||
```bash | ||
curl http://<your ip>:8545 -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "method":"bor_getSigners", "params":["0x98b3ea"]}' | ||
``` | ||
|
||
### Cleanup: deleting remnants of Heimdall and Bor | ||
|
||
**For Linux package:** | ||
|
||
```bash | ||
sudo dpkg -i matic-bor | ||
sudo rm -rf /etc/bor | ||
``` | ||
|
||
**For Binaries:** | ||
|
||
```bash | ||
sudo rm -rf /etc/bor | ||
sudo rm /etc/heimdall | ||
``` | ||
|
||
### Terminate Bor process | ||
|
||
**For Linux:** | ||
|
||
```bash | ||
ps -aux | grep bor | ||
sudo kill -9 <PID> | ||
``` | ||
|
||
**For Binaries:** | ||
|
||
```bash | ||
cd CS-2003/bor | ||
bash stop.sh | ||
``` | ||
|
||
### Retrieve latest peer details | ||
|
||
To retrieve the latest peer details, run: | ||
|
||
```bash | ||
bor attach bor.ipc | ||
admin.peers.forEach(function(value){ | ||
console.log(value.enode+',') | ||
}) | ||
exit | ||
``` | ||
|
||
### Stop Heimdall and Bor services | ||
|
||
**For Linux packages:** | ||
|
||
```bash | ||
sudo service heimdalld stop | ||
sudo service bor stop | ||
``` | ||
|
||
**For binaries:** | ||
|
||
```bash | ||
pkill heimdalld | ||
pkill heimdalld-bridge | ||
cd CS-2001/bor | ||
bash stop.sh | ||
``` | ||
|
||
### Remove Heimdall and Bor directories | ||
|
||
**For Linux packages:** | ||
|
||
```bash | ||
sudo rm -rf /etc/heimdall/* | ||
sudo rm -rf /etc/bor/* | ||
``` | ||
|
||
**For binaries:** | ||
|
||
```bash | ||
sudo rm -rf /var/lib/heimdalld/ | ||
sudo rm -rf /var/lib/bor | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
|
||
## Purpose and capabilities | ||
|
||
The primary role of multi-signature wallets (multisigs) is to facilitate contract upgrades during the early stages of development. As these contracts become more robust, Polygon plans to: | ||
|
||
- Transition from multisigs to governance-controlled proxies. | ||
- Implement timelocks for added security. | ||
- Phase out multisigs entirely in the long term. | ||
|
||
**It's important to note that the existing multisigs do not have the capability to censor transactions, including bridge transactions.** | ||
|
||
## Active multi-signature wallets | ||
|
||
### Ethereum chain multisigs | ||
|
||
| Multisig Address | **5/9 Multisig**<br/>`0xFa7D2a996aC6350f4b56C043112Da0366a59b74c` | | ||
|:----------------:|---------------------------------------------------------------------| | ||
| Purpose | To upgrade PoS and staking contracts on Ethereum. | | ||
| Chain | Ethereum | | ||
| Rights | - Update staking contracts for optimizations and upgrades.<br/>- Address unexpected bugs in PoS contracts. | | ||
| Signatories | Quickswap, Curve, Polygon, Horizon Games, Cometh | | ||
|
||
### Polygon commitchain multisigs | ||
|
||
| Multisig Address | **5/8 Multisig**<br/>`0x355b8E02e7F5301E6fac9b7cAc1D6D9c86C0343f` | | ||
|:----------------:|---------------------------------------------------------------------| | ||
| Purpose | To update custom ChildERC20s on Polygon Commitchain. | | ||
| Chain | Polygon Commitchain | | ||
| Rights | Ability to upgrade custom child contracts. | | ||
| Signatories | Quickswap, Curve, Polygon, Horizon Games, Cometh | | ||
|
||
### Custom child ERC20s mapping | ||
|
||
| Multisig Address | **4/8 Multisig**<br/>`0x424bDE99FCfB68c5a1218fd3215caFfD031f19C4` | | ||
|:----------------:|---------------------------------------------------------------------| | ||
| Purpose | To enable the mapping of custom ChildERC20s with Mainnet contracts. | | ||
| Chain | Ethereum | | ||
| Rights | Limited to mapping; no access to Child tokens or deposit/withdrawal rights. | | ||
| Signatories | Polygon | | ||
|
||
### Permissionless mapping | ||
|
||
| Multisig Address | **Permissionless Mapping of Standard ChildERC20 Tokens (No Multisig Required)** | | ||
|:----------------:|--------------------------------------------------------------------------------| | ||
| Purpose | FxPortal supports permissionless token mapping of standard ChildERC20 for any ERC20 token on Ethereum. | | ||
| Chain | Permissionless | | ||
| Rights | Permissionless | | ||
| Signatories | Permissionless | | ||
|
||
<sub>*Plans are underway to transition these functions to governance. We are currently exploring options such as Aave's governance contracts and Compound’s timelock contracts.</sub> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
Polygon supports delegation via validator shares. By using this design, it is easier to distribute rewards and slash with scale (thousands of delegators) on Ethereum contracts without much computation. | ||
|
||
Delegators delegate by purchasing shares of a finite pool from validators. Each validator will have their own validator share token. Let's call these fungible tokens `VATIC` for a validator `A`. As soon as a user delegates to a validator `A`, they will be issued `VATIC` based on an exchange rate of `MATIC/VATIC` pair. As users accrue value the exchange rate indicates that they can now withdraw more `MATIC` for each `VATIC` and when users get slashed, users withdraw less `MATIC` for their `VATIC`. | ||
|
||
Note that `MATIC` is a staking token. A delegator needs to have `MATIC` tokens to participate in the delegation. | ||
|
||
Initially, a delegator `D` buys tokens from validator `A` specific pool when `1 MATIC per 1 VATIC`. | ||
|
||
When a validator gets rewarded with more `MATIC` tokens, new tokens are added to the pool. Let's say with the current pool of `100 MATIC` tokens, `10 MATIC` rewards are added to the pool. But since the total supply of `VATIC` tokens didn't change due to rewards, the exchange rate becomes `1 MATIC per 0.9 VATIC`. Now, delegator `D` gets more `MATIC` for the same shares. | ||
|
||
`VATIC`: Validator specific minted validator share tokens (ERC20 tokens) | ||
|
||
## Technical specification | ||
|
||
```solidity | ||
uint256 public validatorId; // Delegation contract for validator | ||
uint256 public validatorRewards; // accumulated rewards for validator | ||
uint256 public commissionRate; // validator's cut % | ||
uint256 public validatorDelegatorRatio = 10; // to be implemented/used | ||
uint256 public totalStake; | ||
uint256 public rewards; // rewards for pool of delegation stake | ||
uint256 public activeAmount; // # of tokens delegated which are part of active stake | ||
``` | ||
|
||
Exchange rate is calculated as below: | ||
|
||
```js | ||
ExchangeRate = (totalDelegatedPower + delegatorRewardPool) / totalDelegatorShares | ||
``` | ||
|
||
## Methods and variables | ||
|
||
### buyVoucher | ||
|
||
```js | ||
function buyVoucher(uint256 _amount) public; | ||
``` | ||
|
||
- Transfer the `_amount` to stakeManager and update the timeline data structure for active stake. | ||
- `updateValidatorState` is used to update timeline DS. | ||
- `Mint` delegation shares using current `exchangeRate` for `_amount`. | ||
- `amountStaked` is used to keep track of active stake of each delegator in order to calculate liquid rewards. | ||
|
||
### sellVoucher | ||
|
||
```js | ||
function sellVoucher() public; | ||
``` | ||
|
||
- Using current `exchangeRate` and number of shares to calculate total amount (active stake + rewards). | ||
- `unBond` active stake from validator and transfer rewards to delegator, if any. | ||
- Must remove active stake from timeline using `updateValidatorState` in stakeManger. | ||
- `delegators` mapping is used to keep track of stake in withdrawal period. | ||
|
||
### withdrawRewards | ||
|
||
```js | ||
function withdrawRewards() public; | ||
``` | ||
|
||
- For a delegator, calculate the rewards and transfer, and depending upon `exchangeRate` burn count of shares. | ||
- Example: if a delegator owns 100 shares and exchange rate is 200 so rewards are 100 tokens, transfer 100 tokens to delegator. Remaining stake is 100 so using exchange rate 200, now it is worth 50 shares. So burn 50 shares. Delegator now has 50 shares worth 100 tokens (which he initially staked / delegated). | ||
|
||
### reStake | ||
|
||
Restake can work in two ways: delegator can buy more shares using `buyVoucher` or reStake rewards. | ||
|
||
```js | ||
function reStake() public; | ||
``` | ||
|
||
Above function is used to reStake rewards. The number of shares aren’t affected because `exchangeRate` is the same; so just the rewards are moved into active stake for both validator share contract and stakeManager timeline. | ||
|
||
`getLiquidRewards` is used for calculating accumulated rewards i.e., delegator owns 100 share and exchange rate is 200, so rewards are 100 tokens. Move 100 tokens into active stake, since exchange rate is still same number of share will also remain same. Only difference is that now 200 tokens are considered into active stake and can't be withdrawn immediately (not a part of liquid rewards). | ||
|
||
Purpose of reStaking is that since delegator's validator has now more active stake and they will earn more rewards for that so will the delegator. | ||
|
||
### unStakeClaimTokens | ||
|
||
```js | ||
function unStakeClaimTokens() | ||
``` | ||
|
||
Once withdrawal period is over, delegators who've sold their shares can claim their MATIC tokens. Must transfer tokens to user. | ||
|
||
### updateCommissionRate | ||
|
||
```js | ||
function updateCommissionRate(uint256 newCommissionRate) | ||
external | ||
onlyValidator | ||
``` | ||
|
||
- Updates commission % for the validator. | ||
|
||
### updateRewards | ||
|
||
```js | ||
function updateRewards(uint256 reward, uint256 checkpointStakePower, uint256 validatorStake) | ||
external | ||
onlyOwner | ||
returns (uint256) | ||
``` | ||
|
||
When a validator gets rewards for submitting checkpoint, this function is called for disbursements of rewards between validator and delegators. |
Oops, something went wrong.