Skip to content
This repository has been archived by the owner on Aug 13, 2024. It is now read-only.

Commit

Permalink
Add update of validator refresh interval
Browse files Browse the repository at this point in the history
  • Loading branch information
hyeonLewis committed May 13, 2024
1 parent 3424cb1 commit 8478e49
Showing 1 changed file with 92 additions and 52 deletions.
144 changes: 92 additions & 52 deletions KIPs/kip-163.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ Introducing a new CnStakingV3 with public delegation.

## Abstract

The new CnStakingV3 will be compatible with public delegation. The public delegation will support `delegation` and `redelegation` for general users.
The new CnStakingV3 will be compatible with public delegation. The public delegation will support `delegation` and `redelegation` for general users. Also, the staking information interval will be changed to 1 block, which is currently 86,400 blocks.

## Motivation

In KIP-81, Klaytn introduced CnStakingV2. However, it’s difficult for general users to delegate their KLAY if a validator doesn’t provide public delegation services. For example, users can delegate to `SwapScanner` and `KommuneDAO` since they provide their own public delegation services. This narrowed the delegation options to a small number of GC members. In addition, Klaytn expects various GC members to join in the merged chain; there is a strong need to introduce a new CnStakingV3 with public delegation.

The `redelegation` can make massive staking changes in a short period, which can lead to non-negligible errors in the validator set and reward distribution with current 86,400 blocks interval. To prevent this, the staking information intervl will be changed to 1 block.

## Specification

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.
Expand All @@ -29,23 +31,25 @@ The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL

CnStakingV3 is basically an upgraded version of CnStakingV2, so it must be compatible with the existing core contracts like `AddressBook`, `StakingTracker` and so on. The notifying changes include the followings:

- CnStakingV3 supports public delegation natively, allowing it to receive delegations and re-delegation from general users.
- CnStakingV3 supports public delegation natively, allowing it to receive delegations and re-delegation from general users.

- Re-delegation is supported between CnStakingV3 enabling public delegation and re-delegation.
- Re-delegation is supported between CnStakingV3 enabling public delegation and re-delegation.

A GC member can enable public delegation from CnStakingV3. If it is enabled, all staking functionalities must be proxied via a public delegation contract defined in this proposal, namely `PublicDelegation`. When users want to delegate their KLAY, they stake KLAY to `PublicDelegation` and receive `shares` in return, which represent users' assets.

`PublicDelegation` shall be implemented based on an interest-bearing token model, especially ERC-4626. However, `shares` must not be transferable.

Staking information for block `N` will come from block `N-1` instead of `CalcStakingBlockNumber(N)` from `FORK_BLOCK`.

### Smart Contracts Overview

This KIP contains upgraded and newly implemented smart contracts. The overall structure is shown in below diagram.

- CnStakingV3: an upgraded version of CnStakingV2. It can enable public delegation and use re-delegation between CNs enable public delegation.
- CnStakingV3: an upgraded version of CnStakingV2. It can enable public delegation and use re-delegation between CNs enable public delegation.

- IKIP163: an interface that a public delegation must implement to be compatible with CnStakingV3.
- IKIP163: an interface that a public delegation must implement to be compatible with CnStakingV3.

- PublicDelegation: a public delegation contract provided by Klaytn. Note that it will be only compatible with CnStakingV3.
- PublicDelegation: a public delegation contract provided by Klaytn. Note that it will be only compatible with CnStakingV3.

Henceforth, CnStakingV3 shall be denoted as CNv3, and Public Delegation as PD.

Expand Down Expand Up @@ -114,10 +118,10 @@ Deploys and sets a PD to CnV3. The `PublicDelegation` will be deployed via `_pdF

The function validates the following requirement(s):

- The function MUST revert if PD is not enabled.
- The function MUST revert if CnV3 already initialized.
- The function MUST revert if `_pdArgs` isn’t encoded correctly.
- The function MUST revert if PD deployment fails.
- The function MUST revert if PD is not enabled.
- The function MUST revert if CnV3 already initialized.
- The function MUST revert if `_pdArgs` isn’t encoded correctly.
- The function MUST revert if PD deployment fails.

The function emits `SetPublicDelegation` event.

Expand All @@ -129,12 +133,12 @@ Requests CNv3 to redelegate `_user`’s `_value` of KLAY to `_targetCnV3`. CNv3

The function validates the following requirement(s):

- The function MUST revert if CNv3 does not allow PD, or if the caller is not PD.
- The function MUST revert if CNv3 does not allow redelegation.
- The function MUST revert if `_targetCnV3` is itself.
- The function MUST revert if `_targetCnV3` isn’t a valid CNv3 staking contract registered in AddressBook.
- The function MUST revert if `_value` is larger than total staking amount.
- The function MUST revert if `lastRedelegation[_user] != 0 && lastRedelegation[_user] + lockup <= block.timestamp`.
- The function MUST revert if CNv3 does not allow PD, or if the caller is not PD.
- The function MUST revert if CNv3 does not allow redelegation.
- The function MUST revert if `_targetCnV3` is itself.
- The function MUST revert if `_targetCnV3` isn’t a valid CNv3 staking contract registered in AddressBook.
- The function MUST revert if `_value` is larger than total staking amount.
- The function MUST revert if `lastRedelegation[_user] != 0 && lastRedelegation[_user] + lockup <= block.timestamp`.

The function emits `Redelegation` event.

Expand All @@ -146,11 +150,11 @@ Handles redelegation request from departure CNv3. This CNv3 will stake msg.value

The function validates the following requirement(s):

- The function MUST revert if CNv3 does not allow PD.
- The function MUST revert if CNv3 does not allow redelegation.
- The function MUST revert if departure CNv3 isn’t a valid CNv3 staking contract registered in AddressBook.
- The function MUST revert if balance after calling `stakeFor` is lower than expected.
- In `stakeFor`, PD will stake `msg.value` back to CNv3. It means CNv3 can compute deterministic balance changes.
- The function MUST revert if CNv3 does not allow PD.
- The function MUST revert if CNv3 does not allow redelegation.
- The function MUST revert if departure CNv3 isn’t a valid CNv3 staking contract registered in AddressBook.
- The function MUST revert if balance after calling `stakeFor` is lower than expected.
- In `stakeFor`, PD will stake `msg.value` back to CNv3. It means CNv3 can compute deterministic balance changes.

The function emits `HandleRedelegation` event.

Expand Down Expand Up @@ -205,8 +209,8 @@ When block reward is auto-compounding, the commission is calculated and paid aut

Since PD is a type of token contract, its name and symbol will be determined as follows:

- Name: `{gcName} Public Delegated KLAY` (ex. `KF Public Delegated KLAY`)
- Symbol: `{gcName}-pdKLAY` (ex. `KF-pdKLAY`)
- Name: `{gcName} Public Delegated KLAY` (ex. `KF Public Delegated KLAY`)
- Symbol: `{gcName}-pdKLAY` (ex. `KF-pdKLAY`)

##### Interface

Expand Down Expand Up @@ -350,20 +354,20 @@ interface IPublicDelegation is IKIP163 {

The PublicDelegation has constants related to commission.

- `MAX_COMMISSION_RATE`: Max commission rate. It will be 3,000. (= 30%)
- `COMMISSION_DENOMINATOR`: Commission denominator. It will be 10,000.
- `MAX_COMMISSION_RATE`: Max commission rate. It will be 3,000. (= 30%)
- `COMMISSION_DENOMINATOR`: Commission denominator. It will be 10,000.

##### Methods

All math for managing a user's staking follows ERC4626 standard. Note that PD isn’t based on ERC20 assets, but native KLAY.

- `totalAssets()`: Total assets managed by PD. It contains reward.
- `maxRedeem(address owner)`: Max reedeemable shares of owner.
- `maxWithdraw(address owner)`: Max withdrawable KLAY of owner.
- `convertToAssets(uint256 shares)`: Expected KLAY when convert shares.
- `previewDeposit(uint256 assets)`: Expected shares when deposit assets of KLAY.
- `previewWithdraw(uint256 assets)`: Expected shares to withdraw assets of KLAY.
- `previewRedeem(uint256 shares)`: Expected KLAY when redeem shares.
- `totalAssets()`: Total assets managed by PD. It contains reward.
- `maxRedeem(address owner)`: Max reedeemable shares of owner.
- `maxWithdraw(address owner)`: Max withdrawable KLAY of owner.
- `convertToAssets(uint256 shares)`: Expected KLAY when convert shares.
- `previewDeposit(uint256 assets)`: Expected shares when deposit assets of KLAY.
- `previewWithdraw(uint256 assets)`: Expected shares to withdraw assets of KLAY.
- `previewRedeem(uint256 shares)`: Expected KLAY when redeem shares.

To enable auto-compounding, PD stakes cumulative KLAY rewards to CNv3 automatically when the below functions are called or call `sweep` function explicitly.

Expand All @@ -375,7 +379,7 @@ It updates commission receiver address of PD. Previously accumulated commission

The function validates the following requirement(s):

- The function MUST revert if caller is not an owner.
- The function MUST revert if caller is not an owner.

The function emits `UpdateCommissionTo` event.

Expand All @@ -387,8 +391,8 @@ It updates commission rate of PD. Previously accumulated rewards must follow pre

The function validates the following requirement(s):

- The function MUST revert if caller is not an owner.
- The function MUST revert if `_commissionRate` is higher than `MAX_COMMISSION_RATE`.
- The function MUST revert if caller is not an owner.
- The function MUST revert if `_commissionRate` is higher than `MAX_COMMISSION_RATE`.

The function emits `UpdateCommissionRate` event.

Expand All @@ -405,8 +409,8 @@ Call `delegate` with `msg.value` to CNv3 internally. It must mint corresponding

The function validates the following requirement(s):

- The function MUST revert if user would receive 0 shares.
- The function MUST revert if delegate call reverts.
- The function MUST revert if user would receive 0 shares.
- The function MUST revert if delegate call reverts.

The function emits `Staked` event.

Expand All @@ -424,9 +428,9 @@ Call `approveStakingWithdrawal` to CNv3 internally. It must burn corresponding s

The function validates the following requirement(s):

- The function MUST revert if user requests to withdraw 0 KLAY.
- The function MUST revert if user withdraws more than staked.
- The function MUST revert if `approveStakingWithdrawal` call reverts.
- The function MUST revert if user requests to withdraw 0 KLAY.
- The function MUST revert if user withdraws more than staked.
- The function MUST revert if `approveStakingWithdrawal` call reverts.

The functions emit `RequestWithdrawal` event.

Expand All @@ -442,8 +446,8 @@ Call `cancelApprovedStakingWithdrawal` to CNv3 internally. User’s shares must

The function validates the following requirement(s):

- The function MUST revert if a user attempts to withdraw another user’s request.
- The function MUST revert if `cancelApprovedStakingWithdrawal` call reverts.
- The function MUST revert if a user attempts to withdraw another user’s request.
- The function MUST revert if `cancelApprovedStakingWithdrawal` call reverts.

The function emits `RequestCancelWithdrawal` event.

Expand All @@ -460,8 +464,8 @@ Calls `withdrawApprovedStaking` to CNv3 internally. If the withdrawal was cancel

The function validates the following requirement(s):

- The function MUST revert if a user attempts to claim another user’s request.
- The function MUST revert if `withdrawApprovedStaking` call reverts.
- The function MUST revert if a user attempts to claim another user’s request.
- The function MUST revert if `withdrawApprovedStaking` call reverts.

The function emits `Claimed` if withdrew successfully.

Expand All @@ -479,14 +483,50 @@ Call `redelegate` to CNv3 internally. It must burn corresponding shares of users

The function validates the following requirement(s):

- The function MUST revert if `_targetCnV3` isn’t a valid CNv3 staking contract.
- The function MUST revert if current CNv3 doesn’t allow redelegation.
- The function MUST revert if a user redelegates more KLAY than staked.
- The function MUST revert is a user redelegates 0 KLAY.
- The function MUST revert if `redelegate` call reverts.
- The function MUST revert if `_targetCnV3` isn’t a valid CNv3 staking contract.
- The function MUST revert if current CNv3 doesn’t allow redelegation.
- The function MUST revert if a user redelegates more KLAY than staked.
- The function MUST revert is a user redelegates 0 KLAY.
- The function MUST revert if `redelegate` call reverts.

The functions emit `Redelegated` event.

### Core Logic

From `FORK_BLOCK`, the staking information for block `N` will be recorded in block `N-1` instead of `CalcStakingBlockNumber(N)`.

#### Parameters

| Constant | Value |
| ------------ | ----- |
| `FORK_BLOCK` | TBD |

```go
// In staking_manager.go
func GetStakingInfo(blockNum uint64) *StakingInfo {
stakingBlockNumber := blockNum
var stakingInfo *StakingInfo
if isForkBlockEnabled(blockNum) {
// After `FORK_BLOCK`, staking information for block `N` will be recorded in block `N-1`.
if blockNum > 0 {
stakingBlockNumber--
}
stakingInfo = GetStakingInfoForForkBlock(stakingBlockNumber)
} else {
// Before `FORK_BLOCK`, staking information for block `N` will be recorded in `CalcStakingBlockNumber(N)`.
stakingBlockNumber = params.CalcStakingBlockNumber(blockNum)
stakingInfo = GetStakingInfoOnStakingBlock(stakingBlockNumber)
}
return stakingInfo
}
```

| Function | Description |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `GetStakingInfo(blockNum)` | Returns staking information needed to handle block `blockNum`. |
| `GetStakingInfoForForkBlock(blockNum)` | Returns staking information at block `blockNum`. If `blockNum` is before `FORK_BLOCK - 1`, return nil. |
| `GetStakingInfoOnStakingBlock(blockNum)` | Returns staking information at staking block `blockNum`. If `blockNum` is not a staking interval block nor after `FORK_BLOCK`, return nil. |

## Rationale

### Non-transferable shares in PublicDelegation
Expand Down Expand Up @@ -522,9 +562,9 @@ TBA

## References

- [ERC4626](https://eips.ethereum.org/EIPS/eip-4626)
- [Inflation Attack](https://blog.openzeppelin.com/a-novel-defense-against-erc4626-inflation-attacks)
- [Cosmos Staking Module](https://docs.cosmos.network/v0.46/modules/staking/)
- [ERC4626](https://eips.ethereum.org/EIPS/eip-4626)
- [Inflation Attack](https://blog.openzeppelin.com/a-novel-defense-against-erc4626-inflation-attacks)
- [Cosmos Staking Module](https://docs.cosmos.network/v0.46/modules/staking/)

## Copyright

Expand Down

0 comments on commit 8478e49

Please sign in to comment.