Skip to content

Commit

Permalink
chore: update spec (#132)
Browse files Browse the repository at this point in the history
* update concepts and state

* update block

* update gov specs

* update govs

* update messages spec

---------

Co-authored-by: GnaD13 <cpt.meoz@gmail.com>
  • Loading branch information
catShaark and GNaD13 authored Feb 28, 2024
1 parent f444a57 commit 0f80f47
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 73 deletions.
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
Expand Up @@ -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
Expand Up @@ -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
Expand Up @@ -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()`

Expand All @@ -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

Expand All @@ -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`.

0 comments on commit 0f80f47

Please sign in to comment.