Skip to content

Commit c1d86ea

Browse files
authored
Liquidvesting spec (#313)
1 parent b531ad3 commit c1d86ea

8 files changed

+307
-0
lines changed

Diff for: x/liquidvesting/spec/01_concepts.md

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<!--
2+
order: 1
3+
-->
4+
# Concepts
5+
6+
## Liquidation
7+
8+
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:
9+
10+
1. Specified amount amount of locked ISLM token will be transfered from a user vesting account to `x/liquidvesting` module account
11+
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.
12+
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
13+
14+
### Liquid token
15+
16+
Liquid token represents arbitrary amount of ISLM token locked in vesting. For each liquidate transaction new unique liquid token will be created.
17+
Liquid token has vesting unlock schedule, it derives from original vesting account schedule which liquid token created from.
18+
19+
## Redeem
20+
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:
21+
22+
1. Liquid token amount specified for redeem will be burnt
23+
2. ISLM token will be transfered to user's account from `x/liquidvesting` module
24+
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.

Diff for: x/liquidvesting/spec/02_state.md

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<!--
2+
order: 2
3+
-->
4+
5+
# State
6+
7+
## State Objects
8+
9+
The `x/liquidvesting` module keeps the following objects in state:
10+
11+
| State Object | Description | Key | Value | Store |
12+
|--------------|-----------------------|---------------------------------|-----------------| -------- |
13+
| `Denom` | Liquid token bytecode | `[]byte{1} + []byte(baseDenom)` | `[]byte{denom}` | KV |
14+
15+
### Denom
16+
17+
Denom aka liquid token representation of locked ISLM with unlock schedule
18+
19+
```go
20+
type Denom struct {
21+
// base_denom main identifier for the denom, used to query it from store.
22+
BaseDenom string `protobuf:"bytes,1,opt,name=base_denom,json=baseDenom,proto3" json:"base_denom,omitempty"`
23+
// display_denom identifier used for display name for broad audience
24+
DisplayDenom string `protobuf:"bytes,2,opt,name=display_denom,json=displayDenom,proto3" json:"display_denom,omitempty"`
25+
// original_denom which liquid denom derived from
26+
OriginalDenom string `protobuf:"bytes,3,opt,name=original_denom,json=originalDenom,proto3" json:"original_denom,omitempty"`
27+
// start date
28+
StartTime time.Time `protobuf:"bytes,4,opt,name=start_time,json=startTime,proto3,stdtime" json:"start_time"`
29+
// end_date
30+
EndTime time.Time `protobuf:"bytes,5,opt,name=end_time,json=endTime,proto3,stdtime" json:"end_time"`
31+
// lockup periods
32+
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"`
33+
}
34+
```
35+
36+
### Liquid token base denom
37+
38+
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`
39+
40+
### Original denom
41+
42+
Original denom is keeping track of which denom liquid token derives from. In most of the cases it will be ISLM
43+
44+
### Start time
45+
46+
Defines start of unlock schedule bound to luqid token. Always match token creation date
47+
48+
### End time
49+
50+
Defines the date when liquid token schedule ends
51+
52+
### LockupPeriods
53+
54+
The main part of liquid token schedule consist of sdk vesting periods
55+
56+
```go
57+
type Period struct {
58+
// Period duration in seconds.
59+
Length int64 `protobuf:"varint,1,opt,name=length,proto3" json:"length,omitempty"`
60+
// Period amount
61+
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"`
62+
}
63+
```
64+
65+
## Genesis State
66+
67+
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 :
68+
69+
```go
70+
// GenesisState defines the module's genesis state.
71+
type GenesisState struct {
72+
// params defines all the paramaters of the module.
73+
Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"`
74+
// keeps track of denom ID
75+
DenomCounter uint64 `protobuf:"varint,2,opt,name=denomCounter,proto3" json:"denomCounter,omitempty"`
76+
// list of liquid denoms
77+
Denoms []Denom `protobuf:"bytes,3,rep,name=denoms,proto3" json:"denoms"`
78+
}
79+
```

Diff for: x/liquidvesting/spec/03_state_transitions.md

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<!--
2+
order: 3
3+
-->
4+
5+
# State Transitions
6+
7+
## Liquidate
8+
9+
1. User submits `MsgLiquidate`
10+
2. Checks if liquidation allowed for account and amount
11+
- tokens on target account are fully vested
12+
- specified amount is more than minimum liquidation amount param
13+
- specified amount is less or equal to locked token amount
14+
3. Calculate new schedules for account and for liquid token
15+
4. Update target account with new schedule
16+
5. Escrow locked token to module account
17+
6. Create new liquid token with previously calculated schedule and update token id counter
18+
7. Send newly created liquid token to target account
19+
8. Deploy ERC20 contract for liquid token and register token pair with \`x/erc20\` module
20+
9. Convert all liquid tokens from cosmos to ERC20
21+
22+
## Redeem
23+
24+
1. User submits `MsgRedeem`
25+
2. Checks if redeem possible
26+
- Specified liquid token does exist
27+
- Check user's account has sufficient amount of liquid token to redeem
28+
3. Burn specified liquid token amount
29+
4. Subtract burnt liquid token amount from liquid token schedule
30+
5. Transfer ISLM to target account
31+
6. Apply token unlock schedule to target account. If target account is not vesting account it will be converted to vesting one.

Diff for: x/liquidvesting/spec/04_transactions.md

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<!--
2+
order: 4
3+
-->
4+
5+
# Transactions
6+
7+
This section defines the `sdk.Msg` concrete types that result in the state transitions defined on the previous section.
8+
9+
## `MsgLiquidate`
10+
11+
A user broadcasts a `MsgLiquidate` message to liquidate locked ISLM token.
12+
13+
```go
14+
type MsgLiquidate struct {
15+
// account for liquidation of locked vesting tokens
16+
LiquidateFrom string `protobuf:"bytes,1,opt,name=liquidate_from,json=liquidateFrom,proto3" json:"liquidate_from,omitempty"`
17+
// account to send resulted liquid token
18+
LiquidateTo string `protobuf:"bytes,2,opt,name=liquidate_to,json=liquidateTo,proto3" json:"liquidate_to,omitempty"`
19+
// amount of tokens subject for liquidation
20+
Amount types.Coin `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount"`
21+
}
22+
```
23+
24+
Message stateless validation fails if:
25+
26+
- Amount is not positive
27+
- LiquidateFrom bech32 address is invalid
28+
- LiquidateTo bech32 address is invalid
29+
30+
## `MsgRedeem`
31+
32+
A user broadcasts a `MsgRedeem` message to redeem liquid token to locked ISLM.
33+
34+
```go
35+
type MsgRedeem struct {
36+
RedeemFrom string `protobuf:"bytes,1,opt,name=redeem_from,json=redeemFrom,proto3" json:"redeem_from,omitempty"`
37+
// destination address for vesting tokens
38+
RedeemTo string `protobuf:"bytes,2,opt,name=redeem_to,json=redeemTo,proto3" json:"redeem_to,omitempty"`
39+
// amount of vesting tokens to redeem from liquidation module
40+
Amount types.Coin `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount"`
41+
}
42+
```
43+
44+
Message stateless validation fails if:
45+
46+
- Amount is not positive
47+
- RedeemFrom bech32 address is invalid
48+
- RedeemTo bech32 address is invalid

Diff for: x/liquidvesting/spec/05_parameters.md

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!--
2+
order: 5
3+
-->
4+
5+
# Parameters
6+
7+
The `x/liquidvesting` module contains the following parameters:
8+
9+
| Key | Type | Default Value |
10+
|----------------------------|-------------|---------------------|
11+
| `MinimumLiquidationAmount` | sdkmath.Int | `1000*10^18` |
12+
13+
## Minimum liquidation amount
14+
15+
The `MinimumLiquidationAmount` parameter defines minimum amount of locked token which can be liquidated at once.
16+

Diff for: x/liquidvesting/spec/06_clients.md

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<!--
2+
order: 6
3+
-->
4+
5+
# Clients
6+
7+
## CLI
8+
9+
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:
10+
11+
```bash
12+
haqqd query liquidvesting params
13+
```
14+
15+
### Queries
16+
17+
| Command | Subcommand | Description |
18+
|-------------------------|------------|--------------------------------|
19+
| `query` `liquidvesting` | `denom` | Get liquid token |
20+
| `query` `liquidvesting` | `denoms` | Get all existing liquid tokens |
21+
22+
### Transactions
23+
24+
| Command | Subcommand | Description |
25+
|----------------------|-------------|---------------------------------------------------|
26+
| `tx` `liquidvesting` | `liquidate` | Liquidates arbitrary amount of locked ISLM tokens |
27+
| `tx` `liquidvesting` | `redeem` | Redeem liquid token to ISLM |
28+
29+
## gRPC
30+
31+
### Queries
32+
33+
| Verb | Method | Description |
34+
| ------ |-------------------------------------| ------------------------------ |
35+
| `gRPC` | `haqq.liquidvesting.v1.Query/Denom` | Get liquid token |
36+
| `gRPC` | `haqq.liquidvesting.v1.Query/Denoms`| Get all existing liquid tokens |
37+
| `GET` | `/haqq/liquidvesting/v1/denom` | Get liquid token |
38+
| `GET` | `/haqq/liquidvesting/v1/denom` | Get all existing liquid tokens |
39+
40+
### Transactions
41+
42+
| Verb | Method | Description |
43+
|--------|---------------------------------------| ------------------------------------------------- |
44+
| `gRPC` | `haqq.liquidvesting.v1.Msg/Liquidate` | Liquidates arbitrary amount of locked ISLM tokens |
45+
| `gRPC` | `haqq.liquidvesting.v1.Msg/Redeem` | Redeem liquid token to ISLM |
46+
| `POST` | `/haqq/liquidvesting/v1/tx/liquidate` | Liquidates arbitrary amount of locked ISLM tokens |
47+
| `POST` | `/haqq/liquidvesting/v1/tx/redeem` | Redeem liquid token to ISLM |

Diff for: x/liquidvesting/spec/07_schedule_manipulation.md

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Schedule manipulation
2+
3+
This section describes in details how `x/liquidvesting` module handles operation with schedule mutation. Examples are provided.
4+
5+
## Liquidation
6+
7+
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.
8+
Let's imagine every period has different amount 10,20 and 30 respectively
9+
```
10+
10,20,30
11+
```
12+
13+
So total amount locked in this schedule is 60. We want to liquidate 20 tokens from this schedule.
14+
We will subtract portion of this amount from every period proportionally to total sum.
15+
For the first period :
16+
- 10 - first period amount
17+
- 20 - liquidation amount
18+
- 60 - total amount
19+
20+
Formula is 10 - 10*20/60 -> 10 - 200/60 -> 10 - 3 = 7
21+
22+
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.
23+
24+
If we perform the same operation for every period we will get:
25+
```
26+
7,14,20
27+
```
28+
The sum of new periods is 41 but expected sum is 40 because we were subtracting 20 from periods with sum of 60.
29+
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:
30+
```
31+
7,14,19
32+
```
33+
These are our new periods. These new periods will be the new schedule of vesting account targeted by liquidation.
34+
35+
Now we need to know periods for newly created liquid token. and this is simply a diff between original periods and decreased periods
36+
```
37+
10,20,30 - original amount in periods
38+
7,14,19 - decreased amount in periods
39+
3,6,11 - liquid token amount in periods
40+
```

Diff for: x/liquidvesting/spec/README.md

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<!--
2+
order: 0
3+
title: "Liquid vesting Overview"
4+
parent:
5+
title: "liquidvesting"
6+
-->
7+
8+
## Abstract
9+
10+
This document specifies the internal `x/liquidvesting` module of the Haqq Network.
11+
12+
With the `x/liquidvesting` users on Haqq Network can make their ISLM locked in vesting liquid.
13+
14+
## Contents
15+
16+
1. **[Concepts](01_concepts.md)**
17+
2. **[State](02_state.md)**
18+
3. **[State Transitions](03_state_transitions.md)**
19+
4. **[Transactions](04_transactions.md)**
20+
5. **[Parameters](05_parameters.md)**
21+
6. **[Clients](06_clients.md)**
22+
7. **[Schedule Manipulation](07_schedule_manipulation.md)**

0 commit comments

Comments
 (0)