Skip to content

Commit

Permalink
Update spec
Browse files Browse the repository at this point in the history
  • Loading branch information
trinitys7 committed Jan 11, 2025
1 parent fdbd06e commit 30fb126
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 76 deletions.
34 changes: 16 additions & 18 deletions x/asset/spec/02_state.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ The `x/asset` module keeps the following objects in state:
| `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 |
| `WhitelistAddresses` | Whitelist Addresses bytecode | `[]byte{5} + []byte(id) + []byte(address)` | `[]byte{bool}` | KV |
| `DynamicPrecompiles` | Dynamic Contract Precompiles bytecode | `[]byte{6} + []byte(id) + []byte(address)` | `[]byte{bool}` | KV |

### Token

Expand All @@ -28,17 +29,20 @@ type Token struct {
Symbol string `protobuf:"bytes,4,opt,name=symbol,proto3" json:"symbol,omitempty"`
Decimals uint32 `protobuf:"varint,5,opt,name=decimals,proto3" json:"decimals,omitempty"`
Description string `protobuf:"bytes,6,opt,name=description,proto3" json:"description,omitempty"`
EVMAddress common.Address `protobuf:"bytes,7,opt,name=description,proto3" json:"description,omitempty"`
}
```

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
When create the token, `asset` module auto generate for it a evm address. This address is used as a dynamic precompiles.

### TokenManagement

```go
type TokenManager struct{
type TokenManagement struct{
Managers []string `protobuf:"bytes,7,rep,name=managers,proto3" json:"managers,omitempty"`
AllowNewExtensions bool `protobuf:"varint,10,opt,name=allow_new_Extensions,json=allowNewExtensions,proto3" json:"allow_new_Extensions,omitempty"`
ExtensionsList []string `protobuf:"bytes,11,rep,name=extensions_list,json=extensionsList,proto3" json:"extensions_list,omitempty"`
Expand All @@ -48,27 +52,21 @@ type TokenManager struct{

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

### TokenDistributor
### TokenDistribution

```go
type TokenDistributor struct{
Distributors []string `protobuf:"bytes,8,rep,name=distributors,proto3" json:"distributors,omitempty"`
DistributionSettings DistributionSettings `protobuf:"bytes,12,opt,name=distribution_settings,json=distributionSettings,proto3" json:"distribution_settings"`
type TokenDistribution struct{
Distributors []string
MaxSupply math.Int
}
```

### DistributionSettings
`MaxSupply` defines the maximum number of tokens can be minted.

```go
type DistributionSettings struct{
MaxSupply math.Int
MaxRatelimit math.Int
}
```
### WhitelistAddresses

`MaxSupply` defines the maximum number of tokens can be minted.
`MaxRatelimit` defines the ratelimit of tokens can be minted per epoch (each epoch last 1 day).
`WhitelistAddresses` is a list of the address that's allow to create new token.

### FrozenAddress
### DynamicPrecompiles

List of addresses that is frozen 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.
`DynamicPrecompiles` is a list of the EVM precompile addresses.
4 changes: 0 additions & 4 deletions x/asset/spec/03_params.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@ The asset module contains the following parameters:
| Key | Type | Example |
|----------------------|---------------|------------------------|
| AllowExtensions | []string | ["burn","freeze"] |
| RatelimitDuration | time.Duration | "86400s" |
| WhitelistAddresses | []address | ["realio1..."] |

## Details

- AllowExtensions: list of extensions that the module provides. They can be update after the chain upgrade to enable new extension add-on to the module.
- RatelimitDuration: duration of ratelimit for `mint` extension.
- WhitelistAddresses: list of the address that's allow to create new token.
21 changes: 0 additions & 21 deletions x/asset/spec/05_query.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,24 +79,3 @@ 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
```
44 changes: 23 additions & 21 deletions x/asset/spec/06_logic.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,61 +6,63 @@ order: 6

This file describes the core logics in this module.

## Functionality
## Extension

### Register new functionality
### Register new extension

To intergrate with the `asset module` Each type of functionality has to implement this interface
To intergrate with the `asset module` Each type of extension has to implement this interface

```go
type Functionality interface {
type Extension interface {
RegisterInterfaces()
MsgHandler() MsgHandler
QueryHandler() QueryHandler
CLI() *cobra.Command
}

type MsgHandler func(context Context, funcMsg FunctionalityMsg) error
type MsgHandler func(context Context, funcMsg ExtensionMsg) error

type QueryHandler func(context Context, funcQuery FunctionalityMsg) error
type QueryHandler func(context Context, funcQuery ExtensionMsg) error
```

This interface provides all the functionality necessary for a functionality, including a message handler, query handler and cli
This interface provides all the extension necessary for a extension, including a message handler, query handler and cli.

All the `FunctionalityMsg` of a functionality should return the name of that functionality when called `FunctionalityName()`. A message handler should handle all the `FunctionalityMsg` of that functionality.
All the `ExtensionMsg` of a extension should return the name of that extension when called `ExtensionName()`. A message handler should handle all the `ExtensionMsg` of that extension.

### Upgrade Functionalities
### Upgrade Extensions

All functionalities are located in a seperate packages, for example: asset/functionalities, therefore the exentsion or upgrade of functionalities is unrelated to core logic of `Asset` module, all the modification and addition happen in only asset/functionalities package. The core Asset module does not need to be aware of the specifics of functionality handling. It interacts with functionalitys through defined interfaces or protocols.
All extensions are located in a seperate packages, for example: asset/extensions, therefore the exentsion or upgrade of extensions is unrelated to core logic of `Asset` module, all the modification and addition happen in only asset/extensions package. The core Asset module does not need to be aware of the specifics of extension handling. It interacts with extensions through defined interfaces or protocols.

Each Priviliges has their own proto to define their state and execute/query messages. By assigning a distinct proto to each functionality, you ensure that the logic, messages, and data associated with one functionality do not interfere with or complicate the others. This also makes the design easier to understand, maintain, and scale.
Each Extensions has their own proto to define their state and execute/query messages. By assigning a distinct proto to each extension, you ensure that the logic, messages, and data associated with one extension do not interfere with or complicate the others. This also makes the design easier to understand, maintain, and scale.

When adding a `Functionality`, we calls `FunctionalityManager.AddFunctionality()` in `app.go` which inturn maps all the `FunctionalityMsg` of that functionality to its `MsgHandler`. This mapping logic will later be used when running a `MsgExecuteFunctionality`.
When adding a `Extension`, we calls `ExtensionRouting.AddExtension()` in `app.go` which inturn maps all the `ExtensionMsg` of that extension to its `MsgHandler`. This mapping logic will later be used when running a `MsgExecuteExtension`.

### Message/Query routing

The message we pass in `ExecuteFunctionality` is `msg.Any` type. This type refered that it could be any type of message.
The message we pass in `ExecuteExtension` is `msg.Any` type. This type refered that it could be any type of message.
After receive this message, we will unpack the `msg.Any` type to an interface which implements what we want:

```go
type FunctionalityMsg interface {
FunctionalityName() string
type ExtensionMsg interface {
ExtensionName() string
}
```

As we defined the `AllowFunctionalities` in Params. If the message name is in the list, they will also exist there own interface in `FunctionalityRouting`.
As we defined the `AllowExtensions` in Params. If the message name is in the list, they will also exist there own interface in `ExtensionRouting`.

`FunctionalityRouting` acts as a centralized hub for routing messages, making it easy to manage and audit the flow of messages in the system.
It will route the `FunctionalityMsg` to its `MsgHandler` - where the msg is executed. In the `MsgHandler`, the message is further routed based on its type to the correct execution logic. This additional layer of routing within the MsgHandler ensures precise handling through message types, enabling fine-grained control and execution workflows.
`ExtensionRouting` acts as a centralized hub for routing messages, making it easy to manage and audit the flow of messages in the system.
It will route the `ExtensionMsg` to its `MsgHandler` - where the msg is executed. In the `MsgHandler`, the message is further routed based on its type to the correct execution logic. This additional layer of routing within the MsgHandler ensures precise handling through message types, enabling fine-grained control and execution workflows.

This flow will also work with `QueryHandler`, as long as we can unpack the `msg.Any` and get the name of the functionality.
This flow will also work with `QueryHandler`, as long as we can unpack the `msg.Any` and get the name of the extension.

### Extension Store

## EVM interaction

### 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's predefined precompiles, 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 extensions 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.
The token itself exists as a coin within the bank state, maintaining its own logic and extensions 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.

### ERC20 Precompiles
28 changes: 16 additions & 12 deletions x/asset/spec/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ parent:

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 two different roles, manager and distributor. These roles can be assigned to arbitrary accounts (could be either user accounts or module/contract account) by the token issuer.

Each token can choose to enable functionalities supported by the module. Currently, there are four functionalities supported: "mint", "freeze", "clawback", "transfer_auth", each handle a completely different logic. We wanna decouple the logic of these functionalities from the `Asset module`, meaning that they will be defined in separate packages/modules, thus, developers can customize new functionalities without modifying the `Asset Module`. Doing this allows our token model to be extensible while keeping the core logic of `Asset Module` untouched and simple, avoiding complicated migration when we integrating new features.
Each token can choose to enable extensions supported by the module. Currently, there are four extensions supported: "mint", "freeze", "clawback", "transfer_auth", each handle a completely different logic. We wanna decouple the logic of these extensions from the `Asset module`, meaning that they will be defined in separate packages/modules, thus, developers can customize new extensions without modifying the `Asset Module`. Doing this allows our token model to be extensible while keeping the core logic of `Asset Module` untouched and simple, avoiding complicated migration when we integrating new features.

The token manager's task is to choose what functionalities it wants to disable/enable for its token; and only the token manager can trigger those functionalities, except for the `mint` functionality which is handled by the `distributor`.
The token manager's task is to choose what extensions it wants to disable/enable for its token; and only the token manager can trigger those extensions, except for the `mint` extension which is handled by the `distributor`.

![asset_module](imgs/asset_module.png)

Expand All @@ -27,19 +27,19 @@ To link an asset to ERC20 Precompile, user have to create a gov proposal so that

![asset_precompiles](imgs/asset_precompiles.png)

### Mapping functions
### Mapping extensions

ERC20 precompiles come with a limited number of functions which are:
ERC20 precompiles come with a limited number of extensions which are:

- Transfer
- TransferFrom
- Approve
- IncreaseAllowance
- DecreaseAllowance

These functions can be called from both AssetModule and EVM side (by metamask for example).
These extensions can be called from both AssetModule and EVM side (by metamask for example).

Other functions like:
Other extensions like:

- Mint
- Burn
Expand All @@ -52,11 +52,15 @@ can only be called from Asset Module side.

1. **[Concept](01_concepts.md)**
2. **[State](02_state.md)**
- [Minter](02_state.md#minter)
- [Params](02_state.md#params)
- [Token](02_state.md#token)
- [TokenManagement](02_state.md#tokenmanagement)
- [TokenDistribution](02_state.md#tokendistribution)
- [WhitelistAddresses](02_state.md#whitelistaddresses)
- [DynamicPrecompiles](02_state.md#dynamicprecompiles)
3. **[Parameters](03_params.md)**
4. **[Messages](04_msgs.md)**
5. **[Client](05_client.md)**
- [CLI](05_client.md#cli)
- [gRPC](05_client.md#grpc)
- [REST](05_client.md#rest)
5. **[Query](05_query.md)**
6. **[Logic](06_logic.md)**
- [Extension](06_logic.md#extension)
- [EVM interaction](06_logic.md#evm-interaction)

0 comments on commit 30fb126

Please sign in to comment.