Skip to content

Commit

Permalink
Liquidvesting spec (#313)
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanovpetr authored Apr 24, 2024
1 parent b531ad3 commit c1d86ea
Show file tree
Hide file tree
Showing 8 changed files with 307 additions and 0 deletions.
24 changes: 24 additions & 0 deletions x/liquidvesting/spec/01_concepts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!--
order: 1
-->
# Concepts

## Liquidation

Users with vesting accounts can make their locked ISLM tokens liquid. If vesting account contains only locked tokens user can use `Liquidate` transaction and next things will happen:

1. Specified amount amount of locked ISLM token will be transfered from a user vesting account to `x/liquidvesting` module account
2. `x/liquidvesting` module will mint a liquid token which won't be locked and could be freely used in any way. Its amount will be equal to specified amount of locked ISLM token transfered to module account.
3. ERC20 contract of newly created liquid token will be deployed on evm layer and token pair for it will be created with `x/erc20` module

### Liquid token

Liquid token represents arbitrary amount of ISLM token locked in vesting. For each liquidate transaction new unique liquid token will be created.
Liquid token has vesting unlock schedule, it derives from original vesting account schedule which liquid token created from.

## Redeem
Once user has any liquid token on its account, it can be redeemed to locked ISLM token. Once user uses `Redeem` transaction next things will happen:

1. Liquid token amount specified for redeem will be burnt
2. ISLM token will be transfered to user's account from `x/liquidvesting` module
3. Liquid token unlock schedule will be applied to user's account. If user has a regular account it converts to vesting account. If user already has vesting account liquid token schedule will be merged with already existing schedule.
79 changes: 79 additions & 0 deletions x/liquidvesting/spec/02_state.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<!--
order: 2
-->

# State

## State Objects

The `x/liquidvesting` module keeps the following objects in state:

| State Object | Description | Key | Value | Store |
|--------------|-----------------------|---------------------------------|-----------------| -------- |
| `Denom` | Liquid token bytecode | `[]byte{1} + []byte(baseDenom)` | `[]byte{denom}` | KV |

### Denom

Denom aka liquid token representation of locked ISLM with unlock schedule

```go
type Denom struct {
// base_denom main identifier for the denom, used to query it from store.
BaseDenom string `protobuf:"bytes,1,opt,name=base_denom,json=baseDenom,proto3" json:"base_denom,omitempty"`
// display_denom identifier used for display name for broad audience
DisplayDenom string `protobuf:"bytes,2,opt,name=display_denom,json=displayDenom,proto3" json:"display_denom,omitempty"`
// original_denom which liquid denom derived from
OriginalDenom string `protobuf:"bytes,3,opt,name=original_denom,json=originalDenom,proto3" json:"original_denom,omitempty"`
// start date
StartTime time.Time `protobuf:"bytes,4,opt,name=start_time,json=startTime,proto3,stdtime" json:"start_time"`
// end_date
EndTime time.Time `protobuf:"bytes,5,opt,name=end_time,json=endTime,proto3,stdtime" json:"end_time"`
// lockup periods
LockupPeriods github_com_cosmos_cosmos_sdk_x_auth_vesting_types.Periods `protobuf:"bytes,6,rep,name=lockup_periods,json=lockupPeriods,proto3,castrepeated=github.com/cosmos/cosmos-sdk/x/auth/vesting/types.Periods" json:"lockup_periods"`
}
```

### Liquid token base denom

The unique identifier of a `Denom` is obtained by combining prefix `LIQUID` and numeric id which increments every time new liquid token is created e. g. `LIQUID12`

### Original denom

Original denom is keeping track of which denom liquid token derives from. In most of the cases it will be ISLM

### Start time

Defines start of unlock schedule bound to luqid token. Always match token creation date

### End time

Defines the date when liquid token schedule ends

### LockupPeriods

The main part of liquid token schedule consist of sdk vesting periods

```go
type Period struct {
// Period duration in seconds.
Length int64 `protobuf:"varint,1,opt,name=length,proto3" json:"length,omitempty"`
// Period amount
Amount github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,2,rep,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount"`
}
```

## Genesis State

The `x/liquidvesting` module's `GenesisState` defines the state necessary for initializing the chain from a previous exported height. It contains the module parameters and the existing liquid token :

```go
// GenesisState defines the module's genesis state.
type GenesisState struct {
// params defines all the paramaters of the module.
Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"`
// keeps track of denom ID
DenomCounter uint64 `protobuf:"varint,2,opt,name=denomCounter,proto3" json:"denomCounter,omitempty"`
// list of liquid denoms
Denoms []Denom `protobuf:"bytes,3,rep,name=denoms,proto3" json:"denoms"`
}
```
31 changes: 31 additions & 0 deletions x/liquidvesting/spec/03_state_transitions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!--
order: 3
-->

# State Transitions

## Liquidate

1. User submits `MsgLiquidate`
2. Checks if liquidation allowed for account and amount
- tokens on target account are fully vested
- specified amount is more than minimum liquidation amount param
- specified amount is less or equal to locked token amount
3. Calculate new schedules for account and for liquid token
4. Update target account with new schedule
5. Escrow locked token to module account
6. Create new liquid token with previously calculated schedule and update token id counter
7. Send newly created liquid token to target account
8. Deploy ERC20 contract for liquid token and register token pair with \`x/erc20\` module
9. Convert all liquid tokens from cosmos to ERC20

## Redeem

1. User submits `MsgRedeem`
2. Checks if redeem possible
- Specified liquid token does exist
- Check user's account has sufficient amount of liquid token to redeem
3. Burn specified liquid token amount
4. Subtract burnt liquid token amount from liquid token schedule
5. Transfer ISLM to target account
6. Apply token unlock schedule to target account. If target account is not vesting account it will be converted to vesting one.
48 changes: 48 additions & 0 deletions x/liquidvesting/spec/04_transactions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<!--
order: 4
-->

# Transactions

This section defines the `sdk.Msg` concrete types that result in the state transitions defined on the previous section.

## `MsgLiquidate`

A user broadcasts a `MsgLiquidate` message to liquidate locked ISLM token.

```go
type MsgLiquidate struct {
// account for liquidation of locked vesting tokens
LiquidateFrom string `protobuf:"bytes,1,opt,name=liquidate_from,json=liquidateFrom,proto3" json:"liquidate_from,omitempty"`
// account to send resulted liquid token
LiquidateTo string `protobuf:"bytes,2,opt,name=liquidate_to,json=liquidateTo,proto3" json:"liquidate_to,omitempty"`
// amount of tokens subject for liquidation
Amount types.Coin `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount"`
}
```

Message stateless validation fails if:

- Amount is not positive
- LiquidateFrom bech32 address is invalid
- LiquidateTo bech32 address is invalid

## `MsgRedeem`

A user broadcasts a `MsgRedeem` message to redeem liquid token to locked ISLM.

```go
type MsgRedeem struct {
RedeemFrom string `protobuf:"bytes,1,opt,name=redeem_from,json=redeemFrom,proto3" json:"redeem_from,omitempty"`
// destination address for vesting tokens
RedeemTo string `protobuf:"bytes,2,opt,name=redeem_to,json=redeemTo,proto3" json:"redeem_to,omitempty"`
// amount of vesting tokens to redeem from liquidation module
Amount types.Coin `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount"`
}
```

Message stateless validation fails if:

- Amount is not positive
- RedeemFrom bech32 address is invalid
- RedeemTo bech32 address is invalid
16 changes: 16 additions & 0 deletions x/liquidvesting/spec/05_parameters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!--
order: 5
-->

# Parameters

The `x/liquidvesting` module contains the following parameters:

| Key | Type | Default Value |
|----------------------------|-------------|---------------------|
| `MinimumLiquidationAmount` | sdkmath.Int | `1000*10^18` |

## Minimum liquidation amount

The `MinimumLiquidationAmount` parameter defines minimum amount of locked token which can be liquidated at once.

47 changes: 47 additions & 0 deletions x/liquidvesting/spec/06_clients.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<!--
order: 6
-->

# Clients

## CLI

Find below a list of  `haqqd` commands added with the `x/liquidvesting` module. You can obtain the full list by using the `haqqd -h` command. A CLI command can look like this:

```bash
haqqd query liquidvesting params
```

### Queries

| Command | Subcommand | Description |
|-------------------------|------------|--------------------------------|
| `query` `liquidvesting` | `denom` | Get liquid token |
| `query` `liquidvesting` | `denoms` | Get all existing liquid tokens |

### Transactions

| Command | Subcommand | Description |
|----------------------|-------------|---------------------------------------------------|
| `tx` `liquidvesting` | `liquidate` | Liquidates arbitrary amount of locked ISLM tokens |
| `tx` `liquidvesting` | `redeem` | Redeem liquid token to ISLM |

## gRPC

### Queries

| Verb | Method | Description |
| ------ |-------------------------------------| ------------------------------ |
| `gRPC` | `haqq.liquidvesting.v1.Query/Denom` | Get liquid token |
| `gRPC` | `haqq.liquidvesting.v1.Query/Denoms`| Get all existing liquid tokens |
| `GET` | `/haqq/liquidvesting/v1/denom` | Get liquid token |
| `GET` | `/haqq/liquidvesting/v1/denom` | Get all existing liquid tokens |

### Transactions

| Verb | Method | Description |
|--------|---------------------------------------| ------------------------------------------------- |
| `gRPC` | `haqq.liquidvesting.v1.Msg/Liquidate` | Liquidates arbitrary amount of locked ISLM tokens |
| `gRPC` | `haqq.liquidvesting.v1.Msg/Redeem` | Redeem liquid token to ISLM |
| `POST` | `/haqq/liquidvesting/v1/tx/liquidate` | Liquidates arbitrary amount of locked ISLM tokens |
| `POST` | `/haqq/liquidvesting/v1/tx/redeem` | Redeem liquid token to ISLM |
40 changes: 40 additions & 0 deletions x/liquidvesting/spec/07_schedule_manipulation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Schedule manipulation

This section describes in details how `x/liquidvesting` module handles operation with schedule mutation. Examples are provided.

## Liquidation

For example we have an account this account has 3 days of vesting so each day represented as a period and has amount which be unlocked once period is passed.
Let's imagine every period has different amount 10,20 and 30 respectively
```
10,20,30
```

So total amount locked in this schedule is 60. We want to liquidate 20 tokens from this schedule.
We will subtract portion of this amount from every period proportionally to total sum.
For the first period :
- 10 - first period amount
- 20 - liquidation amount
- 60 - total amount

Formula is 10 - 10*20/60 -> 10 - 200/60 -> 10 - 3 = 7

Important note in above calculations. We have step 200/60 and this division has a remainder. We will track this remainder but won't use it to calculate new period.

If we perform the same operation for every period we will get:
```
7,14,20
```
The sum of new periods is 41 but expected sum is 40 because we were subtracting 20 from periods with sum of 60.
So calculate diff between sum of new periods and expected sum and it is 1. Now having the diff we subtract it from last period. So we get:
```
7,14,19
```
These are our new periods. These new periods will be the new schedule of vesting account targeted by liquidation.

Now we need to know periods for newly created liquid token. and this is simply a diff between original periods and decreased periods
```
10,20,30 - original amount in periods
7,14,19 - decreased amount in periods
3,6,11 - liquid token amount in periods
```
22 changes: 22 additions & 0 deletions x/liquidvesting/spec/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!--
order: 0
title: "Liquid vesting Overview"
parent:
title: "liquidvesting"
-->

## Abstract

This document specifies the internal `x/liquidvesting` module of the Haqq Network.

With the `x/liquidvesting` users on Haqq Network can make their ISLM locked in vesting liquid.

## Contents

1. **[Concepts](01_concepts.md)**
2. **[State](02_state.md)**
3. **[State Transitions](03_state_transitions.md)**
4. **[Transactions](04_transactions.md)**
5. **[Parameters](05_parameters.md)**
6. **[Clients](06_clients.md)**
7. **[Schedule Manipulation](07_schedule_manipulation.md)**

0 comments on commit c1d86ea

Please sign in to comment.