Skip to content

Commit

Permalink
asset module spec
Browse files Browse the repository at this point in the history
  • Loading branch information
lacsomot committed Jan 8, 2025
1 parent 14820d8 commit 64fedb7
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 69 deletions.
57 changes: 8 additions & 49 deletions x/asset/spec/01_concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,60 +6,19 @@ order: 1

## The Realio Asset Token Model

The Realio Asset module is centered aroumd a token model. It contains the following fields:
The Realio Asset module is centered around a token model where certain whitelisted accounts can issue their own token. A token issued by this module will be managed by a set of privileged accounts. These privileged accounts are assigned role by the issuer of the asset.

### Token
### System of privileged accounts

```protobuf
message Token {
string token_id = 1;
string issuer = 2;
string name = 3;
string symbol = 4;
uint32 decimals = 5;
string description = 6;
}
```
Privileged accounts of a token are accounts that can execute certain actions for that token. There're are several types of privileges, each has its own logic to define the actions which accounts of said type can execute. We wanna decouple the logic of these privileges from the `Asset module` logic, meaning that privileges will be defined in separate packages/modules, thus, developers can customize their type of privilege without modifying the `Asset Module`. Doing this allows our privileges system to be extensible while keeping the core logic of `Asset Module` untouched and simple, avoiding complicated migration when we expand our privileges system.

The token id for the token will be derived from the Issuer and the Symbol with the format of asset/{Issuer}/{Symbol-Lowercase}. This will allow 2 tokens to have the same name with different issuers.
In order for a privilege to integrate into the `Asset Module`. It has to implement the `Privilege` interface and has its implementation registered via the method `AddPrivilege`. Once that is done, we can make said privilege available onchain by executing `SoftwareUpgradeProposal` like a regular chain upgrade process.

The `issuer` is the address that create token. They can control all informations about the token, define other whitelist roles likes `manager` and `distributor`. `issuer` also can enable the token's single evm representation mode, which is showed in [EVM precompiles](README.md#asset-module-and-erc-20-precompiles).
It's important to note that the token manager can choose what privileges it wants to disable for its token Which is specified by the token manager when creating the token. After creating the token, all the enabled privileges will be assigned to the token manager in default but the token manager can assign privileges to different accounts later on.

### Role
### EVM enable

In token model, each token has 2 roles which can execute different functionality. They are whitelisted address that is defined by the issuer of the token. While `distributor` can control the `mint` functionality and custom the `DistributionSettings`, the `manager` can execute the other functionalities like `burn` or `freeze` and could modify the `functionalities_list`
While it is useful to represent the token in bank module, enabling the token to be in action in evm environment is very convenient and pave the possibility of integrating new features into the ecosystem.

- "ROLE_UNSPECIFIED": 0
- "ROLE_MANAGER": 1
- "ROLE_DISTRIBUTOR": 2
Each token can be enabled to work in the evm environment by the token manager, which means user can interact with the token through evm side like metamask or anyother evm wallet and more other protocol integrated in the future. Note that, token manager can disable or enable the token to be used in the evm environment.

### TokenManager

```protobuf
message TokenManager {
[]address manager_addresses = 1;
bool allow_new_fuctionalities = 2;
[]string functionalities_list = 3;
bool evm_enable = 4;
}
```

By setting `allow_new_fuctionalities`, `issuer` can specify whether they accept new functionalities or not when creating a new token. If he permits it, when upgrading the chain, the new features will be automatically added to the `functionalities_list`and the `manager` can then modify the `functionalities_list` as he sees fit. Otherwise, the `manager` can not chaing the `functionalities_list`.

### TokenDistributor

```protobuf
message TokenDistributor{
[]address distributor_addresses = 2;
DistributionSettings distribution_settings = 5;
}
```

### DistributionSettings

```protobuf
message DistributionSettings {
string max_supply = 1[(gogoproto.customtype) = "cosmossdk.io/math.Int"];
string max_ratelimit = 2[(gogoproto.customtype) = "cosmossdk.io/math.Int"];
}
```
58 changes: 43 additions & 15 deletions x/asset/spec/02_state.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,21 @@ order: 2

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

| State Object | Description | Key | Value | Store |
|----------------------|--------------------------------|--------------------------| ---------------------------|-------|
| `Token` | Token bytecode | `[]byte{1} + []byte(id)` | `[]byte{token}` | KV |
| `TokenManager` | TokenManager bytecode | `[]byte{2} + []byte(id)` | `[]byte{token_manager}` | KV |
| `TokenDistributor` | TokenDistributor bytecode | `[]byte{3} + []byte(id)` | `[]byte{token_distributor}`| KV |
| `FreezedAddresses` | Addresses bytecode | `[]byte{4} + []byte(id)` | `[]byte{[]address}` | KV |
| `Params` | Params bytecode | `[]byte{5} + []byte(id)` | `[]byte(id)` | KV |
| State Object | Description | Key | Value | Store |
|----------------------|----------------------------------------|--------------------------| ---------------------------|-------|
| `Params` | Params of asset module | `[]byte{1}` | `[]byte(params)` | KV |
| `Token` | Token information | `[]byte{2} + []byte(id)` | `[]byte{token}` | KV |
| `TokenManager` | TokenManager info of a denom | `[]byte{3} + []byte(id)` | `[]byte{token_manager}` | KV |
| `TokenDistributor` | TokenDistributor info of a denom | `[]byte{4} + []byte(id)` | `[]byte{token_distributor}`| KV |
| `FrozenAddresses` | Frozen Addresses bytecode | `[]byte{5} + []byte(id)` | `[]byte{[]address}` | KV |

### Params

```go
type Params struct {
AllowFunctionalities []string `protobuf:"bytes,1,rep,name=allow_functionalities,json=allowFunctionalities,proto3" json:"allow_functionalities,omitempty"`
}
```

### Token

Expand All @@ -31,6 +39,10 @@ type Token struct {
}
```

The token id for the token will be derived from the Issuer and the Symbol with the format of asset/{Issuer}/{Symbol-Lowercase}. This will allow 2 tokens to have the same name with different issuers.

The `issuer` is the address that create token. They can control all informations about the token, define other whitelist roles likes `manager` and `distributor`. `issuer` also can enable the token's single evm representation mode, which is showed in [EVM precompiles](README.md#asset-module-and-erc-20-precompiles).

### TokenManager

```go
Expand All @@ -51,19 +63,35 @@ type TokenManager struct{
}
```

### FreezedAddress
By setting `allow_new_fuctionalities`, `issuer` can specify whether they accept new functionalities or not when creating a new token. If he permits it, when upgrading the chain, the new features will be automatically added to the `functionalities_list`and the `manager` can then modify the `functionalities_list` as he sees fit. Otherwise, the `manager` can not chaing the `functionalities_list`.

List of addresses that is freezed by the manager. This only exists when the Token enable the `freeze` functionality. The addresses in list will not be able to execute any msg about the token.
### TokenDistributor

### Params
```protobuf
message TokenDistributor{
[]address distributor_addresses = 2;
DistributionSettings distribution_settings = 5;
}
```

```go
type Params struct {
AllowFunctionalities []string `protobuf:"bytes,1,rep,name=allow_functionalities,json=allowFunctionalities,proto3" json:"allow_functionalities,omitempty"`
### DistributionSettings

```protobuf
message DistributionSettings {
string max_supply = 1[(gogoproto.customtype) = "cosmossdk.io/math.Int"];
string max_ratelimit = 2[(gogoproto.customtype) = "cosmossdk.io/math.Int"];
}
```

## Genesis State
`max_supply` defines the maximum number of tokens can be minted.


### FreezedAddress

List of addresses that is freezed by the manager. This only exists when the Token enable the `freeze` functionality. The addresses in list will not be able to execute any msg about the token.


<!-- ## Genesis State
The `x/asset` module's `GenesisState` defines the state necessary for initializing the chain from a previous exported height. It contains the module parameters and the registered token pairs :
Expand All @@ -72,4 +100,4 @@ The `x/asset` module's `GenesisState` defines the state necessary for initializi
type GenesisState struct {
Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"`
}
```
``` -->
26 changes: 23 additions & 3 deletions x/asset/spec/04_msgs.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ order: 4
Issuer address
Managers [ ]address
Distributors [ ]address
ContractAddress string
Symbol string
Decimal uint32
Description string
Expand All @@ -40,14 +39,26 @@ Example token.json:
{
"Manager": ["realioabc..."],
"Distributor": ["realioabc2..."],
"ContractAddress": "0x...",
"Symbol": "riel",
"Decimal": "rielio",
"Description": "",
"SingleRepresentation": true,
"EvmEnable": true,
"AllowNewFuctionalities": true,
"FunctionalitiesList": [],
}
```

Validation:
- Check if Creator is whitelisted. We only allow some certain accounts to create tokens, these accounts is determined via gov proposal.
- Check if token has been created or not by iterating through all denom existing.
- Sanity check on token info like decimal, description,

Flow:
1. The denom for the token will be derived from Creator and Symbol with the format of asset/{Issuer}/{Symbol-Lowercase}
2. If `EvmEnable` is true, create a dynamic precompiles for the token.
3. Save the token basic information (name, symbol, decimal and description) in the x/bank metadata store
4. Save the token management info and distribution info in the x/asset store.

## 2. AssignRoles

`MsgAssignRoles` allow issue to set role likes manager or distributor for the token.
Expand Down Expand Up @@ -90,6 +101,15 @@ Example privilege.json:
}
```

Validation:
- Check if token exists
- Check if caller is issuer of the token
- Check if manager doesn't exist in the current managers list of token
- Check if distributor doesn't exist in the current distributor list of token

Flow:
1.

## 3. UnassignRole

```go
Expand Down
102 changes: 102 additions & 0 deletions x/asset/spec/05_query.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<!--
order: 5
-->

# Queries

## 1. QueryParams

The `QueryParams` allows users to query asset module params

```go
type QueryParamsRequest struct {
}
```

```go
type QueryParamsResponse struct {
Params Params
}
```

CLI:

```bash
realio-networkd q params
```

## 2. QueryToken

The `QueryToken` allows users to query a token related information

```go
type QueryTokenRequest struct {
TokenId string
}
```

```go
type QueryTokenResponse struct {
Token Token
TokenManager TokenManager
TokenDistributor TokenDistributor
}
```

CLI:

```bash
realio-networkd q token [token-id]
```

## 3. QueryAllTokens

The `QueryAllTokens` allows users to query all tokens related information

```go
type QueryAllTokensRequest struct {
}
```

```go
type QueryAllTokensResponse struct {
TokenInfo []TokenInfo

}
```

```go
type TokenInfo struct {
Token Token
TokenManager TokenManager
TokenDistributor TokenDistributor

}
```

CLI:

```bash
realio-networkd q all-tokens
```

## 4. QueryFrozenAddresses

The `QueryFrozenAddresses` allows users to query all frozen addresses

```go
type QueryFrozenAddressesRequest struct {
}
```

```go
type QueryFrozenAddressesResponse struct {
FrozenAddresses []address
}
```

CLI:

```bash
realio-networkd q frozen-addresses
```
4 changes: 2 additions & 2 deletions x/asset/spec/05_logic.md → x/asset/spec/06_logic.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!--
order: 5
order: 6
-->

# Logic
Expand Down Expand Up @@ -59,7 +59,7 @@ This flow will also work with `QueryHandler`, as long as we can unpack the `msg.

### Enable EVM interface

The token includes a field named `evm_enable`, which allows it to integrate with the ERC20 standard and have an EVM-compatible contract address. This EVM address acts as an abstract interface layer that bypasses the typical logic within ERC20 or EVM contracts. Instead of executing logic directly in the contract, all actions are reflected to the `asset` module, where the token’s core state and functionalities are managed.
The token includes a field named `evm_enable`, which allows it to integrate with the ERC20 standard and have an EVM-compatible contract address. This EVM address acts as an abstract interface layer that bypasses the typical logic within ERC20 or EVM contracts. Instead of executing logic directly in the contract, all actions are reflected to the `asset` module's predefined precompiles, where the token’s core state and functionalities are managed.

The token itself exists as a coin within the bank state, maintaining its own logic and functionalities independently of any ERC20 or EVM contract logic. The ERC20 contract deployed on the EVM serves purely as an interface, with its logic effectively bypassed. When other EVM contracts interact with this interface, their requests are forwarded via JSON-RPC calls to the `asset` module, which directly handles and executes the necessary operations. This is achieved by creating a `dynamic precompile` when `evm_enable` is activated, ensuring that the token’s behavior aligns with its internal state while still providing compatibility with the EVM ecosystem.

Expand Down

0 comments on commit 64fedb7

Please sign in to comment.