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

chore: update spec #132

Merged
merged 6 commits into from
Feb 28, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions x/multi-staking/spec/00_concepts.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,44 @@
# multi-staking-module

The multi-staking-module is a module that allows the cosmos-sdk staking system to support many types of token
The multi-staking-module is a module that allows the cosmos-sdk staking system to support many types of coin

## Features

- Staking with many diffrent type of tokens
- Staking with many diffrent type of coins
- Bond denom selection via Gov proposal
- A validator can only be delegated using its bonded denom
- All user usecases of the sdk staking module
- A validator can only be delegated using with one type of coin
- All usecases of the sdk staking module

## Multi staking design

Given the fact that several core sdk modules such as distribution or slashing is dependent on the sdk staking module, we design the multi staking module as a wrapper around the sdk staking module so that there's no need to replace the sdk staking module and its related modules.

The mechanism of this module is that it still uses the sdk staking module for all the logic related to staking. But since the sdk staking module doesn't allow multiple bond token/denom, in order to support such feature, the multi-staking module will convert (lock and mint) those different bond token/denom into the one token/denom that is used by the sdk staking module and then stake with the converted token/denom.
The mechanism of this module is that it still uses the sdk staking module for all the logic related to staking. But since the sdk staking module doesn't allow delegate with different types of coin, in order to support such feature, the multi-staking module will convert (lock and mint) those different coin into the one bond coin that is used by the sdk staking module and then stake with the converted bond coin.

![design](https://hackmd.io/_uploads/B1BduYEh6.png)

## Concepts and Terms

### Sdk bond token
### Bond coin

Bond coin is the only coin that the sdk staking module accepts for delegation. In our design, the bond coin is just a virtual coin used only in the sdk staking layer, serving no other purposes than that. No user accounts are allowed to access to the bond coin.

Since there're many bond denom/token stake-able via the multi-staking module but only one denom/token used by the underlying sdk staking module, let's refer to the former as `bond token/denom` and the latter as `sdkbond token/denom`.
### Multistaking coin

### Delegation
Multistaking coin refers to the instance of coin that is used to delegate via the multi-staking module.

Each delegation from a `delegator A` is actually reprensented in the form of a `sdk delegation` which refers to the delegation happened at the sdk staking module layer. In other words, there's little to no logic related to the actual delegation system (validator power distr, slashing, distributing rewards...) happens at the `multi-staking module` layer as well as delegation data being stored at `multi-staking module` store.
It is represented by this [struct](../types/multi_staking.pb.go), which is almost identical to the bank coin, except that it has an additional field called `bond weight`.

### Intermediary Account
### Bond Weight

For each delegation from a `delegator A`, the underlying `sdk delegation` will be created and managed DIRECTLY by an unique `intermediary account C` instead of the `delegator A`, meaning that the `sdk delegation` will have the `intermediary account` as its delegator. The `delegator A` though, via messages of the multi-staking module can still dictate what `intermediary account C` on what to do with the `sdk delegation` so that `delegator A` still have full controll over the delegation. However, delegators aren't actually aware of the `intermediary account`. All logic related to `intermediary acocunt` is considered internal logic of the module and thus concealed from `delegator`.
Each `multistaking coin` instance is associated with a `bond weight`. The `bond weight` value shows the conversion ratio to `bond coin` of that `multistaking coin` instance. It's different than the `bond weight` value set by government prop which specifies the current global `bond weight` value of that type of coin rather than `bond weight` value for a specific instance of `multistaking coin`.

The `intermediary account` is also where the `bond token` from `delegator` is locked and the `sdkbond token` is minted to, the minted `sdkbond token` will then be used to create the `sdk delegation`.
We mentioned above that for each delegation the multi-staking will lock the `multistaking coin` and mint a calculated ammount of `bond token`. The calculation here is a multiplication: minted bond token ammount = multistaking coin amount * bond weight.

### Bond Token Weight
### Multistaking lock

Each `bond token` is associated with a `bond token weight`. This `bond token weight` is specified via the gov proposal in which the `bond token` is accepted.
`MultistakingLock` is used to keep tracks of the multi-staking coin that is locked for each delegation. `MultistakingLock` contains `LockID` refering to delegation ID (delegator, validator) of the corresponding delegation, and `MultistakingCoin` refering to the instance of `multistaking coin` that is locked.

We mentioned above that for each delegation the multi-staking will lock the `bond token` and mint a calculated ammount of `sdkbond token`. The calculation here is a multiplication : minted sdkbond token ammount = bond token amount * bond token weight.
### Multistaking unlock

`MultistakingUnlock` is used to keep tracks of the multi-staking coin that is unlocking for each unbonding delegation. `MultistakingUnLock` contains `UnLockID` refering to unbonding delegation ID (delegator, validator) of the corresponding unbonding delegation, and `Entries` refering to the instances of `multistaking coin` that is unlocking.
24 changes: 7 additions & 17 deletions x/multi-staking/spec/01_state.md
Original file line number Diff line number Diff line change
@@ -6,28 +6,18 @@ order: 1

## Store

### Bond Token Weight
### Bond Weight

* BondWeight: `0x00 | BondDenom -> BondWeight (sdk.Dec)`
* BondWeight: `0x00 | Token Denom -> BondWeight (sdk.Dec)`

### Validator Bond Denom
### Validator Multistaking Coin

* ValidatorMultiStakingCoin: `0x01 | ValOperatorAddr -> BondDenom (string)`

### Intermediary Account Delegator
### Multistaking Lock

* IntermediaryDelegator: `0x02 | IntermediaryAccount -> DelegatorAddr`
* Multistaking Lock: `0x02 | LockID -> MultistakingLock`

### DV Pair SDK Bond Tokens
### Multistaking Unlock

* DVPairSDKBondToken: `0x03 | DVPair -> SDKBondTokens`

### DV Pair Bond Token

* DVPairBondToken: `0x04 | DVPair -> BondTokens`

## MemStore

### CompletedDelegations

* CompletedDelegations :`0x00 -> store(delegations)`
* CompletedDelegations :`0x03 | UnlockID -> MultistakingUnlock`
8 changes: 2 additions & 6 deletions x/multi-staking/spec/02_gov.md
Original file line number Diff line number Diff line change
@@ -2,12 +2,8 @@

### Add Bond Token Proposals

We can designate a token as a `bond token` by submiting an `AddBondDenomProposal`. In this proposal, we specify the token's denom and its `BondWeight`, if the proposal passes, the specified token will become a `bond token` with the designated `BondWeight`.
We can designate a token as a `multistaking coin` by submiting an `AddMultiStakingCoinProposal`. In this proposal, we specify the token's `denom` and its `BondWeight`, if the proposal passes, the specified token will become a `multistaking coin` with the designated `BondWeight`.

### Change Bond Token Weight Proposals

We can alter the `BondWeight` of a `bond token` by submiting a `UpdateBondWeightProposal`. This proposal requires specifying the `bond token` and the new `BondWeight`, if the proposal is passed the specified `bond token` will have its `BondWeight` changed.

### Remove Bond Token Proposals

We can remove a `bond token` by submiting a `RemoveBondTokenProposal`. This proposal requires specifying the `bond token`. If the proposal passes, the specified token will be removed from the list of bond tokens.
We can alter the `BondWeight` of a `multistaking coin` by submiting a `UpdateBondWeightProposal`. This proposal requires specifying `denom` of the `multistaking coin` and the new `BondWeight`, if the proposal is passed the specified `multistaking coin` have its `BondWeight` changed to new value that decleared by the proposal.
45 changes: 23 additions & 22 deletions x/multi-staking/spec/03_messages.md
Original file line number Diff line number Diff line change
@@ -42,37 +42,34 @@ This message is expected to fail if:
## MsgDelegate

Within this message the delegator locked up coins in the `multi-staking` module account.
The `multi-staking` inturns mint a calculated amount of `sdkstaking.Denom` and
create an `IntermediaryAccount` to delegate on behalf of the delegator.
The `multi-staking` inturns mint a calculated amount of `bondtoken` and delegate.

Logic flow:

* Get `IntermediaryAccount` for the delegator.
* Lock `multi staking` coin in the `multi-staking` module account.

* Set `IntermediaryDelegator` if it's not set yet.
* Caculate the `bond token` to be minted using `BondWeight`.

* Send delegated coins from user to `IntermediaryAccount`.
* Mint `bond token` to `delegator`

* Caculate the `sdkbond token` to be minted using `BondWeight`.
* Update `multi staking lock`.

* Mint `sdkbond token` to `IntermediaryAccount`

* Update `DVPairSDKBondTokens`.

* Update `DVPairBondTokens`.

* Create `sdk delegation` with `IntermediaryAccount` using the minted `sdkbond token`
* `delegate` using the minted `sdkbond token`

## MsgUndelegate

The `MsgUndelegate` message allows delegators to undelegate their tokens from
validator.
The `MsgUndelegate` message allows delegators to undelegate their `multi-staking` tokens from
validator, after the unbonding period the module will unlock the `multi-staking` tokens to return to the delegator

Logic flow:

* Calculate ammount of `sdkbond token` need to be `sdk undelegated`
* Calculate ammount of `bond token` need to be `undelegate`

* Update `multi staking lock`

* Call `stakingkeeper.Undelegate()` with the calculated amount of `sdkbond token`
* Update `multi staking unlock`

* Call `stakingkeeper.Undelegate()` with the calculated amount of `bond token`

The rest of the unbonding logic such as sending locked coins back to user will happens at `EndBlock()`

@@ -82,9 +79,13 @@ The `MsgCancelUnbonding` message allows delegators to cancel the `unbondingDeleg

Logic flow:

* Calculate amount of `sdkbond token` need to be `sdk cancel undelegation`
* Calculate amount of `bond token` need to be `cancel undelegation`

* Update `multi staking lock`

* Update `multi staking unlock`

* Call `stakingkeeper.CancelUnbondingDelegation()` with the calculated amount of `sdkbond token`
* Call `stakingkeeper.CancelUnbondingDelegation()` with the calculated amount of `bond token`

## MsgBeginRedelegate

@@ -94,8 +95,8 @@ the EndBlocker.

Logic flow:

* Calculate amount of `sdkbond token` need to be `sdk redelegate`
* Calculate amount of `bond token` need to be `redelegate`

* Call `stakingkeeper.BeginRedelegate()` with the calculated amount of `sdkbond token`
* Update the src `multi-staking lock` and the dst `multi-staking lock`

* Update `DVPairSDKBondTokens`
* Call `stakingkeeper.BeginRedelegate()` with the calculated amount of `bond token`
26 changes: 13 additions & 13 deletions x/multi-staking/spec/04_block.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
# Begin-Block
# End-Block

## Complete Unbonding Delegations

Check if there's any completed unbonding delegations.
If so, for each of the unbonding delegation:
### Calculate total `UnbondedAmount`

* Get the `delegator account` from `IntermediaryDelegator` store.
* Retrieve `matureUnbondingDelegations` which is the array of all `UnbondingDelegations` that complete in this block

* Update `CompletedDelegations`.
### Staking module EndBlock

# End-Block
* Call `Staking` module `EndBlock` to `CompleteUnbonding`

## Complete Unbonding Delegations
### MultiStaking module EndBlock

* Iterate over `matureUnbondingDelegations` which was retrieve above

Check if there's any entries in `CompletedDelegations`.
If so, for each entry:
* For each iteration, we will:

* Calculate the amount of `bond token` to be unlocked.
* Calculate amount of `unlockedCoin` that will be return to user by multiply the amount of `unbonded coin` and `bonded weight`

* Send the calculated amount of `bond token` from `IntermediaryAccount` to `delegator`
* Burn the `remainingCoin` that remain on the `Lock` after send `unlockedCoin` to user

* Update `DVPairSDKBondCoins`.
* Delete `UnlockEntry`.

* Delete the entry in `CompletetedDelegations`.