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

Modify/ecosystem incentive design #265

Merged
merged 19 commits into from
Dec 14, 2022
Merged
88 changes: 63 additions & 25 deletions x/ecosystem-incentive/spec/02_state.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,46 @@

**NOTE: This is early draft.**

## IncentiveStore
## IncentiveUnit

```protobuf
message IncentiveUnit {
string id = 1 [
(gogoproto.moretags) = "yaml:\"id\""
];
repeated SubjectInfo subject_info_list = 2 [
(gogoproto.moretags) = "yaml:\"subject_info_lists\"",
(gogoproto.nullable) = false
];
}

message SubjectInfo {
string address = 1 [
(gogoproto.moretags) = "yaml:\"subject_addr\"",
(gogoproto.customtype) = "github.com/UnUniFi/chain/types.StringAccAddress",
(gogoproto.nullable) = false
];
string weight = 2 [
(gogoproto.moretags) = "yaml:\"weight\"",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
}
```

- Incentive: `"incentive_id" -> format(IncentiveStore)`

### incentive_id

`incentive_id` is the unique identifier in the `incentive_store` for the subjects. Hence, it can't be duplicated.

## SubjectInfo

### weight

The ratio of the reward distribution in a `incentive_store` unit.
`incentive_store` can contain several `subject`s and ratio for each.

```protobuf
message IncentiveStore {
string incentive_id = 1;
repeated string subjects = 2;
repeated undetermined weights = 3;
RewardType reward_type = 4;
}
```

- Incentive: `"incentive_id" -> format(IncentiveStore)`

## NftmarketFrontendIncentiveIdTable

Expand All @@ -36,12 +55,16 @@ RewardTable is the record of the rewards for the subject of the `ecosystem-incen

```protobuf
message Reward {
string subject = 1 [
(gogoproto.moretags) = "yaml:\"sender\"",
string subject_addr = 1 [
(gogoproto.moretags) = "yaml:\"subject_addr\"",
(gogoproto.customtype) = "github.com/UnUniFi/chain/types.StringAccAddress",
(gogoproto.nullable) = false
];
repeated cosmos.base.v1beta1.Coin rewards = 2;
repeated cosmos.base.v1beta1.Coin rewards = 2 [
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
(gogoproto.moretags) = "yaml:\"rewards\"",
(gogoproto.nullable) = false
];
}
```

Expand All @@ -51,29 +74,40 @@ message Reward {

```protobuf
message Params {
repeated RewardParam reward_params = 1 [
(gogoproto.moretags) = "yaml:\"reward_params\"",
(gogoproto.nullable) = false
];
repeated RewardType reward_types = 2;
repeated RewardParams reward_params = 1 [ (gogoproto.moretags) = "yaml:\"reward_params\"" ];
uint64 max_incentive_unit_id_len = 2 [ (gogoproto.moretags) = "yaml:\"max_incentive_unit_id_len\"" ];
uint64 max_subject_info_num_in_unit = 3 [ (gogoproto.moretags) = "yaml:\"max_subject_info_num_in_unit\"" ];
}

message RewardParams {
string module_name = 1;
repeated RewardRate reward_rate = 2;
string module_name = 1 [
(gogoproto.moretags) = "yaml:\"module_name\""
];
repeated RewardRate reward_rate = 2 [
(gogoproto.moretags) = "yaml:\"reward_rate\"",
(gogoproto.nullable) = false
];
}

// RewardRate defines the ratio to take reward for a specific reward_type.
// The total sum of reward_rate in a module cannot be exceed 1
message RewardRate {
RewardType reward_type = 1;
unsure rate = 2;
RewardType reward_type = 1 [ (gogoproto.moretags) = "yaml:\"reward_type\"" ];
string rate = 2 [
(gogoproto.moretags) = "yaml:\"rate\"",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
}

// At first, we go with this one type.
// NFTMARKET_FRONTEND type reward will be disributed for the creators of frontend of UnUniFi's services.
enum RewardType {
NFTMARKET_FRONTEND = 0; // example
NFTMARKET_FRONTEND = 0;
}
```

`Params` contains `RewardParams` as the configuration of this module parameters.
`Params` contains `RewardParams` as the configuration of this module parameters and `MaxIncentiveUnitIdLen` as to define the max length of the IncentiveUnitId.

### RewardRate

Expand All @@ -84,3 +118,7 @@ e.g. If `reward_rate` is 80% and the trading fee that is made in a target messag

The reward type manages the types of the reward for the various subject.
At first, we support frontend creator. But, the reward will be able to distributed for the different type of parties in our ecosystem.

### MaxIncentiveUnitIdLen

The length of `IncentiveUnitId` must be between `MaxIncentiveUnitIdLen` and 0.
99 changes: 80 additions & 19 deletions x/ecosystem-incentive/spec/03_msgs_and_queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,67 @@ All messages of `ecosystem-incentive`.

### Register

A message to register `incentive_unit` to take reward from `ecosystem-incentive`.

```protobuf
message MsgIncentiveRegister {
string incentive_id = 1;
repeated string subjects = 2 [
message MsgRegister {
string sender = 1 [
(gogoproto.moretags) = "yaml:\"sender\"",
(gogoproto.customtype) = "github.com/UnUniFi/chain/types.StringAccAddress",
(gogoproto.nullable) = false
];
repeated undetermined weights = 3;
string incentive_unit_id = 2 [ (gogoproto.moretags) = "yaml:\"incentive_unit_id\"" ];
repeated string subject_addrs = 3 [
(gogoproto.moretags) = "yaml:\"subject_addrs\"",
(gogoproto.customtype) = "github.com/UnUniFi/chain/types.StringAccAddress",
(gogoproto.nullable) = false
];
repeated string weights = 4 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.moretags) = "yaml:\"weights\"",
(gogoproto.nullable) = false
];
}
message MsgRegisterResponse {}
```

or possibly take json file
`weights` must be `1.000000000000000000` (just ok as long as it represent 1).
For example,
ok: [0.5, 0.5], [0.33, 0.33, 0.34]
not: [0.5, 0.1], [0.33, 0.33, 0.3333]

And more importantly, don't forget how one `subject_addr` is associated with one `weight`. It's just order for those two lists. For example, in this case
```shell
subject_addrs = [
"ununifi17gs6kgph4657epky2ctl9sf66ucyua939nexgl",
"ununifi1w9s3wpkh0kfk0t40m4lwjsx6h2v6gktsvfrgux"
]
weights = [
"0.6",
"0.4
]
```

`ununifi17gs6kgph4657epky2ctl9sf66ucyua939nexgl`'s `weight` will be `0.6` and `ununifi1w9s3wpkh0kfk0t40m4lwjsx6h2v6gktsvfrgux`'s will be `0.4`.

#### CLI

We receive a JSON file in CLI command for this message.
Example JSON file for CLI tx command:

```Json
{
"incentive-id": "incentive-unit1",
"subject-addrs": [
"ununifi17gs6kgph4657epky2ctl9sf66ucyua939nexgl",
"ununifi1w9s3wpkh0kfk0t40m4lwjsx6h2v6gktsvfrgux"
],
"weights": [
"0.50",
"0.50"
]
}
```

### WithdrawAllRewards

Expand All @@ -36,40 +84,47 @@ message MsgWithdrawAllRewards {
}
```

### WithdrawSpecificReward
### WithdrawReward

A message to withdraw accumulated reward of specified denom.

```protobuf
message MsgWithdrawSpecificDenomReward {
message MsgWithdrawReward {
string sender = 1 [
(gogoproto.moretags) = "yaml:\"sender\"",
(gogoproto.customtype) = "github.com/UnUniFi/chain/types.StringAccAddress",
(gogoproto.nullable) = false
];
string denom = 2;
string denom = 2 [ (gogoproto.moretags) = "yaml:\"denom\"" ];
}
```

## Queries

All queries of `ecosystem-incentive`.

### IncentiveStore
### IncentiveUnit

```protobuf
message QueryIncentiveRequest {
string incentive_id = 1;
message QueryIncentiveUnitRequest {
string incentive_unit_id = 1 [ (gogoproto.moretags) = "yaml:\"incentive_unit_id\"" ];
}

message QueryIncentiveUnitResponse {
IncentiveUnit incentive_unit = 1 [ (gogoproto.moretags) = "yaml:\"incentive_unit\"" ];
}
```

### AllRewards

```protobuf
message QueryAllRewardsRequest {
string subject = 1 [
(gogoproto.moretags) = "yaml:\"sender\"",
(gogoproto.customtype) = "github.com/UnUniFi/chain/types.StringAccAddress",
string subject_addr = 1 [ (gogoproto.moretags) = "yaml:\"subject_addr\"" ];
}

message QueryAllRewardsResponse {
Reward rewards = 1 [
(gogoproto.moretags) = "yaml:\"rewards\"",
(gogoproto.nullable) = false
];
}
Expand All @@ -78,11 +133,17 @@ message QueryAllRewardsRequest {
### SpecificDenomReward

```protobuf
message QuerySpecificDenomRewardRequest {
string subject = 1 [
(gogoproto.moretags) = "yaml:\"sender\"",
(gogoproto.customtype) = "github.com/UnUniFi/chain/types.StringAccAddress",
message QueryRewardRequest {
string subject_addr = 1 [ (gogoproto.moretags) = "yaml:\"subject_addr\"" ];
string denom = 2 [ (gogoproto.moretags) = "yaml:\"denom\"" ];
}

message QueryRewardResponse {
cosmos.base.v1beta1.Coin reward = 1 [
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coin",
(gogoproto.moretags) = "yaml:\"reward\"",
(gogoproto.nullable) = false
];
string denom = 2;
}
```

14 changes: 7 additions & 7 deletions x/ecosystem-incentive/spec/04_hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,24 @@ The example hooks functions interfaces in x/nftmarket module:

```go
type NftmarketHooks interface {
AfterNftListed(ctx sdk.Context, nft_id types.NftIdentifier, tx_memo string)
AfterNftPaymentWithCommission(ctx sdk.Context, nft_id types.NftIdentifier, fee_amount mathInt, fee_denom string)
AfterNftUnlistedWituoutPayment(ctx sdk.Context, nft_id types.NftIdentifier)
AfterNftListed(ctx sdk.Context, nftIdentifier NftIdentifier, txMemo string)
AfterNftPaymentWithCommission(ctx sdk.Context, nftIdentifier NftIdentifier, fee sdk.Coin)
AfterNftUnlistedWithoutPayment(ctx sdk.Context, nftIdentifier NftIdentifier)
}
```

## AfterNftListed

This hooks function is called for the resistration for the `ecosystem-incentive` with the `incentive_id` and `NftIdentifiler` if the `incentive_id` is already registered on `ecosystem-incentive` module by sending `MsgRegister` message.
To pass the `incentive_id` from the memo data of `MsgListNft` requires a method to get memo data in the process of `MsgListNft` in `x/nftmarket` module.
This hook function is called for the resistration for the `ecosystem-incentive` with the `txMemo` and `nftIdentifiler`.
To pass the `txMemo` from the memo data of `MsgListNft` requires a method to get memo data in the process of `MsgListNft` in `x/nftmarket` module.

### Location to be inserted

- `ListNft(ctx sdk.Context, msg *types.MsgListNft)` from x/nftmarket in nft_listing.go

## AfterNftPaymentWithCommission

This hooks function is called for the accumulation of the reward for the subjects which are connected with the `nft_id` in the argument.
This hook function is called for the accumulation of the reward for the subjects which are connected with the `nftIdentifiler` in the argument.
The calculation of the actual reward amount is executed in methods which this hook function calls in this module.

### Location to be inserted
Expand All @@ -35,7 +35,7 @@ The calculation of the actual reward amount is executed in methods which this ho
## AfterNftUnlistedWituoutPayment

This hook function is called when a nft is unlisted for some reason like liquidation.
The purpose is to remove the unlisted nft information from `IncentiveIdTable` KVStore to keep the data consystent.
The purpose is to remove the unlisted nft information from `NftmarketFrontendIncentiveIdTable` KVStore to keep the data consystent.

### Location to be inserted

Expand Down
17 changes: 0 additions & 17 deletions x/ecosystem-incentive/spec/05_memo_structre.md

This file was deleted.

21 changes: 21 additions & 0 deletions x/ecosystem-incentive/spec/05_memo_structure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Data structure for the memo field

We use tx memo field data to identify what incentive will be distributed to what `incentive-unit` by putting the correct formatted json data into that.

The v1's formal data archtecture is:

```json
{
"version": "v1",
"incentive-unit-id": "incentive_unit-1"
}
```

NOTE: There's a lot of chances to be changed this structure with the change of the version. Please note it when to use.

## Frontends

We use memo field data to know which frontend a lisetd nft used in the case of frontend-incentive model.
So we have to use the organized data structure of memo field in a listing tx (MsgListNft) to distingush it as a legitimate entry or not.

Even if you put the wrong formatted data in the memo of tx contains MsgListNft, the MsgListNft itself will still succeed. The registration of the information which nft-id relates to what `incentive-unit-id` will just fail.
Loading