Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve governance and staking docs #177

Merged
merged 17 commits into from
Jun 26, 2024
Merged
2 changes: 2 additions & 0 deletions documentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ This folder contains the following documents essential for understanding the dep
4. [Vesting Documentation](./vesting.md): This page explains the technical details concerning implementation, deployment and maintenance of vesting smart contracts that hold LSK tokens and release them according to predefined schedules.

5. [Migration Airdrop Documentation](./airdrop.md): This page explains the technical details concerning design and lifecycle of the migration airdrop smart contract that distributes LSK tokens as a reward to the users that migrated from the Lisk L1 network.

6. [Staking and Lisk DAO Documentation](./staking-governance.md): This page explains the technical details concerning Staking and Lisk DAO. The two topics are combined in one document as they are strongly linked to each other.
Binary file modified documentation/diagrams/delegating.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
57 changes: 37 additions & 20 deletions documentation/staking-governance.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,53 @@ This design with selectable locking duration helps to align token holders with t

The mechanism for locking tokens works as follows:

- Users can lock tokens for a specific locking duration (between 2 weeks and 2 years). After the locking duration ends, the users can redeem their tokens.
- Users can modify their locking positions (increase amount, extend locking duration) at any time.
- Users have the option to pause their locking period countdown. That means, the remaining locking duration remains fixed until the user decides to resume it. Note that this results in higher voting power and staking rewards as described below.
- Users can **lock** tokens for a specific locking duration (between 2 weeks and 2 years). After the locking duration ends, the users can unlock their tokens.
- Users can **modify** their locking positions (increase amount, extend locking duration) at any time.
- Users have the option to **pause** their locking period countdown. That means, the remaining locking duration remains fixed until the user decides to resume it. Note that this results in higher voting power and staking rewards as [described below](#pausing-a-locking-position).
- Each user may have multiple locking positions.
- Locking positions are represented using NFTs for composability into DeFi and potential future uses.
- In case a user wants to unlock earlier than the end of the locking duration, there is a fast unlock option. The fast unlock implies a penalty, i.e., an amount that is deducted from the locked LSK tokens. The penalty is set to `0.5 * lockedAmount * (remainingLockingDurationInDays / maximumLockingDuration)`, where `maximumLockingDuration` is set to 2 years. Users can then redeem their tokens after a 3-day emergency locking period.
- Locking positions are represented using **NFTs** for composability into DeFi and potential future uses.
- In case a user wants to unlock earlier than the end of the locking duration, there is a **fast unlock** option. The fast unlock implies a penalty, i.e., an amount that is deducted from the locked LSK tokens. The penalty is set to `0.5 * lockedAmount * (remainingLockingDurationInDays / maximumLockingDuration)`, where `maximumLockingDuration` is set to 2 years. Users can then unlock their tokens after a 3-day emergency locking period.
- Confiscated tokens are immediately redirected to the staking rewards pool to be distributed over the next 14 days period on top of the guaranteed rewards.
- Users do not have the option to cancel the fast un-stake during this 3 day window.
- Users do not have the option to cancel the fast unlock during this 3 day window.

## Voting Power

The voting power for a locked amount of tokens is computed as follows:
The voting power of an account is expressed by the account's balance of another ERC20 contract, the *Voting Power* contract. The token symbol of this contract `vpLSK`. The voting power for a locked amount of tokens is computed as follows:

- Generally, locked tokens provide a voting power proportional to the amount of locked tokens. Concretely, 1 locked LSK provides one unit of voting power.
- In case a user pauses their locking period countdown, they receives a boost of the voting power meaning the voting power is set to `lockedAmount * (1 + remainingLockingDurationInDays/365)`. Hence, the voting power can be increased by up to 200%.
- Generally, locked tokens provide a voting power proportional to the amount of locked tokens. Concretely, 1 locked LSK provides 1 vpLSK.
- In case a user pauses their locking period countdown, they receive a boost of the voting power meaning the voting power is set to `lockedAmount * (1 + remainingLockingDurationInDays/365)`. Hence, the voting power can be increased by up to 200% by pausing a locking position with the maximum locking period of 2 years.
gkoumout marked this conversation as resolved.
Show resolved Hide resolved

gkoumout marked this conversation as resolved.
Show resolved Hide resolved
### Voting Power for a Concrete Proposal

At the time a proposal is created, a snapshot of the delegated voting power is taken and the voting result is based on this snapshot. Consequently, neither any changes in the voting power nor any delegations made after the proposal creation have any influence on the voting result.

## Staking Rewards

Users receive rewards for their locking tokens as follows:
Users receive rewards for locking their tokens as follows:

- Rewards are calculated on a daily basis, based on the amount locked and the remaining locking duration. Concretely, the weight for a locked amount is given by `lockedAmount * (remainingLockingDurationInDays + 150)`. The total daily amount of staking rewards is then shared by all users proportional to their weight. That means, a position with weight `w` receives `totalDailyRewards * w / totalWeight`.
- Users can claim their rewards (and restake them immediately if they want) at any time.

## Pausing a Locking Position

- Rewards are calculated on a daily basis, based on the amount locked and the remaining locking duration. Concretely, the weight for a locked amount is given by `lockedAmount * (remainingLockingDurationInDays + 150)`. The total daily amount of staking rewards is then shared by all users proportional to their weight.
- Users can claim their rewards (and restake them immediately if they want) at any time.
As mentioned in several places above, it is possible *to pause* the countdown of a locking position. This can be done at any time. Once paused, the remaining locking duration does not decrease anymore. The owner of the locking position can *resume* the countdown of the locking period an any point in time. Once resumed, the remaining locking duration descreases again daily.

**Example**: A users creates a locking position on day 1 and with a locking duration of 30 days. On day 6, the remaining locking duration is 25 days. On the same day, the user pauses the locking pausition. On day 50, the remaining locking duration is still 25. The users resumes the countdown of the locking position on this day. On day 75, the reamining locking duration is zero and the user can unlock their tokens.

What are the consequences of pausing the countdown:

- The voting power is boosted, i.e. increased from `lockedAmount` to `lockedAmount * (1 + remainingLockingDurationInDays/365)`.
- The weight on the rewards calculation (`lockedAmount * (remainingLockingDurationInDays + 150)`) does not decrease daily (in contrast to unpaused locking positions) but remains fixed for the duration that the position remains paused. This results in higher staking rewards.
- The locking position does not expire.

## Onchain Governance

The main aspects of our onchain governance system are planned as follows:
The main aspects of our onchain governance system are as follows:

- We use OpenZeppelin’s Governor contract framework and also manage the Lisk DAO treasury with it.
- The following parameters are used:
- **Proposal threshold**: For creating a proposal, the voting power of the proposer must be at least 300,000, i.e., the value corresponding to 100,000 LSK locked for 2 years where the countdown is paused.
- **Quorum**: For a proposal to pass, the “yes” and “abstain” votes must sum up at least to 22,500,000, i.e., the value that corresponds to 7,500,000 LSK locked for 2 years where the countdown is paused.
- **Proposal threshold**: For creating a proposal, the voting power of the proposer must be at least 300,000 vpLSK, i.e., the value corresponding to 100,000 LSK locked for 2 years where the countdown is paused.
- **Quorum**: For a proposal to pass, the “yes” and “abstain” votes must sum up at least to 24,000,000 vpLSK, i.e., the value that corresponds to 8,000,000 LSK locked for 2 years where the countdown is paused.
- A proposal is accepted if the quorum, as defined above, is reached, and if there are strictly more “yes” than “no” votes.
- The onchain governance allows the following two proposal types:
- **Funding proposals**: A proposal for receiving a certain amount of funds to an address. If passed, the recipient receives the amount given in the proposal.
Expand All @@ -58,31 +74,32 @@ The graphic above shows all contracts involved in the staking and governance sys

### User Interaction

### Locking/Unlocking
#### Locking/Unlocking

![Locking/Unlocking/Modifying](diagrams/lock_unlock.png)

There are two ways how the user can lock/unlock/modify a staking position. In the first one, the user calls the Staking contract. The Staking contract will create/delete/modify a locking position in the Locking Position Contract which in turn forwards a call to the Voting Power Contract to adjust the voting power of the owner of the locking position. The Voting Power contract will emit events which will be used by Tally for indexing. For locking positions created like this, the user will not receive any rewards.

In the second way, the user calls the Reward contract. The Reward contract will call lock/unlock/modify in the Staking contract, which will trigger the same forwarded calls as in the first way. The difference is that the user will receive rewards for locking positions create this way.

### Delegating
#### Delegating

![Delegating](diagrams/delegating.png)

For delegating, the user is interacting with the Voting Power contract directly. The Voting Power contract will emit events which will be used by Tally for indexing.

### Creating Proposals and Voting
#### Creating Proposals and Voting

![Creating Proposals](diagrams/create_proposal.png)

For creating a proposal or voting on a proposal, the user is interacting with the Governor contract. The Governor contract will request the voting power of the proposer/voter in order to see if the user has enough voting power to create a proposal or for counting the voting results. Moreover, the Governor contract will emit events which will be used by Tally for indexing.

### Queueing and Executing Proposals
#### Queueing and Executing Proposals

![Queueing](diagrams/queue.png)

If a proposal has an attached execution, e.g. a transfer of some treasury funds, and the proposal passed, then the proposal must be queued and then executed. For this, a user (this can be any user) must interact with the Governor contract. This one is forwarding the queue/execute operation to the Timelock Controller contract, and the Governor contract additionally emits events which Tally uses for indexing. The Governor contract is the only account that is allowed to queue proposals at the Timelock Controller. As all executions are eventually executed by the Timelock Controller, contracts owned by the Lisk DAO must be owned by the Timelock Controller, and the DAO treasury must be held by it as well.

### Implementation of Lisk Staking
[See Lisk Staking implementation page](./staking.md)

For details about the implementation of the staking sytem, see the [Lisk Staking implementation page](./staking-implementation.md)
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
# L2 Lisk Staking

Staking L2 tokens creates additional utility of L2 Lisk token by allowing user to stake (Locking Position) an amount of token for a certain period of time allowing them to earn daily rewards and contribute to Governance.

## Implementation
# Staking Implementation

Implementation of L2 staking functionality is separated into,

Expand All @@ -15,7 +11,7 @@ Implementation of L2 staking functionality is separated into,
- `L2VotingPower` contract is an implementation of `ERC20Votes` token standard that maintains the voting power of an account.


### Structure of a Locking position
## Structure of a Locking position
A locking position (or a stake) is represented as a custom data structure containing:

![Structure of a Locking position](diagrams/locking_position.png)
Expand All @@ -27,11 +23,11 @@ A locking position (or a stake) is represented as a custom data structure contai
| expDate | `uint256` | The expiration date, i.e., the day when the locked amount becomes claimable for the user. |
| pausedLockingDuration | `uint256` | Remaining duration in days till the expiry once a paused locking position is resumed. It is set to zero if the locking position is not paused. |

### Identifying a Locking Position
## Identifying a Locking Position
`L2LockingPosition` contract maintains a collection of locking positions against each user and uniquely identifies them with an identifier of type `uint256`.

### L2Reward Contract
#### Events emitted on interactions
## L2Reward Contract
### Events emitted on interactions
`L2Reward` communicates changes to state made by the contract or other contracts it consumes through events:

| Contract | Event | Description |
Expand All @@ -44,12 +40,12 @@ A locking position (or a stake) is represented as a custom data structure contai
| `L2LockingPosition` | `Transfer` | Emitted when a locking position is transferred to another account. |
| `L2VotingPower` | `Transfer` | Emitted when external account creates or modifies a locking position, as the parameters of a locking position impact its owner's voting power by minting or burning some voting power tokens. |

#### API accessible to external user and Events
### API accessible to external user and Events
The diagram highlights the public API accessible to external accounts and how creation and manipulations of locking positions consumes other smart contracts and the relevant events that are emitted.

![API accessible to external user and Events](diagrams/l2reward_external_account_api_and_events.png)

#### API accessible to the owner of L2Reward contract and Events
### API accessible to the owner of L2Reward contract and Events
L2Reward contract is ownable and allows the contract owner to add funds for rewarding locking positions. Its owner can allocate new funds and unused rewards accumulated due to reward capping for a certain duration.

![API accessible to the owner of L2Reward contract and Events](diagrams/l2reward_owner_api_and_events.png)
Expand All @@ -60,7 +56,7 @@ This contract exposes the public API to retrieve information about locking posit

![API L2LockingPosition](diagrams/l2lockingposition_api.png)

# Representing Time
## Representing Time

Contracts involved in L2 Lisk staking maintains (UNIX epoch) time at the granularity of a day, instead of seconds.
The day 19740, will be 19740 x 60 x 60 x 24 i.e. 1705536000 epoch seconds, any interactions at other higher-level environment must convert days to epoch time.
Loading