diff --git a/x/evmutil/spec/01_concepts.md b/x/evmutil/spec/01_concepts.md index 78aeeff8..79d5e129 100644 --- a/x/evmutil/spec/01_concepts.md +++ b/x/evmutil/spec/01_concepts.md @@ -8,38 +8,36 @@ order: 1 In order to use the EVM and be compatible with existing clients, the gas denom used by the EVM must be in 18 decimals. Since `ukava` has 6 decimals of precision, it cannot be used as the EVM gas denom directly. -In order to use the Kava token on the EVM, the `evmutil` module provides an `EvmBankKeeper` that is responsible for the conversion of `ukava` and `akava`. A user's `akava` balance is stored in the `evmutil` store, while it's `ukava` balance remains stored in the cosmos-sdk `bank` module. +To use the Kava token on the EVM, the evmutil module provides an `EvmBankKeeper` that is responsible for the conversion of `ukava` and `akava`. A user's excess `akava` balance is stored in the `x/evmutil` store, while its `ukava` balance remains in the cosmos-sdk `x/bank` module. ## `EvmBankKeeper` Overview -The `EvmBankKeeper` provides access to an account's **total** `akava` balance and the ability to transfer, mint, and burn `akava`. If anything other than the `akava` denom is requested, the `EvmBankKeeper` will panic. +The `EvmBankKeeper` provides access to an account's total `akava` balance and the ability to transfer, mint, and burn `akava`. If anything other than the `akava` denom is requested, the `EvmBankKeeper` will panic. -```go -type BankKeeper interface { - evmtypes.BankKeeper - SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins - SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error -} -``` +This keeper implements the `x/evm` module's `BankKeeper` interface to enable the usage of `akava` denom on the EVM. -The keeper implements the `x/evm` module's `BankKeeper` interface to enable the usage of `akava` denom on the EVM. - -### `x/evm` Parameter +### `x/evm` Parameter Requirements Since the EVM denom `akava` is required to use the `EvmBankKeeper`, it is necessary to set the `EVMDenom` param of the `x/evm` module to `akava`. -### `akava` Balance Calculation +### Balance Calculation of `akava` -The `akava` balance of an account is derived from an account's **spendable** `ukava` balance times 10^12 (to derive its `akava` equivalent), plus the account's excess `akava` balance that can be accessed by the module `Keeper`. +The `akava` balance of an account is derived from an account's **spendable** `ukava` balance times 10^12 (to derive its `akava` equivalent), plus the account's excess `akava` balance that can be accessed via the module `Keeper`. -### Conversions Between `akava` & `ukava` +### `akava` <> `ukava` Conversion -When an account does not have sufficient `akava` to cover a transfer or burn, the `EvmBankKeeper` will try to swap 1 `ukava` to its equivalent `akava` amount. It does this by transferring 1 `ukava` from the sender to the `evmutil` module account, then adding the equivalent `akava` amount to the sender's balance via the keeper's `AddBalance`. +When an account does not have sufficient `akava` to cover a transfer or burn, the `EvmBankKeeper` will try to swap 1 `ukava` to its equivalent `akava` amount. It does this by transferring 1 `ukava` from the sender to the `x/evmutil` module account, then adding the equivalent `akava` amount to the sender's balance in the module state. -In reverse, if an account has enough `akava` balance for one or more `ukava`, the excess `akava` balance will be converted to `ukava`. This is done by removing the excess `akava` balance tracked by `evmutil` module store, then transferring the equivalent `ukava` coins from the `evmutil` module account to the target account. +In reverse, if an account has enough `akava` balance for one or more `ukava`, the excess `akava` balance will be converted to `ukava`. This is done by removing the excess `akava` balance in the module store, then transferring the equivalent `ukava` coins from the `x/evmutil` module account to the target account. The swap logic ensures that all `akava` is backed by the equivalent `ukava` balance stored in the module account. +## ERC20 token <> sdk.Coin Conversion + +`x/evmutil` enables the conversion between ERC20 tokens and sdk.Coins. This done through the use of the `MsgConvertERC20ToCoin` & `MsgConvertCoinToERC20` messages (see **[Messages](03_messages.md)**). + +Only ERC20 contract address that are whitelist via the `EnabledConversionPairs` param (see **[Params](05_params.md)**) can be converted via these messages. + ## Module Keeper The module Keeper provides access to an account's excess `akava` balance and the ability to update the balance. diff --git a/x/evmutil/spec/02_state.md b/x/evmutil/spec/02_state.md index 425386da..3f2c2d48 100644 --- a/x/evmutil/spec/02_state.md +++ b/x/evmutil/spec/02_state.md @@ -4,15 +4,35 @@ order: 2 # State -## Genesis state +## Parameters and Genesis State -`GenesisState` defines the state that must be persisted when the blockchain stops/restarts in order for normal function of the committee module to resume. +`Parameters` define the list of conversion pairs allowed to be converted between Kava ERC20 tokens and sdk.Coins. + +```protobuf +// Params defines the evmutil module params +message Params { + // enabled_conversion_pairs defines the list of conversion pairs allowed to be + // converted between Kava ERC20 and sdk.Coin + repeated ConversionPair enabled_conversion_pairs = 4; +} + +// ConversionPair defines a Kava ERC20 address and corresponding denom that is +// allowed to be converted between ERC20 and sdk.Coin +message ConversionPair { + // ERC20 address of the token on the Kava EVM + bytes kava_erc20_address = 1; + // Denom of the corresponding sdk.Coin + string denom = 2; +} +``` + +`GenesisState` defines the state that must be persisted when the blockchain stops/restarts in order for normal function of the evmutil module to resume. ```protobuf message GenesisState { - repeated Account accounts = 1; + repeated Account accounts = 1 [(gogoproto.nullable) = false]; + Params params = 2 [(gogoproto.nullable) = false]; } - ``` ## Account @@ -30,4 +50,4 @@ message Account { ## Store -For complete implementation details for how items are stored, see [keys.go](../types/keys.go). The `evmutil` module store state consists of accounts. +For complete implementation details for how items are stored, see [keys.go](../types/keys.go). `x/evmutil` store state consists of accounts. diff --git a/x/evmutil/spec/03_messages.md b/x/evmutil/spec/03_messages.md new file mode 100644 index 00000000..cedc0095 --- /dev/null +++ b/x/evmutil/spec/03_messages.md @@ -0,0 +1,65 @@ + + +# Messages + +Users can submit various messages to the evmutil module which trigger state changes detailed below. + +## MsgConvertERC20ToCoin + +`MsgConvertCoinToERC20` converts a Kava ERC20 coin to sdk.Coin. + +```protobuf +service Msg { + // ConvertERC20ToCoin defines a method for converting Kava ERC20 to sdk.Coin. + rpc ConvertERC20ToCoin(MsgConvertERC20ToCoin) returns (MsgConvertERC20ToCoinResponse); +} + +// MsgConvertERC20ToCoin defines a conversion from Kava ERC20 to sdk.Coin. +message MsgConvertERC20ToCoin { + // EVM 0x hex address initiating the conversion. + string initiator = 1; + // Kava bech32 address that will receive the converted sdk.Coin. + string receiver = 2; + // EVM 0x hex address of the ERC20 contract. + string kava_erc20_address = 3; + // ERC20 token amount to convert. + string amount = 4 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + ]; +} +``` + +### State Changes + +- The `EnabledConversionPairs` param from `x/evmutil` is checked to ensure the conversion pair is enabled. +- The initiator's ERC20 token from `kava_erc20_address` is locked by transferring it from the initiator's 0x address to the `x/evmutil` module account's 0x address. +- The same amount of sdk.Coin are minted for the corresponding denom of the `kava_erc20_address` in the `EnabledConversionPairs` param. The coins are then transferred to the receiver's Kava address. + +## MsgConvertCoinToERC20 + +`MsgConvertCoinToERC20` converts sdk.Coin to Kava ERC20. + +```protobuf +service Msg { + // ConvertCoinToERC20 defines a method for converting sdk.Coin to Kava ERC20. + rpc ConvertCoinToERC20(MsgConvertCoinToERC20) returns (MsgConvertCoinToERC20Response); +} + +// MsgConvertCoinToERC20 defines a conversion from sdk.Coin to Kava ERC20. +message MsgConvertCoinToERC20 { + // Kava bech32 address initiating the conversion. + string initiator = 1; + // EVM 0x hex address that will receive the converted Kava ERC20 tokens. + string receiver = 2; + // Amount is the sdk.Coin amount to convert. + cosmos.base.v1beta1.Coin amount = 3; +} +``` + +### State Changes + +- The `EnabledConversionPairs` param from `x/evmutil` is checked to ensure the conversion pair is enabled. +- The specified sdk.Coin is moved from the initiator's address to the module account and burned. +- The same amount of ERC20 coins are sent from the `x/evmutil` module account to the 0x receiver address. diff --git a/x/evmutil/spec/04_events.md b/x/evmutil/spec/04_events.md new file mode 100644 index 00000000..fb4243ff --- /dev/null +++ b/x/evmutil/spec/04_events.md @@ -0,0 +1,31 @@ + + +# Events + +The evmutil module emits the following events: + +## Handlers + +### MsgConvertERC20ToCoin + +| Type | Attribute Key | Attribute Value | +| --------------------- | ------------- | ------------------ | +| convert_erc20_to_coin | erc20_address | `{erc20 address}` | +| convert_erc20_to_coin | initiator | `{initiator}` | +| convert_erc20_to_coin | receiver | `{receiver}` | +| convert_erc20_to_coin | amount | `{amount}` | +| message | module | evmutil | +| message | sender | {'sender address}' | + +### MsgConvertCoinToERC20 + +| Type | Attribute Key | Attribute Value | +| --------------------- | ------------- | ------------------ | +| convert_coin_to_erc20 | initiator | `{initiator}` | +| convert_coin_to_erc20 | receiver | `{receiver}` | +| convert_coin_to_erc20 | erc20_address | `{erc20_address}` | +| convert_coin_to_erc20 | amount | `{amount}` | +| message | module | evmutil | +| message | sender | {'sender address}' | diff --git a/x/evmutil/spec/05_params.md b/x/evmutil/spec/05_params.md new file mode 100644 index 00000000..d1edf4fe --- /dev/null +++ b/x/evmutil/spec/05_params.md @@ -0,0 +1,22 @@ + + +# Parameters + +The evmutil module contains the following parameters: + +| Key | Type | Example | +| ---------------------- | ---------------------- | ------------- | +| EnabledConversionPairs | array (ConversionPair) | [{see below}] | + +Example parameters for `ConversionPair`: + +| Key | Type | Example | Description | +| ------------------ | ------ | -------------------------------------------- | ---------------------------------- | +| kava_erc20_Address | string | "0x43d8814fdfb9b8854422df13f1c66e34e4fa91fd" | ERC20 contract address | +| denom | string | "erc20/chain/usdc" | sdk.Coin denom for the ERC20 token | + +## EnabledConversionPairs + +The enabled conversion pairs parameter is an array of ConversionPair entries mapping an erc20 address to a sdk.Coin denom. Only erc20 contract addresses that are in this list can be converted to sdk.Coin and vice versa. diff --git a/x/evmutil/spec/README.md b/x/evmutil/spec/README.md index 4563227b..0b23cf51 100644 --- a/x/evmutil/spec/README.md +++ b/x/evmutil/spec/README.md @@ -13,15 +13,23 @@ parent: 1. **[Concepts](01_concepts.md)** 2. **[State](02_state.md)** +3. **[Messages](03_messages.md)** +4. **[Events](04_events.md)** +5. **[Params](05_params.md)** ## Overview -The `evmutil` module provides additional functionalities on top of the `evm` module by storing additional state data for evm accounts and exposing an `EvmBankKeeper` that should be used by the `x/evm` keeper for bank operations. +The evmutil module provides additional functionalities on top of the evm module. -Two keepers are exposed by the module, `EvmBankKeeper` and the module `Keeper`. +### EVM `akava` Usage -The main purpose of the `EvmBankKeeper` is to allow the usage of the `akava` balance on the EVM through an account's existing `ukava` balance. -This is needed because the EVM gas token use 18 decimals, and since `ukava` has 6 decimals, it cannot be used as the EVM gas denom directly. +evmutil stores additional state data for evm accounts and exposes an `EvmBankKeeper` that should be used by the `x/evm` keeper for bank operations. +The purpose of the `EvmBankKeeper` is to allow the usage of the `akava` balance on the EVM via an account's existing `ukava` balance. This is needed because the EVM gas token use 18 decimals, and since `ukava` has 6 decimals, it cannot be used as the EVM gas denom directly. -The module `Keeper` provides access to an account's excess `akava` balance and the ability to update `akava` balances. This is needed by the `EvmBankKeeper` to store -excess `akava` balances since the `ukava` token only has 6 decimals of precision. +For additional details on how balance conversions work, see **[Concepts](01_concepts.md)**. + +### ERC20 Token <> sdk.Coin Conversion + +evmutil exposes messages to allow for the conversion of Kava ERC20 tokens and sdk.Coins via a whitelist. + +For additional details on how these messages work, see **[Messages](03_messages.md)**.