mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 01:27:26 +00:00 
			
		
		
		
	Add EIP712 ante (#1267)
* add eip712 ante * minor cleanup * eip712 integration test with bridge conversion * fix issues * update bridge module * merge bridge module convert logic * update eip712 tests & update deps * remove v17 migrations * remove v17 migrations * fix genesis test * fix erc20 to coin tx * remove eth check * clean up imports * remove * fix evmutil cli * remove bridge comments * address feedback * rename mint method * add transfer checks for locking & unlocking funds * fix gas * increase gas even more * fix amount check Co-authored-by: Ruaridh <rhuairahrighairidh@users.noreply.github.com> Co-authored-by: Ruaridh <rhuairahrighairidh@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									ed9991d44a
								
							
						
					
					
						commit
						2b123bf007
					
				@ -47,6 +47,12 @@ func (options HandlerOptions) Validate() error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// cosmosHandlerOptions extends HandlerOptions to provide some Cosmos specific configurations
 | 
				
			||||||
 | 
					type cosmosHandlerOptions struct {
 | 
				
			||||||
 | 
						HandlerOptions
 | 
				
			||||||
 | 
						isEIP712 bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewAnteHandler returns an 'AnteHandler' that will run actions before a tx is sent to a module's handler.
 | 
					// NewAnteHandler returns an 'AnteHandler' that will run actions before a tx is sent to a module's handler.
 | 
				
			||||||
func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
 | 
					func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
 | 
				
			||||||
	if err := options.Validate(); err != nil {
 | 
						if err := options.Validate(); err != nil {
 | 
				
			||||||
@ -63,11 +69,24 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
 | 
				
			|||||||
		txWithExtensions, ok := tx.(authante.HasExtensionOptionsTx)
 | 
							txWithExtensions, ok := tx.(authante.HasExtensionOptionsTx)
 | 
				
			||||||
		if ok {
 | 
							if ok {
 | 
				
			||||||
			opts := txWithExtensions.GetExtensionOptions()
 | 
								opts := txWithExtensions.GetExtensionOptions()
 | 
				
			||||||
			if len(opts) > 0 {
 | 
								if len(opts) > 1 {
 | 
				
			||||||
 | 
									return ctx, sdkerrors.Wrap(
 | 
				
			||||||
 | 
										sdkerrors.ErrInvalidRequest,
 | 
				
			||||||
 | 
										"rejecting tx with more than 1 extension option",
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if len(opts) == 1 {
 | 
				
			||||||
				switch typeURL := opts[0].GetTypeUrl(); typeURL {
 | 
									switch typeURL := opts[0].GetTypeUrl(); typeURL {
 | 
				
			||||||
				case "/ethermint.evm.v1.ExtensionOptionsEthereumTx":
 | 
									case "/ethermint.evm.v1.ExtensionOptionsEthereumTx":
 | 
				
			||||||
					// handle as *evmtypes.MsgEthereumTx
 | 
										// handle as *evmtypes.MsgEthereumTx
 | 
				
			||||||
					anteHandler = newEthAnteHandler(options)
 | 
										anteHandler = newEthAnteHandler(options)
 | 
				
			||||||
 | 
									case "/ethermint.types.v1.ExtensionOptionsWeb3Tx":
 | 
				
			||||||
 | 
										// handle as normal Cosmos SDK tx, except signature is checked for EIP712 representation
 | 
				
			||||||
 | 
										anteHandler = newCosmosAnteHandler(cosmosHandlerOptions{
 | 
				
			||||||
 | 
											HandlerOptions: options,
 | 
				
			||||||
 | 
											isEIP712:       true,
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
				default:
 | 
									default:
 | 
				
			||||||
					return ctx, sdkerrors.Wrapf(
 | 
										return ctx, sdkerrors.Wrapf(
 | 
				
			||||||
						sdkerrors.ErrUnknownExtensionOptions,
 | 
											sdkerrors.ErrUnknownExtensionOptions,
 | 
				
			||||||
@ -82,7 +101,10 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
 | 
				
			|||||||
		// handle as totally normal Cosmos SDK tx
 | 
							// handle as totally normal Cosmos SDK tx
 | 
				
			||||||
		switch tx.(type) {
 | 
							switch tx.(type) {
 | 
				
			||||||
		case sdk.Tx:
 | 
							case sdk.Tx:
 | 
				
			||||||
			anteHandler = newCosmosAnteHandler(options)
 | 
								anteHandler = newCosmosAnteHandler(cosmosHandlerOptions{
 | 
				
			||||||
 | 
									HandlerOptions: options,
 | 
				
			||||||
 | 
									isEIP712:       false,
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
 | 
								return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -91,17 +113,27 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
 | 
				
			|||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler {
 | 
					func newCosmosAnteHandler(options cosmosHandlerOptions) sdk.AnteHandler {
 | 
				
			||||||
	decorators := []sdk.AnteDecorator{}
 | 
						decorators := []sdk.AnteDecorator{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	decorators = append(decorators,
 | 
						decorators = append(decorators,
 | 
				
			||||||
		evmante.RejectMessagesDecorator{},   // reject MsgEthereumTxs
 | 
							evmante.RejectMessagesDecorator{},   // reject MsgEthereumTxs
 | 
				
			||||||
		authante.NewSetUpContextDecorator(), // second decorator. SetUpContext must be called before other decorators
 | 
							authante.NewSetUpContextDecorator(), // second decorator. SetUpContext must be called before other decorators
 | 
				
			||||||
		authante.NewRejectExtensionOptionsDecorator(),
 | 
					 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !options.isEIP712 {
 | 
				
			||||||
 | 
							decorators = append(decorators, authante.NewRejectExtensionOptionsDecorator())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(options.AddressFetchers) > 0 {
 | 
						if len(options.AddressFetchers) > 0 {
 | 
				
			||||||
		decorators = append(decorators, NewAuthenticatedMempoolDecorator(options.AddressFetchers...))
 | 
							decorators = append(decorators, NewAuthenticatedMempoolDecorator(options.AddressFetchers...))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var sigVerification sdk.AnteDecorator = authante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler)
 | 
				
			||||||
 | 
						if options.isEIP712 {
 | 
				
			||||||
 | 
							sigVerification = evmante.NewEip712SigVerificationDecorator(options.AccountKeeper, options.SignModeHandler, options.EvmKeeper)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	decorators = append(decorators,
 | 
						decorators = append(decorators,
 | 
				
			||||||
		NewEvmMinGasFilter(options.EvmKeeper), // filter out evm denom from min-gas-prices
 | 
							NewEvmMinGasFilter(options.EvmKeeper), // filter out evm denom from min-gas-prices
 | 
				
			||||||
		authante.NewMempoolFeeDecorator(),
 | 
							authante.NewMempoolFeeDecorator(),
 | 
				
			||||||
@ -118,7 +150,7 @@ func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler {
 | 
				
			|||||||
		authante.NewSetPubKeyDecorator(options.AccountKeeper), // SetPubKeyDecorator must be called before all signature verification decorators
 | 
							authante.NewSetPubKeyDecorator(options.AccountKeeper), // SetPubKeyDecorator must be called before all signature verification decorators
 | 
				
			||||||
		authante.NewValidateSigCountDecorator(options.AccountKeeper),
 | 
							authante.NewValidateSigCountDecorator(options.AccountKeeper),
 | 
				
			||||||
		authante.NewSigGasConsumeDecorator(options.AccountKeeper, options.SigGasConsumer),
 | 
							authante.NewSigGasConsumeDecorator(options.AccountKeeper, options.SigGasConsumer),
 | 
				
			||||||
		authante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
 | 
							sigVerification,
 | 
				
			||||||
		authante.NewIncrementSequenceDecorator(options.AccountKeeper), // innermost AnteDecorator
 | 
							authante.NewIncrementSequenceDecorator(options.AccountKeeper), // innermost AnteDecorator
 | 
				
			||||||
		ibcante.NewAnteDecorator(options.IBCKeeper),
 | 
							ibcante.NewAnteDecorator(options.IBCKeeper),
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										777
									
								
								app/ante/eip712_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										777
									
								
								app/ante/eip712_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,777 @@
 | 
				
			|||||||
 | 
					package ante_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/client"
 | 
				
			||||||
 | 
						codectypes "github.com/cosmos/cosmos-sdk/codec/types"
 | 
				
			||||||
 | 
						cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/simapp/helpers"
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/types/tx/signing"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
 | 
				
			||||||
 | 
						authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
 | 
				
			||||||
 | 
						authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
 | 
				
			||||||
 | 
						stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
 | 
						ethtypes "github.com/ethereum/go-ethereum/core/types"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/crypto"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/suite"
 | 
				
			||||||
 | 
						abci "github.com/tendermint/tendermint/abci/types"
 | 
				
			||||||
 | 
						"github.com/tendermint/tendermint/crypto/tmhash"
 | 
				
			||||||
 | 
						tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
 | 
				
			||||||
 | 
						tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
 | 
				
			||||||
 | 
						"github.com/tendermint/tendermint/version"
 | 
				
			||||||
 | 
						"github.com/tharsis/ethermint/crypto/ethsecp256k1"
 | 
				
			||||||
 | 
						"github.com/tharsis/ethermint/ethereum/eip712"
 | 
				
			||||||
 | 
						"github.com/tharsis/ethermint/tests"
 | 
				
			||||||
 | 
						etherminttypes "github.com/tharsis/ethermint/types"
 | 
				
			||||||
 | 
						evmtypes "github.com/tharsis/ethermint/x/evm/types"
 | 
				
			||||||
 | 
						feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/app"
 | 
				
			||||||
 | 
						cdptypes "github.com/kava-labs/kava/x/cdp/types"
 | 
				
			||||||
 | 
						evmutilkeeper "github.com/kava-labs/kava/x/evmutil/keeper"
 | 
				
			||||||
 | 
						evmutiltestutil "github.com/kava-labs/kava/x/evmutil/testutil"
 | 
				
			||||||
 | 
						evmutiltypes "github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
						hardtypes "github.com/kava-labs/kava/x/hard/types"
 | 
				
			||||||
 | 
						pricefeedtypes "github.com/kava-labs/kava/x/pricefeed/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						ChainID       = "kavatest_1-1"
 | 
				
			||||||
 | 
						USDCCoinDenom = "erc20/usdc"
 | 
				
			||||||
 | 
						USDCCDPType   = "erc20-usdc"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type EIP712TestSuite struct {
 | 
				
			||||||
 | 
						suite.Suite
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tApp          app.TestApp
 | 
				
			||||||
 | 
						ctx           sdk.Context
 | 
				
			||||||
 | 
						evmutilKeeper evmutilkeeper.Keeper
 | 
				
			||||||
 | 
						clientCtx     client.Context
 | 
				
			||||||
 | 
						ethSigner     ethtypes.Signer
 | 
				
			||||||
 | 
						testAddr      sdk.AccAddress
 | 
				
			||||||
 | 
						testAddr2     sdk.AccAddress
 | 
				
			||||||
 | 
						testPrivKey   cryptotypes.PrivKey
 | 
				
			||||||
 | 
						testPrivKey2  cryptotypes.PrivKey
 | 
				
			||||||
 | 
						testEVMAddr   evmutiltypes.InternalEVMAddress
 | 
				
			||||||
 | 
						testEVMAddr2  evmutiltypes.InternalEVMAddress
 | 
				
			||||||
 | 
						usdcEVMAddr   evmutiltypes.InternalEVMAddress
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *EIP712TestSuite) getEVMAmount(amount int64) sdk.Int {
 | 
				
			||||||
 | 
						incr := sdk.RelativePow(sdk.NewUint(10), sdk.NewUint(18), sdk.OneUint())
 | 
				
			||||||
 | 
						return sdk.NewInt(amount).Mul(sdk.NewIntFromUint64(incr.Uint64()))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *EIP712TestSuite) createTestEIP712CosmosTxBuilder(
 | 
				
			||||||
 | 
						from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, msgs []sdk.Msg,
 | 
				
			||||||
 | 
					) client.TxBuilder {
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nonce, err := suite.tApp.GetAccountKeeper().GetSequence(suite.ctx, from)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pc, err := etherminttypes.ParseChainID(chainId)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						ethChainId := pc.Uint64()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// GenerateTypedData TypedData
 | 
				
			||||||
 | 
						fee := legacytx.NewStdFee(gas, gasAmount)
 | 
				
			||||||
 | 
						accNumber := suite.tApp.GetAccountKeeper().GetAccount(suite.ctx, from).GetAccountNumber()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data := eip712.ConstructUntypedEIP712Data(chainId, accNumber, nonce, 0, fee, msgs, "")
 | 
				
			||||||
 | 
						typedData, err := eip712.WrapTxToTypedData(ethChainId, msgs, data, &eip712.FeeDelegationOptions{
 | 
				
			||||||
 | 
							FeePayer: from,
 | 
				
			||||||
 | 
						}, suite.tApp.GetEvmKeeper().GetParams(suite.ctx))
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						sigHash, err := eip712.ComputeTypedDataHash(typedData)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Sign typedData
 | 
				
			||||||
 | 
						keyringSigner := tests.NewSigner(priv)
 | 
				
			||||||
 | 
						signature, pubKey, err := keyringSigner.SignByAddress(from, sigHash)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						signature[crypto.RecoveryIDOffset] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add ExtensionOptionsWeb3Tx extension
 | 
				
			||||||
 | 
						var option *codectypes.Any
 | 
				
			||||||
 | 
						option, err = codectypes.NewAnyWithValue(ðerminttypes.ExtensionOptionsWeb3Tx{
 | 
				
			||||||
 | 
							FeePayer:         from.String(),
 | 
				
			||||||
 | 
							TypedDataChainID: ethChainId,
 | 
				
			||||||
 | 
							FeePayerSig:      signature,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						suite.clientCtx.TxConfig.SignModeHandler()
 | 
				
			||||||
 | 
						txBuilder := suite.clientCtx.TxConfig.NewTxBuilder()
 | 
				
			||||||
 | 
						builder, ok := txBuilder.(authtx.ExtensionOptionsTxBuilder)
 | 
				
			||||||
 | 
						suite.Require().True(ok)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						builder.SetExtensionOptions(option)
 | 
				
			||||||
 | 
						builder.SetFeeAmount(gasAmount)
 | 
				
			||||||
 | 
						builder.SetGasLimit(gas)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sigsV2 := signing.SignatureV2{
 | 
				
			||||||
 | 
							PubKey: pubKey,
 | 
				
			||||||
 | 
							Data: &signing.SingleSignatureData{
 | 
				
			||||||
 | 
								SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Sequence: nonce,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = builder.SetSignatures(sigsV2)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = builder.SetMsgs(msgs...)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return builder
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *EIP712TestSuite) SetupTest() {
 | 
				
			||||||
 | 
						tApp := app.NewTestApp()
 | 
				
			||||||
 | 
						suite.tApp = tApp
 | 
				
			||||||
 | 
						cdc := tApp.AppCodec()
 | 
				
			||||||
 | 
						suite.evmutilKeeper = tApp.GetEvmutilKeeper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						addr, privkey := tests.NewAddrKey()
 | 
				
			||||||
 | 
						suite.testAddr = sdk.AccAddress(addr.Bytes())
 | 
				
			||||||
 | 
						suite.testPrivKey = privkey
 | 
				
			||||||
 | 
						suite.testEVMAddr = evmutiltestutil.MustNewInternalEVMAddressFromString(addr.String())
 | 
				
			||||||
 | 
						addr2, privKey2 := tests.NewAddrKey()
 | 
				
			||||||
 | 
						suite.testPrivKey2 = privKey2
 | 
				
			||||||
 | 
						suite.testAddr2 = sdk.AccAddress(addr2.Bytes())
 | 
				
			||||||
 | 
						suite.testEVMAddr2 = evmutiltestutil.MustNewInternalEVMAddressFromString(addr2.String())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						encodingConfig := app.MakeEncodingConfig()
 | 
				
			||||||
 | 
						suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
 | 
				
			||||||
 | 
						suite.ethSigner = ethtypes.LatestSignerForChainID(tApp.GetEvmKeeper().ChainID())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Genesis states
 | 
				
			||||||
 | 
						evmGs := evmtypes.NewGenesisState(
 | 
				
			||||||
 | 
							evmtypes.NewParams("akava", true, true, evmtypes.DefaultChainConfig()),
 | 
				
			||||||
 | 
							nil,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						feemarketGenesis := feemarkettypes.DefaultGenesisState()
 | 
				
			||||||
 | 
						feemarketGenesis.Params.EnableHeight = 1
 | 
				
			||||||
 | 
						feemarketGenesis.Params.NoBaseFee = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cdpGenState := cdptypes.DefaultGenesisState()
 | 
				
			||||||
 | 
						cdpGenState.Params.GlobalDebtLimit = sdk.NewInt64Coin("usdx", 53000000000000)
 | 
				
			||||||
 | 
						cdpGenState.Params.CollateralParams = cdptypes.CollateralParams{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Denom:                            USDCCoinDenom,
 | 
				
			||||||
 | 
								Type:                             USDCCDPType,
 | 
				
			||||||
 | 
								LiquidationRatio:                 sdk.MustNewDecFromStr("1.01"),
 | 
				
			||||||
 | 
								DebtLimit:                        sdk.NewInt64Coin("usdx", 500000000000),
 | 
				
			||||||
 | 
								StabilityFee:                     sdk.OneDec(),
 | 
				
			||||||
 | 
								AuctionSize:                      sdk.NewIntFromUint64(10000000000),
 | 
				
			||||||
 | 
								LiquidationPenalty:               sdk.MustNewDecFromStr("0.05"),
 | 
				
			||||||
 | 
								CheckCollateralizationIndexCount: sdk.NewInt(10),
 | 
				
			||||||
 | 
								KeeperRewardPercentage:           sdk.MustNewDecFromStr("0.01"),
 | 
				
			||||||
 | 
								SpotMarketID:                     "usdc:usd",
 | 
				
			||||||
 | 
								LiquidationMarketID:              "usdc:usd:30",
 | 
				
			||||||
 | 
								ConversionFactor:                 sdk.NewInt(18),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hardGenState := hardtypes.DefaultGenesisState()
 | 
				
			||||||
 | 
						hardGenState.Params.MoneyMarkets = []hardtypes.MoneyMarket{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Denom: "usdx",
 | 
				
			||||||
 | 
								BorrowLimit: hardtypes.BorrowLimit{
 | 
				
			||||||
 | 
									HasMaxLimit:  true,
 | 
				
			||||||
 | 
									MaximumLimit: sdk.MustNewDecFromStr("100000000000"),
 | 
				
			||||||
 | 
									LoanToValue:  sdk.MustNewDecFromStr("1"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								SpotMarketID:     "usdx:usd",
 | 
				
			||||||
 | 
								ConversionFactor: sdk.NewInt(1_000_000),
 | 
				
			||||||
 | 
								InterestRateModel: hardtypes.InterestRateModel{
 | 
				
			||||||
 | 
									BaseRateAPY:    sdk.MustNewDecFromStr("0.05"),
 | 
				
			||||||
 | 
									BaseMultiplier: sdk.MustNewDecFromStr("2"),
 | 
				
			||||||
 | 
									Kink:           sdk.MustNewDecFromStr("0.8"),
 | 
				
			||||||
 | 
									JumpMultiplier: sdk.MustNewDecFromStr("10"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								ReserveFactor:          sdk.MustNewDecFromStr("0.05"),
 | 
				
			||||||
 | 
								KeeperRewardPercentage: sdk.ZeroDec(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pricefeedGenState := pricefeedtypes.DefaultGenesisState()
 | 
				
			||||||
 | 
						pricefeedGenState.Params.Markets = []pricefeedtypes.Market{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								MarketID:   "usdx:usd",
 | 
				
			||||||
 | 
								BaseAsset:  "usdx",
 | 
				
			||||||
 | 
								QuoteAsset: "usd",
 | 
				
			||||||
 | 
								Oracles:    []sdk.AccAddress{},
 | 
				
			||||||
 | 
								Active:     true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								MarketID:   "usdc:usd",
 | 
				
			||||||
 | 
								BaseAsset:  "usdc",
 | 
				
			||||||
 | 
								QuoteAsset: "usd",
 | 
				
			||||||
 | 
								Oracles:    []sdk.AccAddress{},
 | 
				
			||||||
 | 
								Active:     true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								MarketID:   "usdc:usd:30",
 | 
				
			||||||
 | 
								BaseAsset:  "usdc",
 | 
				
			||||||
 | 
								QuoteAsset: "usd",
 | 
				
			||||||
 | 
								Oracles:    []sdk.AccAddress{},
 | 
				
			||||||
 | 
								Active:     true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pricefeedGenState.PostedPrices = []pricefeedtypes.PostedPrice{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								MarketID:      "usdx:usd",
 | 
				
			||||||
 | 
								OracleAddress: sdk.AccAddress{},
 | 
				
			||||||
 | 
								Price:         sdk.MustNewDecFromStr("1.00"),
 | 
				
			||||||
 | 
								Expiry:        time.Now().Add(1 * time.Hour),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								MarketID:      "usdc:usd",
 | 
				
			||||||
 | 
								OracleAddress: sdk.AccAddress{},
 | 
				
			||||||
 | 
								Price:         sdk.MustNewDecFromStr("1.00"),
 | 
				
			||||||
 | 
								Expiry:        time.Now().Add(1 * time.Hour),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								MarketID:      "usdc:usd:30",
 | 
				
			||||||
 | 
								OracleAddress: sdk.AccAddress{},
 | 
				
			||||||
 | 
								Price:         sdk.MustNewDecFromStr("1.00"),
 | 
				
			||||||
 | 
								Expiry:        time.Now().Add(1 * time.Hour),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						genState := app.GenesisState{
 | 
				
			||||||
 | 
							evmtypes.ModuleName:       cdc.MustMarshalJSON(evmGs),
 | 
				
			||||||
 | 
							feemarkettypes.ModuleName: cdc.MustMarshalJSON(feemarketGenesis),
 | 
				
			||||||
 | 
							cdptypes.ModuleName:       cdc.MustMarshalJSON(&cdpGenState),
 | 
				
			||||||
 | 
							hardtypes.ModuleName:      cdc.MustMarshalJSON(&hardGenState),
 | 
				
			||||||
 | 
							pricefeedtypes.ModuleName: cdc.MustMarshalJSON(&pricefeedGenState),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// funds our test accounts with some ukava
 | 
				
			||||||
 | 
						coinsGenState := app.NewFundedGenStateWithSameCoins(
 | 
				
			||||||
 | 
							tApp.AppCodec(),
 | 
				
			||||||
 | 
							sdk.NewCoins(sdk.NewInt64Coin("ukava", 1e9)),
 | 
				
			||||||
 | 
							[]sdk.AccAddress{suite.testAddr, suite.testAddr2},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tApp.InitializeFromGenesisStatesWithTimeAndChainID(
 | 
				
			||||||
 | 
							time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
				
			||||||
 | 
							ChainID,
 | 
				
			||||||
 | 
							genState,
 | 
				
			||||||
 | 
							coinsGenState,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// consensus key
 | 
				
			||||||
 | 
						consPriv, err := ethsecp256k1.GenerateKey()
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						consAddress := sdk.ConsAddress(consPriv.PubKey().Address())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx := tApp.NewContext(false, tmproto.Header{
 | 
				
			||||||
 | 
							Height:          tApp.LastBlockHeight() + 1,
 | 
				
			||||||
 | 
							ChainID:         ChainID,
 | 
				
			||||||
 | 
							Time:            time.Now().UTC(),
 | 
				
			||||||
 | 
							ProposerAddress: consAddress.Bytes(),
 | 
				
			||||||
 | 
							Version: tmversion.Consensus{
 | 
				
			||||||
 | 
								Block: version.BlockProtocol,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							LastBlockId: tmproto.BlockID{
 | 
				
			||||||
 | 
								Hash: tmhash.Sum([]byte("block_id")),
 | 
				
			||||||
 | 
								PartSetHeader: tmproto.PartSetHeader{
 | 
				
			||||||
 | 
									Total: 11,
 | 
				
			||||||
 | 
									Hash:  tmhash.Sum([]byte("partset_header")),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							AppHash:            tmhash.Sum([]byte("app")),
 | 
				
			||||||
 | 
							DataHash:           tmhash.Sum([]byte("data")),
 | 
				
			||||||
 | 
							EvidenceHash:       tmhash.Sum([]byte("evidence")),
 | 
				
			||||||
 | 
							ValidatorsHash:     tmhash.Sum([]byte("validators")),
 | 
				
			||||||
 | 
							NextValidatorsHash: tmhash.Sum([]byte("next_validators")),
 | 
				
			||||||
 | 
							ConsensusHash:      tmhash.Sum([]byte("consensus")),
 | 
				
			||||||
 | 
							LastResultsHash:    tmhash.Sum([]byte("last_result")),
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						suite.ctx = ctx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We need to set the validator as calling the EVM looks up the validator address
 | 
				
			||||||
 | 
						// https://github.com/tharsis/ethermint/blob/f21592ebfe74da7590eb42ed926dae970b2a9a3f/x/evm/keeper/state_transition.go#L487
 | 
				
			||||||
 | 
						// evmkeeper.EVMConfig() will return error "failed to load evm config" if not set
 | 
				
			||||||
 | 
						valAcc := ðerminttypes.EthAccount{
 | 
				
			||||||
 | 
							BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(consAddress.Bytes()), nil, 0, 0),
 | 
				
			||||||
 | 
							CodeHash:    common.BytesToHash(crypto.Keccak256(nil)).String(),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						tApp.GetAccountKeeper().SetAccount(ctx, valAcc)
 | 
				
			||||||
 | 
						_, testAddresses := app.GeneratePrivKeyAddressPairs(1)
 | 
				
			||||||
 | 
						valAddr := sdk.ValAddress(testAddresses[0].Bytes())
 | 
				
			||||||
 | 
						validator, err := stakingtypes.NewValidator(valAddr, consPriv.PubKey(), stakingtypes.Description{})
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						err = tApp.GetStakingKeeper().SetValidatorByConsAddr(ctx, validator)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						tApp.GetStakingKeeper().SetValidator(ctx, validator)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Deploy an ERC20 contract for USDC
 | 
				
			||||||
 | 
						contractAddr := suite.deployUSDCERC20(tApp, ctx)
 | 
				
			||||||
 | 
						pair := evmutiltypes.NewConversionPair(
 | 
				
			||||||
 | 
							contractAddr,
 | 
				
			||||||
 | 
							USDCCoinDenom,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.usdcEVMAddr = pair.GetAddress()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add a contract to evmutil conversion pair
 | 
				
			||||||
 | 
						suite.evmutilKeeper.SetParams(suite.ctx, evmutiltypes.NewParams(
 | 
				
			||||||
 | 
							evmutiltypes.NewConversionPairs(
 | 
				
			||||||
 | 
								evmutiltypes.NewConversionPair(
 | 
				
			||||||
 | 
									// First contract evmutil module deploys
 | 
				
			||||||
 | 
									evmutiltestutil.MustNewInternalEVMAddressFromString("0x15932E26f5BD4923d46a2b205191C4b5d5f43FE3"),
 | 
				
			||||||
 | 
									"erc20/usdc",
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// allow msgs through evm eip712
 | 
				
			||||||
 | 
						evmKeeper := suite.tApp.GetEvmKeeper()
 | 
				
			||||||
 | 
						params := evmKeeper.GetParams(suite.ctx)
 | 
				
			||||||
 | 
						params.EIP712AllowedMsgs = []evmtypes.EIP712AllowedMsg{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								MsgTypeUrl:       "/kava.evmutil.v1beta1.MsgConvertERC20ToCoin",
 | 
				
			||||||
 | 
								MsgValueTypeName: "MsgValueEVMConvertERC20ToCoin",
 | 
				
			||||||
 | 
								ValueTypes: []evmtypes.EIP712MsgAttrType{
 | 
				
			||||||
 | 
									{Name: "initiator", Type: "string"},
 | 
				
			||||||
 | 
									{Name: "receiver", Type: "string"},
 | 
				
			||||||
 | 
									{Name: "kava_erc20_address", Type: "string"},
 | 
				
			||||||
 | 
									{Name: "amount", Type: "string"},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								MsgTypeUrl:       "/kava.cdp.v1beta1.MsgCreateCDP",
 | 
				
			||||||
 | 
								MsgValueTypeName: "MsgValueCDPCreate",
 | 
				
			||||||
 | 
								ValueTypes: []evmtypes.EIP712MsgAttrType{
 | 
				
			||||||
 | 
									{Name: "sender", Type: "string"},
 | 
				
			||||||
 | 
									{Name: "collateral", Type: "Coin"},
 | 
				
			||||||
 | 
									{Name: "principal", Type: "Coin"},
 | 
				
			||||||
 | 
									{Name: "collateral_type", Type: "string"},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								MsgTypeUrl:       "/kava.cdp.v1beta1.MsgDeposit",
 | 
				
			||||||
 | 
								MsgValueTypeName: "MsgValueCDPDeposit",
 | 
				
			||||||
 | 
								ValueTypes: []evmtypes.EIP712MsgAttrType{
 | 
				
			||||||
 | 
									{Name: "depositor", Type: "string"},
 | 
				
			||||||
 | 
									{Name: "owner", Type: "string"},
 | 
				
			||||||
 | 
									{Name: "collateral", Type: "Coin"},
 | 
				
			||||||
 | 
									{Name: "collateral_type", Type: "string"},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								MsgTypeUrl:       "/kava.hard.v1beta1.MsgDeposit",
 | 
				
			||||||
 | 
								MsgValueTypeName: "MsgValueHardDeposit",
 | 
				
			||||||
 | 
								ValueTypes: []evmtypes.EIP712MsgAttrType{
 | 
				
			||||||
 | 
									{Name: "depositor", Type: "string"},
 | 
				
			||||||
 | 
									{Name: "amount", Type: "Coin[]"},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								MsgTypeUrl:       "/kava.evmutil.v1beta1.MsgConvertCoinToERC20",
 | 
				
			||||||
 | 
								MsgValueTypeName: "MsgValueEVMConvertCoinToERC20",
 | 
				
			||||||
 | 
								ValueTypes: []evmtypes.EIP712MsgAttrType{
 | 
				
			||||||
 | 
									{Name: "initiator", Type: "string"},
 | 
				
			||||||
 | 
									{Name: "receiver", Type: "string"},
 | 
				
			||||||
 | 
									{Name: "amount", Type: "Coin"},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								MsgTypeUrl:       "/kava.cdp.v1beta1.MsgRepayDebt",
 | 
				
			||||||
 | 
								MsgValueTypeName: "MsgValueCDPRepayDebt",
 | 
				
			||||||
 | 
								ValueTypes: []evmtypes.EIP712MsgAttrType{
 | 
				
			||||||
 | 
									{Name: "sender", Type: "string"},
 | 
				
			||||||
 | 
									{Name: "collateral_type", Type: "string"},
 | 
				
			||||||
 | 
									{Name: "payment", Type: "Coin"},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								MsgTypeUrl:       "/kava.hard.v1beta1.MsgWithdraw",
 | 
				
			||||||
 | 
								MsgValueTypeName: "MsgValueHardWithdraw",
 | 
				
			||||||
 | 
								ValueTypes: []evmtypes.EIP712MsgAttrType{
 | 
				
			||||||
 | 
									{Name: "depositor", Type: "string"},
 | 
				
			||||||
 | 
									{Name: "amount", Type: "Coin[]"},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						evmKeeper.SetParams(suite.ctx, params)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// give test address 50k erc20 usdc to begin with
 | 
				
			||||||
 | 
						initBal := suite.getEVMAmount(50_000)
 | 
				
			||||||
 | 
						err = suite.evmutilKeeper.MintERC20(
 | 
				
			||||||
 | 
							ctx,
 | 
				
			||||||
 | 
							pair.GetAddress(), // contractAddr
 | 
				
			||||||
 | 
							suite.testEVMAddr, //receiver
 | 
				
			||||||
 | 
							initBal.BigInt(),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						err = suite.evmutilKeeper.MintERC20(
 | 
				
			||||||
 | 
							ctx,
 | 
				
			||||||
 | 
							pair.GetAddress(),  // contractAddr
 | 
				
			||||||
 | 
							suite.testEVMAddr2, //receiver
 | 
				
			||||||
 | 
							initBal.BigInt(),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We need to commit so that the ethermint feemarket beginblock runs to set the minfee
 | 
				
			||||||
 | 
						// feeMarketKeeper.GetBaseFee() will return nil otherwise
 | 
				
			||||||
 | 
						suite.Commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// set base fee
 | 
				
			||||||
 | 
						suite.tApp.GetFeeMarketKeeper().SetBaseFee(suite.ctx, big.NewInt(100))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *EIP712TestSuite) Commit() {
 | 
				
			||||||
 | 
						_ = suite.tApp.Commit()
 | 
				
			||||||
 | 
						header := suite.ctx.BlockHeader()
 | 
				
			||||||
 | 
						header.Height += 1
 | 
				
			||||||
 | 
						suite.tApp.BeginBlock(abci.RequestBeginBlock{
 | 
				
			||||||
 | 
							Header: header,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// update ctx
 | 
				
			||||||
 | 
						suite.ctx = suite.tApp.NewContext(false, header)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *EIP712TestSuite) deployUSDCERC20(app app.TestApp, ctx sdk.Context) evmutiltypes.InternalEVMAddress {
 | 
				
			||||||
 | 
						// make sure module account is created
 | 
				
			||||||
 | 
						suite.tApp.FundModuleAccount(
 | 
				
			||||||
 | 
							suite.ctx,
 | 
				
			||||||
 | 
							evmutiltypes.ModuleName,
 | 
				
			||||||
 | 
							sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(0))),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						contractAddr, err := suite.evmutilKeeper.DeployTestMintableERC20Contract(suite.ctx, "USDC", "USDC", uint8(18))
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						suite.Require().Greater(len(contractAddr.Address), 0)
 | 
				
			||||||
 | 
						return contractAddr
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *EIP712TestSuite) TestEIP712Tx() {
 | 
				
			||||||
 | 
						encodingConfig := app.MakeEncodingConfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						testcases := []struct {
 | 
				
			||||||
 | 
							name           string
 | 
				
			||||||
 | 
							usdcDepositAmt int64
 | 
				
			||||||
 | 
							usdxToMintAmt  int64
 | 
				
			||||||
 | 
							updateTx       func(txBuilder client.TxBuilder, msgs []sdk.Msg) client.TxBuilder
 | 
				
			||||||
 | 
							updateMsgs     func(msgs []sdk.Msg) []sdk.Msg
 | 
				
			||||||
 | 
							expectedCode   uint32
 | 
				
			||||||
 | 
							failCheckTx    bool
 | 
				
			||||||
 | 
							errMsg         string
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:           "processes deposit eip712 messages successfully",
 | 
				
			||||||
 | 
								usdcDepositAmt: 100,
 | 
				
			||||||
 | 
								usdxToMintAmt:  99,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:           "fails when convertion more erc20 usdc than balance",
 | 
				
			||||||
 | 
								usdcDepositAmt: 51_000,
 | 
				
			||||||
 | 
								usdxToMintAmt:  100,
 | 
				
			||||||
 | 
								errMsg:         "transfer amount exceeds balance",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:           "fails when minting more usdx than allowed",
 | 
				
			||||||
 | 
								usdcDepositAmt: 100,
 | 
				
			||||||
 | 
								usdxToMintAmt:  100,
 | 
				
			||||||
 | 
								errMsg:         "proposed collateral ratio is below liquidation ratio",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:           "fails when trying to convert usdc for another address",
 | 
				
			||||||
 | 
								usdcDepositAmt: 100,
 | 
				
			||||||
 | 
								usdxToMintAmt:  90,
 | 
				
			||||||
 | 
								errMsg:         "unauthorized",
 | 
				
			||||||
 | 
								failCheckTx:    true,
 | 
				
			||||||
 | 
								updateMsgs: func(msgs []sdk.Msg) []sdk.Msg {
 | 
				
			||||||
 | 
									convertMsg := evmutiltypes.NewMsgConvertERC20ToCoin(
 | 
				
			||||||
 | 
										suite.testEVMAddr2,
 | 
				
			||||||
 | 
										suite.testAddr,
 | 
				
			||||||
 | 
										suite.usdcEVMAddr,
 | 
				
			||||||
 | 
										suite.getEVMAmount(100),
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
									msgs[0] = &convertMsg
 | 
				
			||||||
 | 
									return msgs
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:           "fails when trying to convert erc20 for non-whitelisted contract",
 | 
				
			||||||
 | 
								usdcDepositAmt: 100,
 | 
				
			||||||
 | 
								usdxToMintAmt:  90,
 | 
				
			||||||
 | 
								errMsg:         "ERC20 token not enabled to convert to sdk.Coin",
 | 
				
			||||||
 | 
								updateMsgs: func(msgs []sdk.Msg) []sdk.Msg {
 | 
				
			||||||
 | 
									convertMsg := evmutiltypes.NewMsgConvertERC20ToCoin(
 | 
				
			||||||
 | 
										suite.testEVMAddr,
 | 
				
			||||||
 | 
										suite.testAddr,
 | 
				
			||||||
 | 
										suite.testEVMAddr2,
 | 
				
			||||||
 | 
										suite.getEVMAmount(100),
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
									msgs[0] = &convertMsg
 | 
				
			||||||
 | 
									return msgs
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:           "fails when signer tries to send messages with invalid signature",
 | 
				
			||||||
 | 
								usdcDepositAmt: 100,
 | 
				
			||||||
 | 
								usdxToMintAmt:  90,
 | 
				
			||||||
 | 
								failCheckTx:    true,
 | 
				
			||||||
 | 
								errMsg:         "tx intended signer does not match the given signer",
 | 
				
			||||||
 | 
								updateTx: func(txBuilder client.TxBuilder, msgs []sdk.Msg) client.TxBuilder {
 | 
				
			||||||
 | 
									var option *codectypes.Any
 | 
				
			||||||
 | 
									option, _ = codectypes.NewAnyWithValue(ðerminttypes.ExtensionOptionsWeb3Tx{
 | 
				
			||||||
 | 
										FeePayer:         suite.testAddr.String(),
 | 
				
			||||||
 | 
										TypedDataChainID: 1,
 | 
				
			||||||
 | 
										FeePayerSig:      []byte("sig"),
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
									builder, _ := txBuilder.(authtx.ExtensionOptionsTxBuilder)
 | 
				
			||||||
 | 
									builder.SetExtensionOptions(option)
 | 
				
			||||||
 | 
									return txBuilder
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:           "fails when insufficient gas fees are provided",
 | 
				
			||||||
 | 
								usdcDepositAmt: 100,
 | 
				
			||||||
 | 
								usdxToMintAmt:  90,
 | 
				
			||||||
 | 
								errMsg:         "insufficient funds",
 | 
				
			||||||
 | 
								updateTx: func(txBuilder client.TxBuilder, msgs []sdk.Msg) client.TxBuilder {
 | 
				
			||||||
 | 
									bk := suite.tApp.GetBankKeeper()
 | 
				
			||||||
 | 
									gasCoins := bk.GetBalance(suite.ctx, suite.testAddr, "ukava")
 | 
				
			||||||
 | 
									suite.tApp.GetBankKeeper().SendCoins(suite.ctx, suite.testAddr, suite.testAddr2, sdk.NewCoins(gasCoins))
 | 
				
			||||||
 | 
									return txBuilder
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:           "fails when invalid chain id is provided",
 | 
				
			||||||
 | 
								usdcDepositAmt: 100,
 | 
				
			||||||
 | 
								usdxToMintAmt:  90,
 | 
				
			||||||
 | 
								failCheckTx:    true,
 | 
				
			||||||
 | 
								errMsg:         "invalid chain-id",
 | 
				
			||||||
 | 
								updateTx: func(txBuilder client.TxBuilder, msgs []sdk.Msg) client.TxBuilder {
 | 
				
			||||||
 | 
									gasAmt := sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(20)))
 | 
				
			||||||
 | 
									return suite.createTestEIP712CosmosTxBuilder(
 | 
				
			||||||
 | 
										suite.testAddr, suite.testPrivKey, "kavatest_12-1", uint64(helpers.DefaultGenTxGas*10), gasAmt, msgs,
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:           "fails when invalid fee payer is provided",
 | 
				
			||||||
 | 
								usdcDepositAmt: 100,
 | 
				
			||||||
 | 
								usdxToMintAmt:  90,
 | 
				
			||||||
 | 
								failCheckTx:    true,
 | 
				
			||||||
 | 
								errMsg:         "invalid pubkey",
 | 
				
			||||||
 | 
								updateTx: func(txBuilder client.TxBuilder, msgs []sdk.Msg) client.TxBuilder {
 | 
				
			||||||
 | 
									gasAmt := sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(20)))
 | 
				
			||||||
 | 
									return suite.createTestEIP712CosmosTxBuilder(
 | 
				
			||||||
 | 
										suite.testAddr2, suite.testPrivKey2, ChainID, uint64(helpers.DefaultGenTxGas*10), gasAmt, msgs,
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range testcases {
 | 
				
			||||||
 | 
							suite.Run(tc.name, func() {
 | 
				
			||||||
 | 
								suite.SetupTest()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// create messages to convert, mint, and deposit to lend
 | 
				
			||||||
 | 
								usdcAmt := suite.getEVMAmount(tc.usdcDepositAmt)
 | 
				
			||||||
 | 
								convertMsg := evmutiltypes.NewMsgConvertERC20ToCoin(
 | 
				
			||||||
 | 
									suite.testEVMAddr,
 | 
				
			||||||
 | 
									suite.testAddr,
 | 
				
			||||||
 | 
									suite.usdcEVMAddr,
 | 
				
			||||||
 | 
									usdcAmt,
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
								usdxAmt := sdk.NewInt(1_000_000).Mul(sdk.NewInt(tc.usdxToMintAmt))
 | 
				
			||||||
 | 
								mintMsg := cdptypes.NewMsgCreateCDP(
 | 
				
			||||||
 | 
									suite.testAddr,
 | 
				
			||||||
 | 
									sdk.NewCoin(USDCCoinDenom, usdcAmt),
 | 
				
			||||||
 | 
									sdk.NewCoin(cdptypes.DefaultStableDenom, usdxAmt),
 | 
				
			||||||
 | 
									USDCCDPType,
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
								lendMsg := hardtypes.NewMsgDeposit(
 | 
				
			||||||
 | 
									suite.testAddr,
 | 
				
			||||||
 | 
									sdk.NewCoins(sdk.NewCoin(cdptypes.DefaultStableDenom, usdxAmt)),
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
								msgs := []sdk.Msg{
 | 
				
			||||||
 | 
									&convertMsg,
 | 
				
			||||||
 | 
									&mintMsg,
 | 
				
			||||||
 | 
									&lendMsg,
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if tc.updateMsgs != nil {
 | 
				
			||||||
 | 
									msgs = tc.updateMsgs(msgs)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								gasAmt := sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(20)))
 | 
				
			||||||
 | 
								txBuilder := suite.createTestEIP712CosmosTxBuilder(
 | 
				
			||||||
 | 
									suite.testAddr, suite.testPrivKey, ChainID, uint64(helpers.DefaultGenTxGas*10), gasAmt, msgs,
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
								if tc.updateTx != nil {
 | 
				
			||||||
 | 
									txBuilder = tc.updateTx(txBuilder, msgs)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								txBytes, err := encodingConfig.TxConfig.TxEncoder()(txBuilder.GetTx())
 | 
				
			||||||
 | 
								suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								resCheckTx := suite.tApp.CheckTx(
 | 
				
			||||||
 | 
									abci.RequestCheckTx{
 | 
				
			||||||
 | 
										Tx:   txBytes,
 | 
				
			||||||
 | 
										Type: abci.CheckTxType_New,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
								if !tc.failCheckTx {
 | 
				
			||||||
 | 
									suite.Require().Equal(resCheckTx.Code, uint32(0), resCheckTx.Log)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									suite.Require().NotEqual(resCheckTx.Code, uint32(0), resCheckTx.Log)
 | 
				
			||||||
 | 
									suite.Require().Contains(resCheckTx.Log, tc.errMsg)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								resDeliverTx := suite.tApp.DeliverTx(
 | 
				
			||||||
 | 
									abci.RequestDeliverTx{
 | 
				
			||||||
 | 
										Tx: txBytes,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if tc.errMsg == "" {
 | 
				
			||||||
 | 
									suite.Require().Equal(resDeliverTx.Code, uint32(0), resDeliverTx.Log)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// validate user cosmos erc20/usd balance
 | 
				
			||||||
 | 
									bk := suite.tApp.GetBankKeeper()
 | 
				
			||||||
 | 
									amt := bk.GetBalance(suite.ctx, suite.testAddr, USDCCoinDenom)
 | 
				
			||||||
 | 
									suite.Require().Equal(sdk.ZeroInt(), amt.Amount)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// validate cdp
 | 
				
			||||||
 | 
									cdp, found := suite.tApp.GetCDPKeeper().GetCdpByOwnerAndCollateralType(suite.ctx, suite.testAddr, USDCCDPType)
 | 
				
			||||||
 | 
									suite.Require().True(found)
 | 
				
			||||||
 | 
									suite.Require().Equal(suite.testAddr, cdp.Owner)
 | 
				
			||||||
 | 
									suite.Require().Equal(sdk.NewCoin(USDCCoinDenom, suite.getEVMAmount(100)), cdp.Collateral)
 | 
				
			||||||
 | 
									suite.Require().Equal(sdk.NewCoin("usdx", sdk.NewInt(99_000_000)), cdp.Principal)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// validate hard
 | 
				
			||||||
 | 
									hardDeposit, found := suite.tApp.GetHardKeeper().GetDeposit(suite.ctx, suite.testAddr)
 | 
				
			||||||
 | 
									suite.Require().True(found)
 | 
				
			||||||
 | 
									suite.Require().Equal(suite.testAddr, hardDeposit.Depositor)
 | 
				
			||||||
 | 
									suite.Require().Equal(sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(99_000_000))), hardDeposit.Amount)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									suite.Require().NotEqual(resDeliverTx.Code, uint32(0), resCheckTx.Log)
 | 
				
			||||||
 | 
									suite.Require().Contains(resDeliverTx.Log, tc.errMsg)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *EIP712TestSuite) TestEIP712Tx_DepositAndWithdraw() {
 | 
				
			||||||
 | 
						encodingConfig := app.MakeEncodingConfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// create deposit msgs
 | 
				
			||||||
 | 
						usdcAmt := suite.getEVMAmount(100)
 | 
				
			||||||
 | 
						convertMsg := evmutiltypes.NewMsgConvertERC20ToCoin(
 | 
				
			||||||
 | 
							suite.testEVMAddr,
 | 
				
			||||||
 | 
							suite.testAddr,
 | 
				
			||||||
 | 
							suite.usdcEVMAddr,
 | 
				
			||||||
 | 
							usdcAmt,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						usdxAmt := sdk.NewInt(1_000_000).Mul(sdk.NewInt(99))
 | 
				
			||||||
 | 
						mintMsg := cdptypes.NewMsgCreateCDP(
 | 
				
			||||||
 | 
							suite.testAddr,
 | 
				
			||||||
 | 
							sdk.NewCoin(USDCCoinDenom, usdcAmt),
 | 
				
			||||||
 | 
							sdk.NewCoin(cdptypes.DefaultStableDenom, usdxAmt),
 | 
				
			||||||
 | 
							USDCCDPType,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						lendMsg := hardtypes.NewMsgDeposit(
 | 
				
			||||||
 | 
							suite.testAddr,
 | 
				
			||||||
 | 
							sdk.NewCoins(sdk.NewCoin(cdptypes.DefaultStableDenom, usdxAmt)),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						depositMsgs := []sdk.Msg{
 | 
				
			||||||
 | 
							&convertMsg,
 | 
				
			||||||
 | 
							&mintMsg,
 | 
				
			||||||
 | 
							&lendMsg,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// deliver deposit msg
 | 
				
			||||||
 | 
						gasAmt := sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(20)))
 | 
				
			||||||
 | 
						txBuilder := suite.createTestEIP712CosmosTxBuilder(
 | 
				
			||||||
 | 
							suite.testAddr, suite.testPrivKey, ChainID, uint64(helpers.DefaultGenTxGas*10), gasAmt, depositMsgs,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						txBytes, err := encodingConfig.TxConfig.TxEncoder()(txBuilder.GetTx())
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						resDeliverTx := suite.tApp.DeliverTx(
 | 
				
			||||||
 | 
							abci.RequestDeliverTx{
 | 
				
			||||||
 | 
								Tx: txBytes,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().Equal(resDeliverTx.Code, uint32(0), resDeliverTx.Log)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// validate hard
 | 
				
			||||||
 | 
						hardDeposit, found := suite.tApp.GetHardKeeper().GetDeposit(suite.ctx, suite.testAddr)
 | 
				
			||||||
 | 
						suite.Require().True(found)
 | 
				
			||||||
 | 
						suite.Require().Equal(suite.testAddr, hardDeposit.Depositor)
 | 
				
			||||||
 | 
						suite.Require().Equal(sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(99_000_000))), hardDeposit.Amount)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// validate erc20 balance
 | 
				
			||||||
 | 
						coinBal, err := suite.evmutilKeeper.QueryERC20BalanceOf(suite.ctx, suite.usdcEVMAddr, suite.testEVMAddr)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						suite.Require().Equal(suite.getEVMAmount(49_900).BigInt(), coinBal)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// withdraw msgs
 | 
				
			||||||
 | 
						withdrawConvertMsg := evmutiltypes.NewMsgConvertCoinToERC20(
 | 
				
			||||||
 | 
							suite.testAddr.String(),
 | 
				
			||||||
 | 
							suite.testEVMAddr.String(),
 | 
				
			||||||
 | 
							sdk.NewCoin(USDCCoinDenom, usdcAmt),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						cdpWithdrawMsg := cdptypes.NewMsgRepayDebt(
 | 
				
			||||||
 | 
							suite.testAddr,
 | 
				
			||||||
 | 
							USDCCDPType,
 | 
				
			||||||
 | 
							sdk.NewCoin(cdptypes.DefaultStableDenom, usdxAmt),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						hardWithdrawMsg := hardtypes.NewMsgWithdraw(
 | 
				
			||||||
 | 
							suite.testAddr,
 | 
				
			||||||
 | 
							sdk.NewCoins(sdk.NewCoin(cdptypes.DefaultStableDenom, usdxAmt)),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						withdrawMsgs := []sdk.Msg{
 | 
				
			||||||
 | 
							&hardWithdrawMsg,
 | 
				
			||||||
 | 
							&cdpWithdrawMsg,
 | 
				
			||||||
 | 
							&withdrawConvertMsg,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// deliver withdraw msg
 | 
				
			||||||
 | 
						txBuilder = suite.createTestEIP712CosmosTxBuilder(
 | 
				
			||||||
 | 
							suite.testAddr, suite.testPrivKey, ChainID, uint64(helpers.DefaultGenTxGas*10), gasAmt, withdrawMsgs,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						txBytes, err = encodingConfig.TxConfig.TxEncoder()(txBuilder.GetTx())
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						resDeliverTx = suite.tApp.DeliverTx(
 | 
				
			||||||
 | 
							abci.RequestDeliverTx{
 | 
				
			||||||
 | 
								Tx: txBytes,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().Equal(resDeliverTx.Code, uint32(0), resDeliverTx.Log)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// validate hard & cdp should be repayed
 | 
				
			||||||
 | 
						_, found = suite.tApp.GetHardKeeper().GetDeposit(suite.ctx, suite.testAddr)
 | 
				
			||||||
 | 
						suite.Require().False(found)
 | 
				
			||||||
 | 
						_, found = suite.tApp.GetCDPKeeper().GetCdpByOwnerAndCollateralType(suite.ctx, suite.testAddr, USDCCDPType)
 | 
				
			||||||
 | 
						suite.Require().False(found)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// validate user cosmos erc20/usd balance
 | 
				
			||||||
 | 
						bk := suite.tApp.GetBankKeeper()
 | 
				
			||||||
 | 
						amt := bk.GetBalance(suite.ctx, suite.testAddr, USDCCoinDenom)
 | 
				
			||||||
 | 
						suite.Require().Equal(sdk.ZeroInt(), amt.Amount)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// validate erc20 balance
 | 
				
			||||||
 | 
						coinBal, err = suite.evmutilKeeper.QueryERC20BalanceOf(suite.ctx, suite.usdcEVMAddr, suite.testEVMAddr)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						suite.Require().Equal(suite.getEVMAmount(50_000).BigInt(), coinBal)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestEIP712Suite(t *testing.T) {
 | 
				
			||||||
 | 
						suite.Run(t, new(EIP712TestSuite))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -210,7 +210,7 @@ var (
 | 
				
			|||||||
		govtypes.ModuleName:             {authtypes.Burner},
 | 
							govtypes.ModuleName:             {authtypes.Burner},
 | 
				
			||||||
		ibctransfertypes.ModuleName:     {authtypes.Minter, authtypes.Burner},
 | 
							ibctransfertypes.ModuleName:     {authtypes.Minter, authtypes.Burner},
 | 
				
			||||||
		evmtypes.ModuleName:             {authtypes.Minter, authtypes.Burner}, // used for secure addition and subtraction of balance using module account
 | 
							evmtypes.ModuleName:             {authtypes.Minter, authtypes.Burner}, // used for secure addition and subtraction of balance using module account
 | 
				
			||||||
		evmutiltypes.ModuleName:         nil,
 | 
							evmutiltypes.ModuleName:         {authtypes.Minter, authtypes.Burner},
 | 
				
			||||||
		kavadisttypes.KavaDistMacc:      {authtypes.Minter},
 | 
							kavadisttypes.KavaDistMacc:      {authtypes.Minter},
 | 
				
			||||||
		auctiontypes.ModuleName:         nil,
 | 
							auctiontypes.ModuleName:         nil,
 | 
				
			||||||
		issuancetypes.ModuleAccountName: {authtypes.Minter, authtypes.Burner},
 | 
							issuancetypes.ModuleAccountName: {authtypes.Minter, authtypes.Burner},
 | 
				
			||||||
@ -392,6 +392,7 @@ func NewApp(
 | 
				
			|||||||
	feemarketSubspace := app.paramsKeeper.Subspace(feemarkettypes.ModuleName)
 | 
						feemarketSubspace := app.paramsKeeper.Subspace(feemarkettypes.ModuleName)
 | 
				
			||||||
	evmSubspace := app.paramsKeeper.Subspace(evmtypes.ModuleName)
 | 
						evmSubspace := app.paramsKeeper.Subspace(evmtypes.ModuleName)
 | 
				
			||||||
	bridgeSubspace := app.paramsKeeper.Subspace(bridgetypes.ModuleName)
 | 
						bridgeSubspace := app.paramsKeeper.Subspace(bridgetypes.ModuleName)
 | 
				
			||||||
 | 
						evmutilSubspace := app.paramsKeeper.Subspace(evmutiltypes.ModuleName)
 | 
				
			||||||
	earnSubspace := app.paramsKeeper.Subspace(earntypes.ModuleName)
 | 
						earnSubspace := app.paramsKeeper.Subspace(earntypes.ModuleName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bApp.SetParamStore(
 | 
						bApp.SetParamStore(
 | 
				
			||||||
@ -491,6 +492,9 @@ func NewApp(
 | 
				
			|||||||
	app.evmutilKeeper = evmutilkeeper.NewKeeper(
 | 
						app.evmutilKeeper = evmutilkeeper.NewKeeper(
 | 
				
			||||||
		app.appCodec,
 | 
							app.appCodec,
 | 
				
			||||||
		keys[evmutiltypes.StoreKey],
 | 
							keys[evmutiltypes.StoreKey],
 | 
				
			||||||
 | 
							evmutilSubspace,
 | 
				
			||||||
 | 
							app.bankKeeper,
 | 
				
			||||||
 | 
							app.accountKeeper,
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	evmBankKeeper := evmutilkeeper.NewEvmBankKeeper(app.evmutilKeeper, app.bankKeeper, app.accountKeeper)
 | 
						evmBankKeeper := evmutilkeeper.NewEvmBankKeeper(app.evmutilKeeper, app.bankKeeper, app.accountKeeper)
 | 
				
			||||||
@ -500,6 +504,8 @@ func NewApp(
 | 
				
			|||||||
		options.EVMTrace,
 | 
							options.EVMTrace,
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						app.evmutilKeeper.SetEvmKeeper(app.evmKeeper)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	app.kavadistKeeper = kavadistkeeper.NewKeeper(
 | 
						app.kavadistKeeper = kavadistkeeper.NewKeeper(
 | 
				
			||||||
		appCodec,
 | 
							appCodec,
 | 
				
			||||||
		keys[kavadisttypes.StoreKey],
 | 
							keys[kavadisttypes.StoreKey],
 | 
				
			||||||
 | 
				
			|||||||
@ -22,12 +22,14 @@ import (
 | 
				
			|||||||
	paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper"
 | 
						paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper"
 | 
				
			||||||
	slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper"
 | 
						slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper"
 | 
				
			||||||
	stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
 | 
						stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
 | 
				
			||||||
 | 
						bridgekeeper "github.com/kava-labs/kava-bridge/x/bridge/keeper"
 | 
				
			||||||
	"github.com/stretchr/testify/require"
 | 
						"github.com/stretchr/testify/require"
 | 
				
			||||||
	abci "github.com/tendermint/tendermint/abci/types"
 | 
						abci "github.com/tendermint/tendermint/abci/types"
 | 
				
			||||||
	"github.com/tendermint/tendermint/libs/log"
 | 
						"github.com/tendermint/tendermint/libs/log"
 | 
				
			||||||
	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
 | 
						tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
 | 
				
			||||||
	tmdb "github.com/tendermint/tm-db"
 | 
						tmdb "github.com/tendermint/tm-db"
 | 
				
			||||||
	evmkeeper "github.com/tharsis/ethermint/x/evm/keeper"
 | 
						evmkeeper "github.com/tharsis/ethermint/x/evm/keeper"
 | 
				
			||||||
 | 
						feemarketkeeper "github.com/tharsis/ethermint/x/feemarket/keeper"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auctionkeeper "github.com/kava-labs/kava/x/auction/keeper"
 | 
						auctionkeeper "github.com/kava-labs/kava/x/auction/keeper"
 | 
				
			||||||
	bep3keeper "github.com/kava-labs/kava/x/bep3/keeper"
 | 
						bep3keeper "github.com/kava-labs/kava/x/bep3/keeper"
 | 
				
			||||||
@ -107,6 +109,8 @@ func (tApp TestApp) GetIncentiveKeeper() incentivekeeper.Keeper { return tApp.in
 | 
				
			|||||||
func (tApp TestApp) GetEvmutilKeeper() evmutilkeeper.Keeper     { return tApp.evmutilKeeper }
 | 
					func (tApp TestApp) GetEvmutilKeeper() evmutilkeeper.Keeper     { return tApp.evmutilKeeper }
 | 
				
			||||||
func (tApp TestApp) GetEvmKeeper() *evmkeeper.Keeper            { return tApp.evmKeeper }
 | 
					func (tApp TestApp) GetEvmKeeper() *evmkeeper.Keeper            { return tApp.evmKeeper }
 | 
				
			||||||
func (tApp TestApp) GetSavingsKeeper() savingskeeper.Keeper     { return tApp.savingsKeeper }
 | 
					func (tApp TestApp) GetSavingsKeeper() savingskeeper.Keeper     { return tApp.savingsKeeper }
 | 
				
			||||||
 | 
					func (tApp TestApp) GetBridgeKeeper() bridgekeeper.Keeper       { return tApp.bridgeKeeper }
 | 
				
			||||||
 | 
					func (tApp TestApp) GetFeeMarketKeeper() feemarketkeeper.Keeper { return tApp.feeMarketKeeper }
 | 
				
			||||||
func (tApp TestApp) GetEarnKeeper() earnkeeper.Keeper           { return tApp.earnKeeper }
 | 
					func (tApp TestApp) GetEarnKeeper() earnkeeper.Keeper           { return tApp.earnKeeper }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LegacyAmino returns the app's amino codec.
 | 
					// LegacyAmino returns the app's amino codec.
 | 
				
			||||||
 | 
				
			|||||||
@ -214,9 +214,27 @@
 | 
				
			|||||||
  
 | 
					  
 | 
				
			||||||
    - [Msg](#kava.earn.v1beta1.Msg)
 | 
					    - [Msg](#kava.earn.v1beta1.Msg)
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
 | 
					- [kava/evmutil/v1beta1/conversion_pair.proto](#kava/evmutil/v1beta1/conversion_pair.proto)
 | 
				
			||||||
 | 
					    - [ConversionPair](#kava.evmutil.v1beta1.ConversionPair)
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
- [kava/evmutil/v1beta1/genesis.proto](#kava/evmutil/v1beta1/genesis.proto)
 | 
					- [kava/evmutil/v1beta1/genesis.proto](#kava/evmutil/v1beta1/genesis.proto)
 | 
				
			||||||
    - [Account](#kava.evmutil.v1beta1.Account)
 | 
					    - [Account](#kava.evmutil.v1beta1.Account)
 | 
				
			||||||
    - [GenesisState](#kava.evmutil.v1beta1.GenesisState)
 | 
					    - [GenesisState](#kava.evmutil.v1beta1.GenesisState)
 | 
				
			||||||
 | 
					    - [Params](#kava.evmutil.v1beta1.Params)
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					- [kava/evmutil/v1beta1/query.proto](#kava/evmutil/v1beta1/query.proto)
 | 
				
			||||||
 | 
					    - [QueryParamsRequest](#kava.evmutil.v1beta1.QueryParamsRequest)
 | 
				
			||||||
 | 
					    - [QueryParamsResponse](#kava.evmutil.v1beta1.QueryParamsResponse)
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    - [Query](#kava.evmutil.v1beta1.Query)
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					- [kava/evmutil/v1beta1/tx.proto](#kava/evmutil/v1beta1/tx.proto)
 | 
				
			||||||
 | 
					    - [MsgConvertCoinToERC20](#kava.evmutil.v1beta1.MsgConvertCoinToERC20)
 | 
				
			||||||
 | 
					    - [MsgConvertCoinToERC20Response](#kava.evmutil.v1beta1.MsgConvertCoinToERC20Response)
 | 
				
			||||||
 | 
					    - [MsgConvertERC20ToCoin](#kava.evmutil.v1beta1.MsgConvertERC20ToCoin)
 | 
				
			||||||
 | 
					    - [MsgConvertERC20ToCoinResponse](#kava.evmutil.v1beta1.MsgConvertERC20ToCoinResponse)
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    - [Msg](#kava.evmutil.v1beta1.Msg)
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
- [kava/hard/v1beta1/hard.proto](#kava/hard/v1beta1/hard.proto)
 | 
					- [kava/hard/v1beta1/hard.proto](#kava/hard/v1beta1/hard.proto)
 | 
				
			||||||
    - [Borrow](#kava.hard.v1beta1.Borrow)
 | 
					    - [Borrow](#kava.hard.v1beta1.Borrow)
 | 
				
			||||||
@ -3163,6 +3181,39 @@ Msg defines the earn Msg service.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<a name="kava/evmutil/v1beta1/conversion_pair.proto"></a>
 | 
				
			||||||
 | 
					<p align="right"><a href="#top">Top</a></p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## kava/evmutil/v1beta1/conversion_pair.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<a name="kava.evmutil.v1beta1.ConversionPair"></a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### ConversionPair
 | 
				
			||||||
 | 
					ConversionPair defines a Kava ERC20 address and corresponding denom that is
 | 
				
			||||||
 | 
					allowed to be converted between ERC20 and sdk.Coin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					| Field | Type | Label | Description |
 | 
				
			||||||
 | 
					| ----- | ---- | ----- | ----------- |
 | 
				
			||||||
 | 
					| `kava_erc20_address` | [bytes](#bytes) |  | ERC20 address of the token on the Kava EVM |
 | 
				
			||||||
 | 
					| `denom` | [string](#string) |  | Denom of the corresponding sdk.Coin |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 <!-- end messages -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 <!-- end enums -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 <!-- end HasExtensions -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 <!-- end services -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<a name="kava/evmutil/v1beta1/genesis.proto"></a>
 | 
					<a name="kava/evmutil/v1beta1/genesis.proto"></a>
 | 
				
			||||||
<p align="right"><a href="#top">Top</a></p>
 | 
					<p align="right"><a href="#top">Top</a></p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -3195,6 +3246,22 @@ GenesisState defines the evmutil module's genesis state.
 | 
				
			|||||||
| Field | Type | Label | Description |
 | 
					| Field | Type | Label | Description |
 | 
				
			||||||
| ----- | ---- | ----- | ----------- |
 | 
					| ----- | ---- | ----- | ----------- |
 | 
				
			||||||
| `accounts` | [Account](#kava.evmutil.v1beta1.Account) | repeated |  |
 | 
					| `accounts` | [Account](#kava.evmutil.v1beta1.Account) | repeated |  |
 | 
				
			||||||
 | 
					| `params` | [Params](#kava.evmutil.v1beta1.Params) |  | params defines all the parameters of the module. |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<a name="kava.evmutil.v1beta1.Params"></a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Params
 | 
				
			||||||
 | 
					Params defines the evmutil module params
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					| Field | Type | Label | Description |
 | 
				
			||||||
 | 
					| ----- | ---- | ----- | ----------- |
 | 
				
			||||||
 | 
					| `enabled_conversion_pairs` | [ConversionPair](#kava.evmutil.v1beta1.ConversionPair) | repeated | enabled_conversion_pairs defines the list of conversion pairs allowed to be converted between Kava ERC20 and sdk.Coin |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -3210,6 +3277,140 @@ GenesisState defines the evmutil module's genesis state.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<a name="kava/evmutil/v1beta1/query.proto"></a>
 | 
				
			||||||
 | 
					<p align="right"><a href="#top">Top</a></p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## kava/evmutil/v1beta1/query.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<a name="kava.evmutil.v1beta1.QueryParamsRequest"></a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### QueryParamsRequest
 | 
				
			||||||
 | 
					QueryParamsRequest defines the request type for querying x/evmutil parameters.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<a name="kava.evmutil.v1beta1.QueryParamsResponse"></a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### QueryParamsResponse
 | 
				
			||||||
 | 
					QueryParamsResponse defines the response type for querying x/evmutil parameters.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					| Field | Type | Label | Description |
 | 
				
			||||||
 | 
					| ----- | ---- | ----- | ----------- |
 | 
				
			||||||
 | 
					| `params` | [Params](#kava.evmutil.v1beta1.Params) |  |  |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 <!-- end messages -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 <!-- end enums -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 <!-- end HasExtensions -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<a name="kava.evmutil.v1beta1.Query"></a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Query
 | 
				
			||||||
 | 
					Query defines the gRPC querier service for evmutil module
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint |
 | 
				
			||||||
 | 
					| ----------- | ------------ | ------------- | ------------| ------- | -------- |
 | 
				
			||||||
 | 
					| `Params` | [QueryParamsRequest](#kava.evmutil.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#kava.evmutil.v1beta1.QueryParamsResponse) | Params queries all parameters of the evmutil module. | GET|/kava/evmutil/v1beta1/params|
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 <!-- end services -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<a name="kava/evmutil/v1beta1/tx.proto"></a>
 | 
				
			||||||
 | 
					<p align="right"><a href="#top">Top</a></p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## kava/evmutil/v1beta1/tx.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<a name="kava.evmutil.v1beta1.MsgConvertCoinToERC20"></a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### MsgConvertCoinToERC20
 | 
				
			||||||
 | 
					MsgConvertCoinToERC20 defines a conversion from sdk.Coin to Kava ERC20.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					| Field | Type | Label | Description |
 | 
				
			||||||
 | 
					| ----- | ---- | ----- | ----------- |
 | 
				
			||||||
 | 
					| `initiator` | [string](#string) |  | Kava bech32 address initiating the conversion. |
 | 
				
			||||||
 | 
					| `receiver` | [string](#string) |  | EVM 0x hex address that will receive the converted Kava ERC20 tokens. |
 | 
				
			||||||
 | 
					| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) |  | Amount is the sdk.Coin amount to convert. |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<a name="kava.evmutil.v1beta1.MsgConvertCoinToERC20Response"></a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### MsgConvertCoinToERC20Response
 | 
				
			||||||
 | 
					MsgConvertCoinToERC20Response defines the response value from Msg/ConvertCoinToERC20.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<a name="kava.evmutil.v1beta1.MsgConvertERC20ToCoin"></a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### MsgConvertERC20ToCoin
 | 
				
			||||||
 | 
					MsgConvertERC20ToCoin defines a conversion from Kava ERC20 to sdk.Coin.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					| Field | Type | Label | Description |
 | 
				
			||||||
 | 
					| ----- | ---- | ----- | ----------- |
 | 
				
			||||||
 | 
					| `initiator` | [string](#string) |  | EVM 0x hex address initiating the conversion. |
 | 
				
			||||||
 | 
					| `receiver` | [string](#string) |  | Kava bech32 address that will receive the converted sdk.Coin. |
 | 
				
			||||||
 | 
					| `kava_erc20_address` | [string](#string) |  | EVM 0x hex address of the ERC20 contract. |
 | 
				
			||||||
 | 
					| `amount` | [string](#string) |  | ERC20 token amount to convert. |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<a name="kava.evmutil.v1beta1.MsgConvertERC20ToCoinResponse"></a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### MsgConvertERC20ToCoinResponse
 | 
				
			||||||
 | 
					MsgConvertERC20ToCoinResponse defines the response value from
 | 
				
			||||||
 | 
					Msg/MsgConvertERC20ToCoin.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 <!-- end messages -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 <!-- end enums -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 <!-- end HasExtensions -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<a name="kava.evmutil.v1beta1.Msg"></a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Msg
 | 
				
			||||||
 | 
					Msg defines the evmutil Msg service.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint |
 | 
				
			||||||
 | 
					| ----------- | ------------ | ------------- | ------------| ------- | -------- |
 | 
				
			||||||
 | 
					| `ConvertCoinToERC20` | [MsgConvertCoinToERC20](#kava.evmutil.v1beta1.MsgConvertCoinToERC20) | [MsgConvertCoinToERC20Response](#kava.evmutil.v1beta1.MsgConvertCoinToERC20Response) | ConvertCoinToERC20 defines a method for converting sdk.Coin to Kava ERC20. | |
 | 
				
			||||||
 | 
					| `ConvertERC20ToCoin` | [MsgConvertERC20ToCoin](#kava.evmutil.v1beta1.MsgConvertERC20ToCoin) | [MsgConvertERC20ToCoinResponse](#kava.evmutil.v1beta1.MsgConvertERC20ToCoinResponse) | ConvertERC20ToCoin defines a method for converting Kava ERC20 to sdk.Coin. | |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 <!-- end services -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<a name="kava/hard/v1beta1/hard.proto"></a>
 | 
					<a name="kava/hard/v1beta1/hard.proto"></a>
 | 
				
			||||||
<p align="right"><a href="#top">Top</a></p>
 | 
					<p align="right"><a href="#top">Top</a></p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										6
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								go.mod
									
									
									
									
									
								
							@ -12,7 +12,7 @@ require (
 | 
				
			|||||||
	github.com/golang/protobuf v1.5.2
 | 
						github.com/golang/protobuf v1.5.2
 | 
				
			||||||
	github.com/gorilla/mux v1.8.0
 | 
						github.com/gorilla/mux v1.8.0
 | 
				
			||||||
	github.com/grpc-ecosystem/grpc-gateway v1.16.0
 | 
						github.com/grpc-ecosystem/grpc-gateway v1.16.0
 | 
				
			||||||
	github.com/kava-labs/kava-bridge v0.2.0
 | 
						github.com/kava-labs/kava-bridge v0.2.1-0.20220707160130-6199d30c5fe6
 | 
				
			||||||
	github.com/spf13/cast v1.4.1
 | 
						github.com/spf13/cast v1.4.1
 | 
				
			||||||
	github.com/spf13/cobra v1.4.0
 | 
						github.com/spf13/cobra v1.4.0
 | 
				
			||||||
	github.com/stretchr/testify v1.7.1
 | 
						github.com/stretchr/testify v1.7.1
 | 
				
			||||||
@ -158,7 +158,7 @@ replace (
 | 
				
			|||||||
	// Use the cosmos keyring code
 | 
						// Use the cosmos keyring code
 | 
				
			||||||
	github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76
 | 
						github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76
 | 
				
			||||||
	// Use cosmos-sdk fork with backported fix for unsafe-reset-all
 | 
						// Use cosmos-sdk fork with backported fix for unsafe-reset-all
 | 
				
			||||||
	github.com/cosmos/cosmos-sdk => github.com/kava-labs/cosmos-sdk v0.45.4-kava.1
 | 
						github.com/cosmos/cosmos-sdk => github.com/kava-labs/cosmos-sdk v0.45.4-kava.3
 | 
				
			||||||
	// See https://github.com/cosmos/cosmos-sdk/pull/10401, https://github.com/cosmos/cosmos-sdk/commit/0592ba6158cd0bf49d894be1cef4faeec59e8320
 | 
						// See https://github.com/cosmos/cosmos-sdk/pull/10401, https://github.com/cosmos/cosmos-sdk/commit/0592ba6158cd0bf49d894be1cef4faeec59e8320
 | 
				
			||||||
	github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0
 | 
						github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0
 | 
				
			||||||
	// Use the cosmos modified protobufs
 | 
						// Use the cosmos modified protobufs
 | 
				
			||||||
@ -166,7 +166,7 @@ replace (
 | 
				
			|||||||
	// Use rocksdb 7.1.2
 | 
						// Use rocksdb 7.1.2
 | 
				
			||||||
	github.com/tendermint/tm-db => github.com/kava-labs/tm-db v0.6.7-kava.1
 | 
						github.com/tendermint/tm-db => github.com/kava-labs/tm-db v0.6.7-kava.1
 | 
				
			||||||
	// Use ethermint fork that respects min-gas-price with NoBaseFee true and london enabled
 | 
						// Use ethermint fork that respects min-gas-price with NoBaseFee true and london enabled
 | 
				
			||||||
	github.com/tharsis/ethermint => github.com/Kava-Labs/ethermint v0.14.0-kava-v17.3
 | 
						github.com/tharsis/ethermint => github.com/Kava-Labs/ethermint v0.14.0-kava-v17.5
 | 
				
			||||||
	// Make sure that we use grpc compatible with cosmos
 | 
						// Make sure that we use grpc compatible with cosmos
 | 
				
			||||||
	google.golang.org/grpc => google.golang.org/grpc v1.33.2
 | 
						google.golang.org/grpc => google.golang.org/grpc v1.33.2
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										44
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								go.sum
									
									
									
									
									
								
							@ -1,4 +1,5 @@
 | 
				
			|||||||
bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM=
 | 
					bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM=
 | 
				
			||||||
 | 
					bou.ke/monkey v1.0.1/go.mod h1:FgHuK96Rv2Nlf+0u1OOVDpCMdsWyOFmeeketDHE7LIg=
 | 
				
			||||||
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 | 
					cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 | 
				
			||||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 | 
					cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 | 
				
			||||||
cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
 | 
					cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
 | 
				
			||||||
@ -100,14 +101,9 @@ github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t
 | 
				
			|||||||
github.com/DataDog/zstd v1.4.8/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
 | 
					github.com/DataDog/zstd v1.4.8/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
 | 
				
			||||||
github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
 | 
					github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
 | 
				
			||||||
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
 | 
					github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
 | 
				
			||||||
github.com/Kava-Labs/ethermint v0.14.0-kava-v17.3 h1:4+Lg+qmJAL8ey9ns85WqxQkYCCKvN8RyuoxQ7CHJRPU=
 | 
					github.com/Kava-Labs/ethermint v0.14.0-kava-v17.5 h1:oQH7YQ5MBExEbFQZ95UMdXimYLYHAc9su2yIsJ9+ISs=
 | 
				
			||||||
github.com/Kava-Labs/ethermint v0.14.0-kava-v17.3/go.mod h1:k6rs7PRm04GhQZhCmwYLJGQ5czvgbZqcrqpR630+Rik=
 | 
					github.com/Kava-Labs/ethermint v0.14.0-kava-v17.5/go.mod h1:/x9PysLnuLxE1/33pHf8W+TQJFJh7XE49g05uJoQ7kw=
 | 
				
			||||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
 | 
					github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
 | 
				
			||||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
 | 
					 | 
				
			||||||
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
 | 
					 | 
				
			||||||
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
 | 
					 | 
				
			||||||
github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
 | 
					 | 
				
			||||||
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
 | 
					 | 
				
			||||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
 | 
					github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
 | 
				
			||||||
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
 | 
					github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
 | 
				
			||||||
github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY=
 | 
					github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY=
 | 
				
			||||||
@ -135,6 +131,7 @@ github.com/adlio/schema v1.3.0 h1:eSVYLxYWbm/6ReZBCkLw4Fz7uqC+ZNoPvA39bOwi52A=
 | 
				
			|||||||
github.com/adlio/schema v1.3.0/go.mod h1:51QzxkpeFs6lRY11kPye26IaFPOV+HqEj01t5aXXKfs=
 | 
					github.com/adlio/schema v1.3.0/go.mod h1:51QzxkpeFs6lRY11kPye26IaFPOV+HqEj01t5aXXKfs=
 | 
				
			||||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
 | 
					github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
 | 
				
			||||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
 | 
					github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
 | 
				
			||||||
 | 
					github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0=
 | 
				
			||||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
 | 
					github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
 | 
				
			||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 | 
					github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 | 
				
			||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 | 
					github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 | 
				
			||||||
@ -147,8 +144,6 @@ github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2uc
 | 
				
			|||||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
 | 
					github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
 | 
				
			||||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
 | 
					github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
 | 
				
			||||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 | 
					github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 | 
				
			||||||
github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
 | 
					 | 
				
			||||||
github.com/aokoli/goutils v1.1.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
 | 
					 | 
				
			||||||
github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0=
 | 
					github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0=
 | 
				
			||||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
 | 
					github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
 | 
				
			||||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
 | 
					github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
 | 
				
			||||||
@ -186,6 +181,7 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 | 
				
			|||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 | 
					github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 | 
				
			||||||
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
 | 
					github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
 | 
				
			||||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
 | 
					github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
 | 
				
			||||||
 | 
					github.com/binance-chain/tss-lib v1.3.3/go.mod h1:xfM6gCPA61WIV5q5tK9Acdv46n1QJLhXnZ4eD17hJpI=
 | 
				
			||||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
 | 
					github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
 | 
				
			||||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
 | 
					github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
 | 
				
			||||||
github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c=
 | 
					github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c=
 | 
				
			||||||
@ -195,6 +191,7 @@ github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnC
 | 
				
			|||||||
github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0=
 | 
					github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0=
 | 
				
			||||||
github.com/btcsuite/btcd v0.0.0-20190315201642-aa6e0f35703c/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
 | 
					github.com/btcsuite/btcd v0.0.0-20190315201642-aa6e0f35703c/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
 | 
				
			||||||
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
 | 
					github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
 | 
				
			||||||
 | 
					github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
 | 
				
			||||||
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
 | 
					github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
 | 
				
			||||||
github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94=
 | 
					github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94=
 | 
				
			||||||
github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo=
 | 
					github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo=
 | 
				
			||||||
@ -313,6 +310,7 @@ github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6Uh
 | 
				
			|||||||
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
 | 
					github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
 | 
				
			||||||
github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4=
 | 
					github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4=
 | 
				
			||||||
github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo=
 | 
					github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo=
 | 
				
			||||||
 | 
					github.com/decred/dcrd/dcrec/edwards/v2 v2.0.0/go.mod h1:d0H8xGMWbiIQP7gN3v2rByWUcuZPm9YsgmnfoxgbINc=
 | 
				
			||||||
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
 | 
					github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
 | 
				
			||||||
github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M=
 | 
					github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M=
 | 
				
			||||||
github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw=
 | 
					github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw=
 | 
				
			||||||
@ -363,9 +361,7 @@ github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0
 | 
				
			|||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
 | 
					github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
 | 
				
			||||||
github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ=
 | 
					github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ=
 | 
				
			||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 | 
					github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 | 
				
			||||||
github.com/envoyproxy/protoc-gen-validate v0.3.0-java/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 | 
					 | 
				
			||||||
github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
 | 
					github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
 | 
				
			||||||
github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo=
 | 
					 | 
				
			||||||
github.com/ethereum/go-ethereum v1.9.25/go.mod h1:vMkFiYLHI4tgPw4k2j4MHKoovchFE8plZ0M9VMk4/oM=
 | 
					github.com/ethereum/go-ethereum v1.9.25/go.mod h1:vMkFiYLHI4tgPw4k2j4MHKoovchFE8plZ0M9VMk4/oM=
 | 
				
			||||||
github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg=
 | 
					github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg=
 | 
				
			||||||
github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZUGLEaoc=
 | 
					github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZUGLEaoc=
 | 
				
			||||||
@ -487,7 +483,6 @@ github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71
 | 
				
			|||||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
 | 
					github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
 | 
				
			||||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
 | 
					github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
 | 
				
			||||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
 | 
					github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
 | 
				
			||||||
github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 | 
					 | 
				
			||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 | 
					github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 | 
				
			||||||
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
 | 
					github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
 | 
				
			||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 | 
					github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 | 
				
			||||||
@ -682,8 +677,6 @@ github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25
 | 
				
			|||||||
github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM=
 | 
					github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM=
 | 
				
			||||||
github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw=
 | 
					github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw=
 | 
				
			||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 | 
					github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 | 
				
			||||||
github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo=
 | 
					 | 
				
			||||||
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
 | 
					 | 
				
			||||||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
 | 
					github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
 | 
				
			||||||
github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=
 | 
					github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=
 | 
				
			||||||
github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
 | 
					github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
 | 
				
			||||||
@ -694,8 +687,6 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3
 | 
				
			|||||||
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
 | 
					github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
 | 
				
			||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 | 
					github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 | 
				
			||||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 | 
					github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 | 
				
			||||||
github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 | 
					 | 
				
			||||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
 | 
					 | 
				
			||||||
github.com/improbable-eng/grpc-web v0.14.1/go.mod h1:zEjGHa8DAlkoOXmswrNvhUGEYQA9UI7DhrGeHR1DMGU=
 | 
					github.com/improbable-eng/grpc-web v0.14.1/go.mod h1:zEjGHa8DAlkoOXmswrNvhUGEYQA9UI7DhrGeHR1DMGU=
 | 
				
			||||||
github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ=
 | 
					github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ=
 | 
				
			||||||
github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8=
 | 
					github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8=
 | 
				
			||||||
@ -775,10 +766,10 @@ github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F
 | 
				
			|||||||
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0=
 | 
					github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0=
 | 
				
			||||||
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
 | 
					github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
 | 
				
			||||||
github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
 | 
					github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
 | 
				
			||||||
github.com/kava-labs/cosmos-sdk v0.45.4-kava.1 h1:nGL6b6eracc8+FGWbJ/NexFGorI8j6DBMwZ6KvEqteA=
 | 
					github.com/kava-labs/cosmos-sdk v0.45.4-kava.3 h1:U4esIl4rzu9sApLFYGwbccPQTQdRg6C9exUVrokqSHY=
 | 
				
			||||||
github.com/kava-labs/cosmos-sdk v0.45.4-kava.1/go.mod h1:WOqtDxN3eCCmnYLVla10xG7lEXkFjpTaqm2a2WasgCc=
 | 
					github.com/kava-labs/cosmos-sdk v0.45.4-kava.3/go.mod h1:WOqtDxN3eCCmnYLVla10xG7lEXkFjpTaqm2a2WasgCc=
 | 
				
			||||||
github.com/kava-labs/kava-bridge v0.2.0 h1:5t9AsPUy9Riwi+gRLgozhv0dut/xQcvRF+yIB+wLuo8=
 | 
					github.com/kava-labs/kava-bridge v0.2.1-0.20220707160130-6199d30c5fe6 h1:uhdPatSr1VLKvVWTaphkielTlEWF/MvTwmp3uCHgjPo=
 | 
				
			||||||
github.com/kava-labs/kava-bridge v0.2.0/go.mod h1:APqFV9V/rmkm3MnJ27R/CGOjteCX+3mVuRTYE70v7Yw=
 | 
					github.com/kava-labs/kava-bridge v0.2.1-0.20220707160130-6199d30c5fe6/go.mod h1:PNkTAuIw+PhMjlNr2EKPo2AUMcGNwcUIcJHaMhf+qAM=
 | 
				
			||||||
github.com/kava-labs/tm-db v0.6.7-kava.1 h1:7cVYlvWx1yP+gGdaAWcfm6NwMLzf4z6DxXguWn3+O3w=
 | 
					github.com/kava-labs/tm-db v0.6.7-kava.1 h1:7cVYlvWx1yP+gGdaAWcfm6NwMLzf4z6DxXguWn3+O3w=
 | 
				
			||||||
github.com/kava-labs/tm-db v0.6.7-kava.1/go.mod h1:HVZfZzWXuqWseXQVplxsWXK6kLHLkk3kQB6c+nuSZvk=
 | 
					github.com/kava-labs/tm-db v0.6.7-kava.1/go.mod h1:HVZfZzWXuqWseXQVplxsWXK6kLHLkk3kQB6c+nuSZvk=
 | 
				
			||||||
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d h1:Z+RDyXzjKE0i2sTjZ/b1uxiGtPhFy34Ou/Tk0qwN0kM=
 | 
					github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d h1:Z+RDyXzjKE0i2sTjZ/b1uxiGtPhFy34Ou/Tk0qwN0kM=
 | 
				
			||||||
@ -918,7 +909,6 @@ github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T
 | 
				
			|||||||
github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4=
 | 
					github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4=
 | 
				
			||||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
 | 
					github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
 | 
				
			||||||
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
 | 
					github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
 | 
				
			||||||
github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
 | 
					 | 
				
			||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 | 
					github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 | 
				
			||||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 | 
					github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 | 
				
			||||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
 | 
					github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
 | 
				
			||||||
@ -995,7 +985,6 @@ github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl
 | 
				
			|||||||
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
 | 
					github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
 | 
				
			||||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
 | 
					github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
 | 
				
			||||||
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
 | 
					github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
 | 
				
			||||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
 | 
					 | 
				
			||||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 | 
					github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 | 
				
			||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 | 
					github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 | 
				
			||||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
 | 
					github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
 | 
				
			||||||
@ -1010,7 +999,6 @@ github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGg
 | 
				
			|||||||
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 | 
					github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 | 
				
			||||||
github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A=
 | 
					github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A=
 | 
				
			||||||
github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
 | 
					github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
 | 
				
			||||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
 | 
					 | 
				
			||||||
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
 | 
					github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
 | 
				
			||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 | 
					github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 | 
				
			||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 | 
					github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 | 
				
			||||||
@ -1063,8 +1051,6 @@ github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXS
 | 
				
			|||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 | 
					github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 | 
				
			||||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
 | 
					github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
 | 
				
			||||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 | 
					github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 | 
				
			||||||
github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo=
 | 
					 | 
				
			||||||
github.com/mwitkow/go-proto-validators v0.3.2/go.mod h1:ej0Qp0qMgHN/KtDyUt+Q1/tA7a5VarXUOUxD+oeD30w=
 | 
					 | 
				
			||||||
github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJHDHqxHS801UIuhqGl6QdSAEJvtausosHSdazIo=
 | 
					github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJHDHqxHS801UIuhqGl6QdSAEJvtausosHSdazIo=
 | 
				
			||||||
github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
 | 
					github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
 | 
				
			||||||
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
 | 
					github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
 | 
				
			||||||
@ -1145,8 +1131,10 @@ github.com/otiai10/copy v1.6.0 h1:IinKAryFFuPONZ7cm6T6E2QX/vcJwSnlaA5lfoaXIiQ=
 | 
				
			|||||||
github.com/otiai10/copy v1.6.0/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E=
 | 
					github.com/otiai10/copy v1.6.0/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E=
 | 
				
			||||||
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
 | 
					github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
 | 
				
			||||||
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
 | 
					github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
 | 
				
			||||||
 | 
					github.com/otiai10/mint v1.2.4/go.mod h1:d+b7n/0R3tdyUYYylALXpWQ/kTN+QobSq/4SRGBkR3M=
 | 
				
			||||||
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
 | 
					github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
 | 
				
			||||||
github.com/otiai10/mint v1.3.2/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
 | 
					github.com/otiai10/mint v1.3.2/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
 | 
				
			||||||
 | 
					github.com/otiai10/primes v0.0.0-20180210170552-f6d2a1ba97c4/go.mod h1:UmSP7QeU3XmAdGu5+dnrTJqjBc+IscpVZkQzk473cjM=
 | 
				
			||||||
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
 | 
					github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
 | 
				
			||||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 | 
					github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 | 
				
			||||||
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
 | 
					github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
 | 
				
			||||||
@ -1236,9 +1224,6 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
 | 
				
			|||||||
github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
 | 
					github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
 | 
				
			||||||
github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA=
 | 
					github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA=
 | 
				
			||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
 | 
					github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
 | 
				
			||||||
github.com/pseudomuto/protoc-gen-doc v1.5.1/go.mod h1:XpMKYg6zkcpgfpCfQ8GcWBDRtRxOmMR5w7pz4Xo+dYM=
 | 
					 | 
				
			||||||
github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3Q8ViKSAXT0Q=
 | 
					 | 
				
			||||||
github.com/pseudomuto/protokit v0.2.1/go.mod h1:gt7N5Rz2flBzYafvaxyIxMZC0TTF5jDZfRnw25hAAyo=
 | 
					 | 
				
			||||||
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
 | 
					github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
 | 
				
			||||||
github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc=
 | 
					github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc=
 | 
				
			||||||
github.com/raulk/clock v1.1.0/go.mod h1:3MpVxdZ/ODBQDxbN+kzshf5OSZwPjtMDx6BBXBmOeY0=
 | 
					github.com/raulk/clock v1.1.0/go.mod h1:3MpVxdZ/ODBQDxbN+kzshf5OSZwPjtMDx6BBXBmOeY0=
 | 
				
			||||||
@ -1375,7 +1360,6 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
 | 
				
			|||||||
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
 | 
					github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
 | 
				
			||||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
 | 
					github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
 | 
				
			||||||
github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 | 
					github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 | 
				
			||||||
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 | 
					 | 
				
			||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 | 
					github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 | 
				
			||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 | 
					github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 | 
				
			||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 | 
					github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 | 
				
			||||||
@ -1973,7 +1957,6 @@ google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6
 | 
				
			|||||||
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
 | 
					google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
 | 
				
			||||||
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
 | 
					google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
 | 
				
			||||||
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
 | 
					google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
 | 
				
			||||||
google.golang.org/api v0.58.0/go.mod h1:cAbP2FsxoGVNwtgNAmmn3y5G1TWAiVYRmg4yku3lv+E=
 | 
					 | 
				
			||||||
google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
 | 
					google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
 | 
				
			||||||
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
 | 
					google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
 | 
				
			||||||
google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw=
 | 
					google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw=
 | 
				
			||||||
@ -1990,7 +1973,6 @@ google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww
 | 
				
			|||||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 | 
					google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 | 
				
			||||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 | 
					google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 | 
				
			||||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 | 
					google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 | 
				
			||||||
google.golang.org/genproto v0.0.0-20180427144745-86e600f69ee4/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 | 
					 | 
				
			||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 | 
					google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 | 
				
			||||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 | 
					google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 | 
				
			||||||
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 | 
					google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 | 
				
			||||||
 | 
				
			|||||||
@ -4,52 +4,48 @@ import (
 | 
				
			|||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/cosmos/cosmos-sdk/client"
 | 
					 | 
				
			||||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
					 | 
				
			||||||
	"github.com/cosmos/cosmos-sdk/version"
 | 
						"github.com/cosmos/cosmos-sdk/version"
 | 
				
			||||||
	genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
 | 
						genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
 | 
				
			||||||
	"github.com/spf13/cobra"
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
	tmjson "github.com/tendermint/tendermint/libs/json"
 | 
					 | 
				
			||||||
	tmtypes "github.com/tendermint/tendermint/types"
 | 
						tmtypes "github.com/tendermint/tendermint/types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/kava-labs/kava/app"
 | 
						"github.com/kava-labs/kava/app"
 | 
				
			||||||
	"github.com/kava-labs/kava/app/params"
 | 
						"github.com/kava-labs/kava/app/params"
 | 
				
			||||||
	"github.com/kava-labs/kava/migrate/v0_17"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MigrateGenesisCmd returns a command to execute genesis state migration.
 | 
					// MigrateGenesisCmd returns a command to execute genesis state migration.
 | 
				
			||||||
func MigrateGenesisCmd() *cobra.Command {
 | 
					func MigrateGenesisCmd() *cobra.Command {
 | 
				
			||||||
	cmd := &cobra.Command{
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
		Use:     "migrate [genesis-file]",
 | 
							Use:     "migrate [genesis-file]",
 | 
				
			||||||
		Short:   "Migrate genesis from v0.16 to v0.17",
 | 
							Short:   "Migrate genesis from v0.17 to v0.18",
 | 
				
			||||||
		Long:    "Migrate the source genesis into v0.17 and print to STDOUT.",
 | 
							Long:    "Migrate the source genesis into v0.18 and print to STDOUT.",
 | 
				
			||||||
		Example: fmt.Sprintf(`%s migrate /path/to/genesis.json`, version.AppName),
 | 
							Example: fmt.Sprintf(`%s migrate /path/to/genesis.json`, version.AppName),
 | 
				
			||||||
		Args:    cobra.ExactArgs(1),
 | 
							Args:    cobra.ExactArgs(1),
 | 
				
			||||||
		RunE: func(cmd *cobra.Command, args []string) error {
 | 
							RunE: func(cmd *cobra.Command, args []string) error {
 | 
				
			||||||
			clientCtx := client.GetClientContextFromCmd(cmd)
 | 
								// clientCtx := client.GetClientContextFromCmd(cmd)
 | 
				
			||||||
			importGenesis := args[0]
 | 
								// importGenesis := args[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			oldGenDoc, err := tmtypes.GenesisDocFromFile(importGenesis)
 | 
								// oldGenDoc, err := tmtypes.GenesisDocFromFile(importGenesis)
 | 
				
			||||||
			if err != nil {
 | 
								// if err != nil {
 | 
				
			||||||
				return fmt.Errorf("failed to read genesis document from file %s: %w", importGenesis, err)
 | 
								// 	return fmt.Errorf("failed to read genesis document from file %s: %w", importGenesis, err)
 | 
				
			||||||
			}
 | 
								// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			newGenDoc, err := v0_17.Migrate(oldGenDoc, clientCtx)
 | 
								// newGenDoc, err := v0_17.Migrate(oldGenDoc, clientCtx)
 | 
				
			||||||
			if err != nil {
 | 
								// if err != nil {
 | 
				
			||||||
				return fmt.Errorf("failed to run migration: %w", err)
 | 
								// 	return fmt.Errorf("failed to run migration: %w", err)
 | 
				
			||||||
			}
 | 
								// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			bz, err := tmjson.Marshal(newGenDoc)
 | 
								// bz, err := tmjson.Marshal(newGenDoc)
 | 
				
			||||||
			if err != nil {
 | 
								// if err != nil {
 | 
				
			||||||
				return fmt.Errorf("failed to marshal genesis doc: %w", err)
 | 
								// 	return fmt.Errorf("failed to marshal genesis doc: %w", err)
 | 
				
			||||||
			}
 | 
								// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sortedBz, err := sdk.SortJSON(bz)
 | 
								// sortedBz, err := sdk.SortJSON(bz)
 | 
				
			||||||
			if err != nil {
 | 
								// if err != nil {
 | 
				
			||||||
				return fmt.Errorf("failed to sort JSON genesis doc: %w", err)
 | 
								// 	return fmt.Errorf("failed to sort JSON genesis doc: %w", err)
 | 
				
			||||||
			}
 | 
								// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			fmt.Println(string(sortedBz))
 | 
								// fmt.Println(string(sortedBz))
 | 
				
			||||||
			return nil
 | 
								return nil
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,268 +0,0 @@
 | 
				
			|||||||
# This is a TOML config file.
 | 
					 | 
				
			||||||
# For more information, see https://github.com/toml-lang/toml
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
###                           Base Configuration                            ###
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# The minimum gas prices a validator is willing to accept for processing a
 | 
					 | 
				
			||||||
# transaction. A transaction's fees must meet the minimum of any denomination
 | 
					 | 
				
			||||||
# specified in this config (e.g. 0.25token1;0.0001token2).
 | 
					 | 
				
			||||||
minimum-gas-prices = "0.001ukava;1000000000akava"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# default: the last 100 states are kept in addition to every 500th state; pruning at 10 block intervals
 | 
					 | 
				
			||||||
# nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node)
 | 
					 | 
				
			||||||
# everything: all saved states will be deleted, storing only the current and previous state; pruning at 10 block intervals
 | 
					 | 
				
			||||||
# custom: allow pruning options to be manually specified through 'pruning-keep-recent', 'pruning-keep-every', and 'pruning-interval'
 | 
					 | 
				
			||||||
pruning = "default"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# These are applied if and only if the pruning strategy is custom.
 | 
					 | 
				
			||||||
pruning-keep-recent = "0"
 | 
					 | 
				
			||||||
pruning-keep-every = "0"
 | 
					 | 
				
			||||||
pruning-interval = "0"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# HaltHeight contains a non-zero block height at which a node will gracefully
 | 
					 | 
				
			||||||
# halt and shutdown that can be used to assist upgrades and testing.
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# Note: Commitment of state will be attempted on the corresponding block.
 | 
					 | 
				
			||||||
halt-height = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# HaltTime contains a non-zero minimum block time (in Unix seconds) at which
 | 
					 | 
				
			||||||
# a node will gracefully halt and shutdown that can be used to assist upgrades
 | 
					 | 
				
			||||||
# and testing.
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# Note: Commitment of state will be attempted on the corresponding block.
 | 
					 | 
				
			||||||
halt-time = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# MinRetainBlocks defines the minimum block height offset from the current
 | 
					 | 
				
			||||||
# block being committed, such that all blocks past this offset are pruned
 | 
					 | 
				
			||||||
# from Tendermint. It is used as part of the process of determining the
 | 
					 | 
				
			||||||
# ResponseCommit.RetainHeight value during ABCI Commit. A value of 0 indicates
 | 
					 | 
				
			||||||
# that no blocks should be pruned.
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# This configuration value is only responsible for pruning Tendermint blocks.
 | 
					 | 
				
			||||||
# It has no bearing on application state pruning which is determined by the
 | 
					 | 
				
			||||||
# "pruning-*" configurations.
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# Note: Tendermint block pruning is dependant on this parameter in conunction
 | 
					 | 
				
			||||||
# with the unbonding (safety threshold) period, state pruning and state sync
 | 
					 | 
				
			||||||
# snapshot parameters to determine the correct minimum value of
 | 
					 | 
				
			||||||
# ResponseCommit.RetainHeight.
 | 
					 | 
				
			||||||
min-retain-blocks = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# InterBlockCache enables inter-block caching.
 | 
					 | 
				
			||||||
inter-block-cache = true
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# IndexEvents defines the set of events in the form {eventType}.{attributeKey},
 | 
					 | 
				
			||||||
# which informs Tendermint what to index. If empty, all events will be indexed.
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# Example:
 | 
					 | 
				
			||||||
# ["message.sender", "message.recipient"]
 | 
					 | 
				
			||||||
index-events = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# IavlCacheSize set the size of the iavl tree cache. 
 | 
					 | 
				
			||||||
# Default cache size is 50mb.
 | 
					 | 
				
			||||||
iavl-cache-size = 781250
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
###                         Telemetry Configuration                         ###
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[telemetry]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Prefixed with keys to separate services.
 | 
					 | 
				
			||||||
service-name = ""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Enabled enables the application telemetry functionality. When enabled,
 | 
					 | 
				
			||||||
# an in-memory sink is also enabled by default. Operators may also enabled
 | 
					 | 
				
			||||||
# other sinks such as Prometheus.
 | 
					 | 
				
			||||||
enabled = false
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Enable prefixing gauge values with hostname.
 | 
					 | 
				
			||||||
enable-hostname = false
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Enable adding hostname to labels.
 | 
					 | 
				
			||||||
enable-hostname-label = false
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Enable adding service to labels.
 | 
					 | 
				
			||||||
enable-service-label = false
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# PrometheusRetentionTime, when positive, enables a Prometheus metrics sink.
 | 
					 | 
				
			||||||
prometheus-retention-time = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# GlobalLabels defines a global set of name/value label tuples applied to all
 | 
					 | 
				
			||||||
# metrics emitted using the wrapper functions defined in telemetry package.
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# Example:
 | 
					 | 
				
			||||||
# [["chain_id", "cosmoshub-1"]]
 | 
					 | 
				
			||||||
global-labels = [
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
###                           API Configuration                             ###
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[api]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Enable defines if the API server should be enabled.
 | 
					 | 
				
			||||||
enable = false
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Swagger defines if swagger documentation should automatically be registered.
 | 
					 | 
				
			||||||
swagger = false
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Address defines the API server to listen on.
 | 
					 | 
				
			||||||
address = "tcp://0.0.0.0:1317"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# MaxOpenConnections defines the number of maximum open connections.
 | 
					 | 
				
			||||||
max-open-connections = 1000
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# RPCReadTimeout defines the Tendermint RPC read timeout (in seconds).
 | 
					 | 
				
			||||||
rpc-read-timeout = 10
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# RPCWriteTimeout defines the Tendermint RPC write timeout (in seconds).
 | 
					 | 
				
			||||||
rpc-write-timeout = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# RPCMaxBodyBytes defines the Tendermint maximum response body (in bytes).
 | 
					 | 
				
			||||||
rpc-max-body-bytes = 1000000
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk).
 | 
					 | 
				
			||||||
enabled-unsafe-cors = false
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
###                           Rosetta Configuration                         ###
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[rosetta]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Enable defines if the Rosetta API server should be enabled.
 | 
					 | 
				
			||||||
enable = false
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Address defines the Rosetta API server to listen on.
 | 
					 | 
				
			||||||
address = ":8080"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Network defines the name of the blockchain that will be returned by Rosetta.
 | 
					 | 
				
			||||||
blockchain = "app"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Network defines the name of the network that will be returned by Rosetta.
 | 
					 | 
				
			||||||
network = "network"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Retries defines the number of retries when connecting to the node before failing.
 | 
					 | 
				
			||||||
retries = 3
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Offline defines if Rosetta server should run in offline mode.
 | 
					 | 
				
			||||||
offline = false
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
###                           gRPC Configuration                            ###
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[grpc]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Enable defines if the gRPC server should be enabled.
 | 
					 | 
				
			||||||
enable = true
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Address defines the gRPC server address to bind to.
 | 
					 | 
				
			||||||
address = "0.0.0.0:9090"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
###                        gRPC Web Configuration                           ###
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[grpc-web]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# GRPCWebEnable defines if the gRPC-web should be enabled.
 | 
					 | 
				
			||||||
# NOTE: gRPC must also be enabled, otherwise, this configuration is a no-op.
 | 
					 | 
				
			||||||
enable = true
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Address defines the gRPC-web server address to bind to.
 | 
					 | 
				
			||||||
address = "0.0.0.0:9091"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk).
 | 
					 | 
				
			||||||
enable-unsafe-cors = false
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
###                        State Sync Configuration                         ###
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# State sync snapshots allow other nodes to rapidly join the network without replaying historical
 | 
					 | 
				
			||||||
# blocks, instead downloading and applying a snapshot of the application state at a given height.
 | 
					 | 
				
			||||||
[state-sync]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# snapshot-interval specifies the block interval at which local state sync snapshots are
 | 
					 | 
				
			||||||
# taken (0 to disable). Must be a multiple of pruning-keep-every.
 | 
					 | 
				
			||||||
snapshot-interval = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# snapshot-keep-recent specifies the number of recent snapshots to keep and serve (0 to keep all).
 | 
					 | 
				
			||||||
snapshot-keep-recent = 2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
###                             EVM Configuration                           ###
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[evm]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Tracer defines the 'vm.Tracer' type that the EVM will use when the node is run in
 | 
					 | 
				
			||||||
# debug mode. To enable tracing use the '--evm.tracer' flag when starting your node.
 | 
					 | 
				
			||||||
# Valid types are: json|struct|access_list|markdown
 | 
					 | 
				
			||||||
tracer = ""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# MaxTxGasWanted defines the gas wanted for each eth tx returned in ante handler in check tx mode.
 | 
					 | 
				
			||||||
max-tx-gas-wanted = 500000
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
###                           JSON RPC Configuration                        ###
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[json-rpc]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Enable defines if the gRPC server should be enabled.
 | 
					 | 
				
			||||||
enable = true
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Address defines the EVM RPC HTTP server address to bind to.
 | 
					 | 
				
			||||||
address = "0.0.0.0:8545"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Address defines the EVM WebSocket server address to bind to.
 | 
					 | 
				
			||||||
ws-address = "0.0.0.0:8546"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# API defines a list of JSON-RPC namespaces that should be enabled
 | 
					 | 
				
			||||||
# Example: "eth,txpool,personal,net,debug,web3"
 | 
					 | 
				
			||||||
api = "eth,net,web3"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# GasCap sets a cap on gas that can be used in eth_call/estimateGas (0=infinite). Default: 25,000,000.
 | 
					 | 
				
			||||||
gas-cap = 25000000
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# EVMTimeout is the global timeout for eth_call. Default: 5s.
 | 
					 | 
				
			||||||
evm-timeout = "5s"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# TxFeeCap is the global tx-fee cap for send transaction. Default: 1eth.
 | 
					 | 
				
			||||||
txfee-cap = 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# FilterCap sets the global cap for total number of filters that can be created
 | 
					 | 
				
			||||||
filter-cap = 200
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# FeeHistoryCap sets the global cap for total number of blocks that can be fetched
 | 
					 | 
				
			||||||
feehistory-cap = 100
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# LogsCap defines the max number of results can be returned from single 'eth_getLogs' query.
 | 
					 | 
				
			||||||
logs-cap = 10000
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# BlockRangeCap defines the max block range allowed for 'eth_getLogs' query.
 | 
					 | 
				
			||||||
block-range-cap = 10000
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# HTTPTimeout is the read/write timeout of http json-rpc server.
 | 
					 | 
				
			||||||
http-timeout = "30s"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# HTTPIdleTimeout is the idle timeout of http json-rpc server.
 | 
					 | 
				
			||||||
http-idle-timeout = "2m0s"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
###                             TLS Configuration                           ###
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[tls]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Certificate path defines the cert.pem file path for the TLS configuration.
 | 
					 | 
				
			||||||
certificate-path = ""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Key path defines the key.pem file path for the TLS configuration.
 | 
					 | 
				
			||||||
key-path = ""
 | 
					 | 
				
			||||||
@ -1,35 +0,0 @@
 | 
				
			|||||||
package v0_17
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/cosmos/cosmos-sdk/client"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040"
 | 
					 | 
				
			||||||
	v040authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func MigrateCosmosAppState(appState genutiltypes.AppMap, clientCtx client.Context, genesisTime time.Time) genutiltypes.AppMap {
 | 
					 | 
				
			||||||
	appState = migrateV040(appState, clientCtx, genesisTime)
 | 
					 | 
				
			||||||
	return appState
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// reset periodic vesting data for accounts
 | 
					 | 
				
			||||||
func migrateV040(appState genutiltypes.AppMap, clientCtx client.Context, genesisTime time.Time) genutiltypes.AppMap {
 | 
					 | 
				
			||||||
	setConfigIfUnsealed()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	v040Codec := clientCtx.Codec
 | 
					 | 
				
			||||||
	// reset periodic vesting data for accounts
 | 
					 | 
				
			||||||
	if appState[v040auth.ModuleName] != nil {
 | 
					 | 
				
			||||||
		// unmarshal relative source genesis application state
 | 
					 | 
				
			||||||
		var authGenState v040authtypes.GenesisState
 | 
					 | 
				
			||||||
		v040Codec.MustUnmarshalJSON(appState[v040auth.ModuleName], &authGenState)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// reset periodic vesting data for accounts
 | 
					 | 
				
			||||||
		appState[v040auth.ModuleName] = v040Codec.MustMarshalJSON(MigrateAuthV040(authGenState, genesisTime, clientCtx))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return appState
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,67 +0,0 @@
 | 
				
			|||||||
package v0_17
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/cosmos/cosmos-sdk/client"
 | 
					 | 
				
			||||||
	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
 | 
					 | 
				
			||||||
	v040auth "github.com/cosmos/cosmos-sdk/x/auth/types"
 | 
					 | 
				
			||||||
	v040vesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
 | 
					 | 
				
			||||||
	"github.com/kava-labs/kava/migrate/utils"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MigrateAuthV040 resets all periodic vesting accounts for a given
 | 
					 | 
				
			||||||
// v40 cosmos auth module genesis state, returning a copy of the original state where all
 | 
					 | 
				
			||||||
// periodic vesting accounts have been zeroed out.
 | 
					 | 
				
			||||||
func MigrateAuthV040(authGenState v040auth.GenesisState, genesisTime time.Time, ctx client.Context) *v040auth.GenesisState {
 | 
					 | 
				
			||||||
	anyAccounts := make([]*codectypes.Any, len(authGenState.Accounts))
 | 
					 | 
				
			||||||
	for i, anyAcc := range authGenState.Accounts {
 | 
					 | 
				
			||||||
		// Only need to make modifications to vesting accounts
 | 
					 | 
				
			||||||
		if anyAcc.TypeUrl != "/cosmos.vesting.v1beta1.PeriodicVestingAccount" {
 | 
					 | 
				
			||||||
			anyAccounts[i] = anyAcc
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		var acc v040auth.GenesisAccount
 | 
					 | 
				
			||||||
		if err := ctx.InterfaceRegistry.UnpackAny(anyAcc, &acc); err != nil {
 | 
					 | 
				
			||||||
			panic(err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if vacc, ok := acc.(*v040vesting.PeriodicVestingAccount); ok {
 | 
					 | 
				
			||||||
			vestingPeriods := make([]v040vesting.Period, len(vacc.VestingPeriods))
 | 
					 | 
				
			||||||
			for j, period := range vacc.VestingPeriods {
 | 
					 | 
				
			||||||
				vestingPeriods[j] = v040vesting.Period{
 | 
					 | 
				
			||||||
					Length: period.Length,
 | 
					 | 
				
			||||||
					Amount: period.Amount,
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			vacc := v040vesting.PeriodicVestingAccount{
 | 
					 | 
				
			||||||
				BaseVestingAccount: vacc.BaseVestingAccount,
 | 
					 | 
				
			||||||
				StartTime:          vacc.StartTime,
 | 
					 | 
				
			||||||
				VestingPeriods:     vestingPeriods,
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			utils.ResetPeriodicVestingAccount(&vacc, genesisTime)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// If periodic vesting account has zero periods, convert back
 | 
					 | 
				
			||||||
			// to a base account
 | 
					 | 
				
			||||||
			if genesisTime.Unix() >= vacc.EndTime {
 | 
					 | 
				
			||||||
				any, err := codectypes.NewAnyWithValue(vacc.BaseVestingAccount.BaseAccount)
 | 
					 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					panic(err)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				anyAccounts[i] = any
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			// Convert back to any
 | 
					 | 
				
			||||||
			any, err := codectypes.NewAnyWithValue(&vacc)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				panic(err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			anyAccounts[i] = any
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return &v040auth.GenesisState{
 | 
					 | 
				
			||||||
		Params:   authGenState.Params,
 | 
					 | 
				
			||||||
		Accounts: anyAccounts,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,133 +0,0 @@
 | 
				
			|||||||
package v0_17
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"github.com/cosmos/cosmos-sdk/client"
 | 
					 | 
				
			||||||
	"github.com/cosmos/cosmos-sdk/codec"
 | 
					 | 
				
			||||||
	"github.com/cosmos/cosmos-sdk/codec/types"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
					 | 
				
			||||||
	authz "github.com/cosmos/cosmos-sdk/x/authz"
 | 
					 | 
				
			||||||
	genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
 | 
					 | 
				
			||||||
	evmtypes "github.com/tharsis/ethermint/x/evm/types"
 | 
					 | 
				
			||||||
	feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	evmutiltypes "github.com/kava-labs/kava/x/evmutil/types"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bridgetypes "github.com/kava-labs/kava-bridge/x/bridge/types"
 | 
					 | 
				
			||||||
	v016auction "github.com/kava-labs/kava/x/auction/legacy/v0_16"
 | 
					 | 
				
			||||||
	v017auction "github.com/kava-labs/kava/x/auction/legacy/v0_17"
 | 
					 | 
				
			||||||
	auctiontypes "github.com/kava-labs/kava/x/auction/types"
 | 
					 | 
				
			||||||
	v017bep3 "github.com/kava-labs/kava/x/bep3/legacy/v0_17"
 | 
					 | 
				
			||||||
	bep3types "github.com/kava-labs/kava/x/bep3/types"
 | 
					 | 
				
			||||||
	cdptypes "github.com/kava-labs/kava/x/cdp/types"
 | 
					 | 
				
			||||||
	committeetypes "github.com/kava-labs/kava/x/committee/types"
 | 
					 | 
				
			||||||
	incentivetypes "github.com/kava-labs/kava/x/incentive/types"
 | 
					 | 
				
			||||||
	savingstypes "github.com/kava-labs/kava/x/savings/types"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func migrateAppState(appState genutiltypes.AppMap, clientCtx client.Context) {
 | 
					 | 
				
			||||||
	interfaceRegistry := types.NewInterfaceRegistry()
 | 
					 | 
				
			||||||
	v016auction.RegisterInterfaces(interfaceRegistry)
 | 
					 | 
				
			||||||
	v16Codec := codec.NewProtoCodec(interfaceRegistry)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	codec := clientCtx.Codec
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// x/emvutil
 | 
					 | 
				
			||||||
	evmUtilGenState := evmutiltypes.NewGenesisState([]evmutiltypes.Account{})
 | 
					 | 
				
			||||||
	appState[evmutiltypes.ModuleName] = codec.MustMarshalJSON(evmUtilGenState)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// x/evm
 | 
					 | 
				
			||||||
	evmChainConfig := evmtypes.DefaultChainConfig()
 | 
					 | 
				
			||||||
	evmChainConfig.LondonBlock = nil
 | 
					 | 
				
			||||||
	evmChainConfig.ArrowGlacierBlock = nil
 | 
					 | 
				
			||||||
	evmChainConfig.MergeForkBlock = nil
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	evmGenState := &evmtypes.GenesisState{
 | 
					 | 
				
			||||||
		Accounts: []evmtypes.GenesisAccount{},
 | 
					 | 
				
			||||||
		Params: evmtypes.Params{
 | 
					 | 
				
			||||||
			EvmDenom:     "akava",
 | 
					 | 
				
			||||||
			EnableCreate: true,
 | 
					 | 
				
			||||||
			EnableCall:   true,
 | 
					 | 
				
			||||||
			ChainConfig:  evmChainConfig,
 | 
					 | 
				
			||||||
			ExtraEIPs:    nil,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	appState[evmtypes.ModuleName] = codec.MustMarshalJSON(evmGenState)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// x/bridge
 | 
					 | 
				
			||||||
	bridgeGenState := bridgetypes.NewGenesisState(
 | 
					 | 
				
			||||||
		bridgetypes.NewParams(
 | 
					 | 
				
			||||||
			false,                            // Bridge disabled
 | 
					 | 
				
			||||||
			bridgetypes.EnabledERC20Tokens{}, // No bridge ERC20 tokens
 | 
					 | 
				
			||||||
			nil,                              // No relayer
 | 
					 | 
				
			||||||
			bridgetypes.ConversionPairs{},    // No conversion pairs
 | 
					 | 
				
			||||||
		),
 | 
					 | 
				
			||||||
		bridgetypes.ERC20BridgePairs{}, // Empty state as there has been no ERC20 contracts deployed
 | 
					 | 
				
			||||||
		sdk.OneInt(),                   // NextWithdrawSequence starts at 1
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
	appState[bridgetypes.ModuleName] = codec.MustMarshalJSON(&bridgeGenState)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// x/feemarket
 | 
					 | 
				
			||||||
	feemarketState := feemarkettypes.DefaultGenesisState()
 | 
					 | 
				
			||||||
	// disable fee market and use minimum-gas-price instead of dynamic base fee
 | 
					 | 
				
			||||||
	feemarketState.Params.NoBaseFee = true
 | 
					 | 
				
			||||||
	appState[feemarkettypes.ModuleName] = codec.MustMarshalJSON(feemarketState)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// x/authz
 | 
					 | 
				
			||||||
	authzState := authz.DefaultGenesisState()
 | 
					 | 
				
			||||||
	appState[authz.ModuleName] = codec.MustMarshalJSON(authzState)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// x/cdp
 | 
					 | 
				
			||||||
	if appState[cdptypes.ModuleName] != nil {
 | 
					 | 
				
			||||||
		var genState cdptypes.GenesisState
 | 
					 | 
				
			||||||
		codec.MustUnmarshalJSON(appState[cdptypes.ModuleName], &genState)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		genState.Params.GlobalDebtLimit = sdk.NewCoin("usdx", sdk.NewInt(393000000000000))
 | 
					 | 
				
			||||||
		encodedState := codec.MustMarshalJSON(&genState)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		appState[cdptypes.ModuleName] = encodedState
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// x/auction
 | 
					 | 
				
			||||||
	if appState[auctiontypes.ModuleName] != nil {
 | 
					 | 
				
			||||||
		var v16GenState v016auction.GenesisState
 | 
					 | 
				
			||||||
		v16Codec.MustUnmarshalJSON(appState[auctiontypes.ModuleName], &v16GenState)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		migratedState := v017auction.Migrate(v16GenState)
 | 
					 | 
				
			||||||
		encodedState := codec.MustMarshalJSON(migratedState)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		appState[auctiontypes.ModuleName] = encodedState
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// x/incentive
 | 
					 | 
				
			||||||
	if appState[incentivetypes.ModuleName] != nil {
 | 
					 | 
				
			||||||
		var incentiveState incentivetypes.GenesisState
 | 
					 | 
				
			||||||
		codec.MustUnmarshalJSON(appState[incentivetypes.ModuleName], &incentiveState)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		appState[incentivetypes.ModuleName] = codec.MustMarshalJSON(&incentiveState)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// x/savings
 | 
					 | 
				
			||||||
	savingsState := savingstypes.DefaultGenesisState()
 | 
					 | 
				
			||||||
	appState[savingstypes.ModuleName] = codec.MustMarshalJSON(&savingsState)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// x/bep3
 | 
					 | 
				
			||||||
	if appState[bep3types.ModuleName] != nil {
 | 
					 | 
				
			||||||
		var v16GenState bep3types.GenesisState
 | 
					 | 
				
			||||||
		codec.MustUnmarshalJSON(appState[bep3types.ModuleName], &v16GenState)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		migratedState := v017bep3.Migrate(v16GenState)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		appState[bep3types.ModuleName] = codec.MustMarshalJSON(migratedState)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// x/committee
 | 
					 | 
				
			||||||
	if appState[committeetypes.ModuleName] != nil {
 | 
					 | 
				
			||||||
		var genState committeetypes.GenesisState
 | 
					 | 
				
			||||||
		codec.MustUnmarshalJSON(appState[committeetypes.ModuleName], &genState)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		migratedState := migrateCommitteePermissions(genState)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		appState[committeetypes.ModuleName] = codec.MustMarshalJSON(&migratedState)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,148 +0,0 @@
 | 
				
			|||||||
package v0_17
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	auctiontypes "github.com/kava-labs/kava/x/auction/types"
 | 
					 | 
				
			||||||
	cdptypes "github.com/kava-labs/kava/x/cdp/types"
 | 
					 | 
				
			||||||
	committeetypes "github.com/kava-labs/kava/x/committee/types"
 | 
					 | 
				
			||||||
	hardtypes "github.com/kava-labs/kava/x/hard/types"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func migrateCommitteePermissions(genState committeetypes.GenesisState) committeetypes.GenesisState {
 | 
					 | 
				
			||||||
	var newCommittees committeetypes.Committees
 | 
					 | 
				
			||||||
	for _, committee := range genState.GetCommittees() {
 | 
					 | 
				
			||||||
		switch committee.GetDescription() {
 | 
					 | 
				
			||||||
		case "Hard Governance Committee":
 | 
					 | 
				
			||||||
			committee = fixHardPermissions(committee)
 | 
					 | 
				
			||||||
		case "Kava Stability Committee":
 | 
					 | 
				
			||||||
			committee = fixStabilityPermissions(committee)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		newCommittees = append(newCommittees, committee)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	packedCommittees, err := committeetypes.PackCommittees(newCommittees)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		panic(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	genState.Committees = packedCommittees
 | 
					 | 
				
			||||||
	return genState
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func fixStabilityPermissions(committee committeetypes.Committee) committeetypes.Committee {
 | 
					 | 
				
			||||||
	permissions := committee.GetPermissions()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// get first params change permission in committee
 | 
					 | 
				
			||||||
	var perm *committeetypes.ParamsChangePermission
 | 
					 | 
				
			||||||
	var permIndex int
 | 
					 | 
				
			||||||
	var found bool
 | 
					 | 
				
			||||||
	for permIndex = range permissions {
 | 
					 | 
				
			||||||
		p, ok := permissions[permIndex].(*committeetypes.ParamsChangePermission)
 | 
					 | 
				
			||||||
		if ok {
 | 
					 | 
				
			||||||
			perm = p
 | 
					 | 
				
			||||||
			found = true
 | 
					 | 
				
			||||||
			break
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if !found {
 | 
					 | 
				
			||||||
		panic("ParamsChangePermission not found")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	appendSubparamRequirement(
 | 
					 | 
				
			||||||
		perm.AllowedParamsChanges,
 | 
					 | 
				
			||||||
		hardtypes.ModuleName, string(hardtypes.KeyMoneyMarkets),
 | 
					 | 
				
			||||||
		committeetypes.SubparamRequirement{
 | 
					 | 
				
			||||||
			Key: "denom",
 | 
					 | 
				
			||||||
			Val: "ibc/799FDD409719A1122586A629AE8FCA17380351A51C1F47A80A1B8E7F2A491098",
 | 
					 | 
				
			||||||
			AllowedSubparamAttrChanges: []string{
 | 
					 | 
				
			||||||
				"borrow_limit",
 | 
					 | 
				
			||||||
				"interest_rate_model",
 | 
					 | 
				
			||||||
				"keeper_reward_percentage",
 | 
					 | 
				
			||||||
				"reserve_factor",
 | 
					 | 
				
			||||||
				"spot_market_id",
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	appendSubparamRequirement(
 | 
					 | 
				
			||||||
		perm.AllowedParamsChanges,
 | 
					 | 
				
			||||||
		cdptypes.ModuleName, string(cdptypes.KeyCollateralParams),
 | 
					 | 
				
			||||||
		committeetypes.SubparamRequirement{
 | 
					 | 
				
			||||||
			Key: "type",
 | 
					 | 
				
			||||||
			Val: "ust-a",
 | 
					 | 
				
			||||||
			AllowedSubparamAttrChanges: []string{
 | 
					 | 
				
			||||||
				"auction_size",
 | 
					 | 
				
			||||||
				"check_collateralization_index_count",
 | 
					 | 
				
			||||||
				"debt_limit",
 | 
					 | 
				
			||||||
				"keeper_reward_percentage",
 | 
					 | 
				
			||||||
				"stability_fee",
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	perm.AllowedParamsChanges.Delete(auctiontypes.ModuleName, "BidDuration")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	perm.AllowedParamsChanges.Set(committeetypes.AllowedParamsChange{
 | 
					 | 
				
			||||||
		Subspace: auctiontypes.ModuleName,
 | 
					 | 
				
			||||||
		Key:      string(auctiontypes.KeyForwardBidDuration),
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	perm.AllowedParamsChanges.Set(committeetypes.AllowedParamsChange{
 | 
					 | 
				
			||||||
		Subspace: auctiontypes.ModuleName,
 | 
					 | 
				
			||||||
		Key:      string(auctiontypes.KeyReverseBidDuration),
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// update committee
 | 
					 | 
				
			||||||
	permissions[permIndex] = perm
 | 
					 | 
				
			||||||
	committee.SetPermissions(permissions)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return committee
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func fixHardPermissions(committee committeetypes.Committee) committeetypes.Committee {
 | 
					 | 
				
			||||||
	permissions := committee.GetPermissions()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// get first params change permission in committee
 | 
					 | 
				
			||||||
	var perm *committeetypes.ParamsChangePermission
 | 
					 | 
				
			||||||
	var permIndex int
 | 
					 | 
				
			||||||
	var found bool
 | 
					 | 
				
			||||||
	for permIndex = range permissions {
 | 
					 | 
				
			||||||
		p, ok := permissions[permIndex].(*committeetypes.ParamsChangePermission)
 | 
					 | 
				
			||||||
		if ok {
 | 
					 | 
				
			||||||
			perm = p
 | 
					 | 
				
			||||||
			found = true
 | 
					 | 
				
			||||||
			break
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if !found {
 | 
					 | 
				
			||||||
		panic("ParamsChangePermission not found")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	appendSubparamRequirement(
 | 
					 | 
				
			||||||
		perm.AllowedParamsChanges,
 | 
					 | 
				
			||||||
		hardtypes.ModuleName, string(hardtypes.KeyMoneyMarkets),
 | 
					 | 
				
			||||||
		committeetypes.SubparamRequirement{
 | 
					 | 
				
			||||||
			Key: "denom",
 | 
					 | 
				
			||||||
			Val: "ibc/799FDD409719A1122586A629AE8FCA17380351A51C1F47A80A1B8E7F2A491098",
 | 
					 | 
				
			||||||
			AllowedSubparamAttrChanges: []string{
 | 
					 | 
				
			||||||
				"borrow_limit",
 | 
					 | 
				
			||||||
				"interest_rate_model",
 | 
					 | 
				
			||||||
				"keeper_reward_percentage",
 | 
					 | 
				
			||||||
				"reserve_factor",
 | 
					 | 
				
			||||||
				"spot_market_id",
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// update committee
 | 
					 | 
				
			||||||
	permissions[permIndex] = perm
 | 
					 | 
				
			||||||
	committee.SetPermissions(permissions)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return committee
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func appendSubparamRequirement(allowed committeetypes.AllowedParamsChanges, subspace, key string, requirement committeetypes.SubparamRequirement) {
 | 
					 | 
				
			||||||
	apc, found := allowed.Get(subspace, key)
 | 
					 | 
				
			||||||
	if !found {
 | 
					 | 
				
			||||||
		panic("AllowedParamsChange not found")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	apc.MultiSubparamsRequirements = append(apc.MultiSubparamsRequirements, requirement)
 | 
					 | 
				
			||||||
	allowed.Set(apc)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,52 +0,0 @@
 | 
				
			|||||||
package v0_17
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"encoding/json"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/cosmos/cosmos-sdk/client"
 | 
					 | 
				
			||||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
					 | 
				
			||||||
	genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
 | 
					 | 
				
			||||||
	"github.com/kava-labs/kava/app"
 | 
					 | 
				
			||||||
	tmtypes "github.com/tendermint/tendermint/types"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	// TODO: needs verification before release
 | 
					 | 
				
			||||||
	GenesisTime = time.Date(2022, 5, 25, 17, 0, 0, 0, time.UTC)
 | 
					 | 
				
			||||||
	ChainID     = "kava_2222-10"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func setConfigIfUnsealed() {
 | 
					 | 
				
			||||||
	config := sdk.GetConfig()
 | 
					 | 
				
			||||||
	if config.GetBech32AccountAddrPrefix() == "kava" {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	app.SetSDKConfig()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Migrate converts v16 genesis doc to v17 genesis doc
 | 
					 | 
				
			||||||
func Migrate(genDoc *tmtypes.GenesisDoc, ctx client.Context) (*tmtypes.GenesisDoc, error) {
 | 
					 | 
				
			||||||
	setConfigIfUnsealed()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var appState genutiltypes.AppMap
 | 
					 | 
				
			||||||
	var err error
 | 
					 | 
				
			||||||
	if err := json.Unmarshal(genDoc.AppState, &appState); err != nil {
 | 
					 | 
				
			||||||
		return nil, fmt.Errorf("failed to unmarshal app state from genesis doc:  %w", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	MigrateCosmosAppState(appState, ctx, GenesisTime)
 | 
					 | 
				
			||||||
	migrateAppState(appState, ctx)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	genDoc.AppState, err = json.Marshal(appState)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	genDoc.GenesisTime = GenesisTime
 | 
					 | 
				
			||||||
	genDoc.ChainID = ChainID
 | 
					 | 
				
			||||||
	genDoc.InitialHeight = 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return genDoc, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,108 +0,0 @@
 | 
				
			|||||||
# kava-10 Upgrade Instructions
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Software Version and Key Dates
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- We will be upgrading from chain-id "kava-9" to chain-id "kava_2222-10".
 | 
					 | 
				
			||||||
- The version of Kava for kava-10 is v0.17.3
 | 
					 | 
				
			||||||
- The kava-9 chain will be shutdown with a `SoftwareUpgradeProposal` that activates at block height **1610471**, which is approximately 15:00 UTC on May, 25 2022.
 | 
					 | 
				
			||||||
- kava-10 genesis time is set to May 25, 2022 at 17:00 UTC
 | 
					 | 
				
			||||||
- The version of cosmos-sdk for kava-10 is v0.45.3
 | 
					 | 
				
			||||||
- The version of tendermint for kava-10 v0.34.19
 | 
					 | 
				
			||||||
- The minimum version of golang for kava-10 is **1.17+**.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### Risks
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
As a validator, performing the upgrade procedure on your consensus nodes carries a heightened risk of double-signing and being slashed. The most important piece of this procedure is verifying your software version and genesis file hash before starting your validator and signing.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The riskiest thing a validator can do is discover that they made a mistake and repeat the upgrade procedure again during the network startup. If you discover a mistake in the process, the best thing to do is wait for the network to start before correcting it. If the network is halted and you have started with a different genesis file than the expected one, seek advice from a Kava developer before resetting your validator.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### Recovery
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Prior to exporting kava-9 state, validators are encouraged to take a full data snapshot at the export height before proceeding. Snap-shotting depends heavily on infrastructure, but generally this can be done by backing up the .kava directory.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
It is critically important to back-up the .kava/data/priv_validator_state.json file after stopping your kava process. This file is updated every block as your validator participates in consensus rounds. It is a critical file needed to prevent double-signing, in case the upgrade fails and the previous chain needs to be restarted.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
In the event that the upgrade does not succeed, validators and operators must downgrade back to v0.16.x of the Kava software and restore to their latest snapshot before restarting their nodes.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Upgrade Procedure
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### Before the upgrade
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Kava Labs has submitted a `SoftwareUpgradeProposal` that specifies block height **1610471** as the final block height for kava-9. This height corresponds to approximately 15:00 UTC on May 25th. Once the proposal passes, the chain will shutdown automatically at the specified height and does not require manual intervention by validators.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### On the day of the upgrade
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
**The kava chain is expected to halt at block height **1610471**, at approximately 15:00 UTC, and restart with new software at 17:00 UTC May 25th. Do not stop your node and begin the upgrade before 15:00 UTC on May 25th, or you may go offline and be unable to recover until after the upgrade!**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
**Make sure the kava process is stopped before proceeding and that you have backed up your validator**. Failure to backup your validator could make it impossible to restart your node if the upgrade fails.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
1. Export State (this **MUST** be done using **v0.16.x**)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```sh
 | 
					 | 
				
			||||||
# verify version before export:
 | 
					 | 
				
			||||||
kava version --long
 | 
					 | 
				
			||||||
# name: kava
 | 
					 | 
				
			||||||
# server_name: kava
 | 
					 | 
				
			||||||
# version: 0.16.0 (any 0.16 version is fine)
 | 
					 | 
				
			||||||
# commit: 184ef2ad4127517828a4a04cc2c51594b66ac012
 | 
					 | 
				
			||||||
# build_tags: netgo,ledger
 | 
					 | 
				
			||||||
# go: go version go1.17.1 linux/amd64
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# export genesis using v0.16.x
 | 
					 | 
				
			||||||
kava export --for-zero-height --height 1610471 > export-genesis.json
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
**Note:** This can take a while!
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
2. Update to kava-10
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```sh
 | 
					 | 
				
			||||||
  # in the `kava` folder
 | 
					 | 
				
			||||||
  git pull
 | 
					 | 
				
			||||||
  git checkout v0.17.3
 | 
					 | 
				
			||||||
  make install
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # verify versions
 | 
					 | 
				
			||||||
  kava version --long
 | 
					 | 
				
			||||||
  # name: kava
 | 
					 | 
				
			||||||
  # server_name: kava
 | 
					 | 
				
			||||||
  # version: v0.17.3
 | 
					 | 
				
			||||||
  # commit: [TBD]
 | 
					 | 
				
			||||||
  # build_tags: netgo,ledger
 | 
					 | 
				
			||||||
  # go: go version go1.17.1 linux/amd64
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Migrate genesis state
 | 
					 | 
				
			||||||
  kava migrate export-genesis.json > genesis.json
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Verify output of genesis migration
 | 
					 | 
				
			||||||
  kava validate-genesis genesis.json # should say it's valid
 | 
					 | 
				
			||||||
  kava assert-invariants genesis.json # should say invariants pass
 | 
					 | 
				
			||||||
  jq -S -c -M '' genesis.json | shasum -a 256
 | 
					 | 
				
			||||||
  # 3bc9829faf3beae2892ff1dfb7158f41a3f0cff303b4798777a559250a4dc815
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Restart node with migrated genesis state
 | 
					 | 
				
			||||||
  cp genesis.json ~/.kava/config/genesis.json
 | 
					 | 
				
			||||||
  kava tendermint unsafe-reset-all
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Update app.toml - see section below
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Restart node -
 | 
					 | 
				
			||||||
  # ! Be sure to remove --halt-time flag if it is set in systemd/docker
 | 
					 | 
				
			||||||
  kava start
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
kava v0.17 requires changes to app.toml:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- There are 3 new sections - `evm`, `json-rpc`, `tls`. see the [default app.toml](app.toml)
 | 
					 | 
				
			||||||
- There is one addition to Base Configuration: `iavl-cache-size`.
 | 
					 | 
				
			||||||
- It is recommended to add a min gas price for evm txs in `akava` (where 1ukava = 10^12akava). eg `minimum-gas-prices = "0.001ukava;1000000000akava"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
kava v0.17 requires changes to config.toml:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- Depending on your setup, you will need to update the `seeds` and/or `persistent_peers` values in config.toml. These can be found [here](https://docs.google.com/spreadsheets/d/1s3LXLPFJazzdmwKdRv909pe_-ZV_Xbt2uCCNrhoOyIE).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### Coordination
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
If the kava-10 chain does not launch by May 25, 2022 at 21:00 UTC, the launch should be considered a failure and validators should refer to the [rollback](./rollback.md) instructions to restart the previous kava-9 chain. In the event of launch failure, coordination will occur in the [Kava discord](https://discord.com/invite/kQzh3Uv).
 | 
					 | 
				
			||||||
@ -1,200 +0,0 @@
 | 
				
			|||||||
package v0_17
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"io/ioutil"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bridgetypes "github.com/kava-labs/kava-bridge/x/bridge/types"
 | 
					 | 
				
			||||||
	"github.com/kava-labs/kava/app"
 | 
					 | 
				
			||||||
	"github.com/stretchr/testify/assert"
 | 
					 | 
				
			||||||
	"github.com/stretchr/testify/require"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/cosmos/cosmos-sdk/client"
 | 
					 | 
				
			||||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
					 | 
				
			||||||
	authz "github.com/cosmos/cosmos-sdk/x/authz"
 | 
					 | 
				
			||||||
	genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
 | 
					 | 
				
			||||||
	tmjson "github.com/tendermint/tendermint/libs/json"
 | 
					 | 
				
			||||||
	tmtypes "github.com/tendermint/tendermint/types"
 | 
					 | 
				
			||||||
	evmtypes "github.com/tharsis/ethermint/x/evm/types"
 | 
					 | 
				
			||||||
	feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	auctiontypes "github.com/kava-labs/kava/x/auction/types"
 | 
					 | 
				
			||||||
	cdptypes "github.com/kava-labs/kava/x/cdp/types"
 | 
					 | 
				
			||||||
	evmutiltypes "github.com/kava-labs/kava/x/evmutil/types"
 | 
					 | 
				
			||||||
	incentivetypes "github.com/kava-labs/kava/x/incentive/types"
 | 
					 | 
				
			||||||
	savingstypes "github.com/kava-labs/kava/x/savings/types"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestMigrateGenesisDoc(t *testing.T) {
 | 
					 | 
				
			||||||
	expected := getTestDataJSON("genesis-v17.json")
 | 
					 | 
				
			||||||
	genDoc, err := tmtypes.GenesisDocFromFile(filepath.Join("testdata", "genesis-v16.json"))
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	actualGenDoc, err := Migrate(genDoc, newClientContext())
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	actualJson, err := tmjson.Marshal(actualGenDoc)
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	assert.JSONEq(t, expected, string(actualJson))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestMigrateEvmUtil(t *testing.T) {
 | 
					 | 
				
			||||||
	appMap, ctx := migrateToV17AndGetAppMap(t)
 | 
					 | 
				
			||||||
	var genstate evmutiltypes.GenesisState
 | 
					 | 
				
			||||||
	err := ctx.Codec.UnmarshalJSON(appMap[evmutiltypes.ModuleName], &genstate)
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
	assert.Len(t, genstate.Accounts, 0)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestMigrateEvm(t *testing.T) {
 | 
					 | 
				
			||||||
	appMap, ctx := migrateToV17AndGetAppMap(t)
 | 
					 | 
				
			||||||
	var genstate evmtypes.GenesisState
 | 
					 | 
				
			||||||
	err := ctx.Codec.UnmarshalJSON(appMap[evmtypes.ModuleName], &genstate)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	expectedChainConfig := evmtypes.DefaultChainConfig()
 | 
					 | 
				
			||||||
	expectedChainConfig.LondonBlock = nil
 | 
					 | 
				
			||||||
	expectedChainConfig.ArrowGlacierBlock = nil
 | 
					 | 
				
			||||||
	expectedChainConfig.MergeForkBlock = nil
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
	assert.Len(t, genstate.Accounts, 0)
 | 
					 | 
				
			||||||
	assert.Equal(t, evmtypes.Params{
 | 
					 | 
				
			||||||
		EvmDenom:     "akava",
 | 
					 | 
				
			||||||
		EnableCreate: true,
 | 
					 | 
				
			||||||
		EnableCall:   true,
 | 
					 | 
				
			||||||
		ChainConfig:  expectedChainConfig,
 | 
					 | 
				
			||||||
		ExtraEIPs:    []int64{},
 | 
					 | 
				
			||||||
	}, genstate.Params)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestMigrateCDP(t *testing.T) {
 | 
					 | 
				
			||||||
	appMap, ctx := migrateToV17AndGetAppMap(t)
 | 
					 | 
				
			||||||
	var genstate cdptypes.GenesisState
 | 
					 | 
				
			||||||
	err := ctx.Codec.UnmarshalJSON(appMap[cdptypes.ModuleName], &genstate)
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
	assert.Equal(t, genstate.Params.GlobalDebtLimit, sdk.NewCoin("usdx", sdk.NewInt(393000000000000)))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestMigrateAuction(t *testing.T) {
 | 
					 | 
				
			||||||
	appMap, ctx := migrateToV17AndGetAppMap(t)
 | 
					 | 
				
			||||||
	var genstate auctiontypes.GenesisState
 | 
					 | 
				
			||||||
	err := ctx.Codec.UnmarshalJSON(appMap[auctiontypes.ModuleName], &genstate)
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
	assert.Len(t, genstate.Auctions, 3)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestMigrateFeeMarket(t *testing.T) {
 | 
					 | 
				
			||||||
	appMap, ctx := migrateToV17AndGetAppMap(t)
 | 
					 | 
				
			||||||
	var genstate feemarkettypes.GenesisState
 | 
					 | 
				
			||||||
	err := ctx.Codec.UnmarshalJSON(appMap[feemarkettypes.ModuleName], &genstate)
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	expectedState := feemarkettypes.DefaultGenesisState()
 | 
					 | 
				
			||||||
	expectedState.Params.NoBaseFee = true
 | 
					 | 
				
			||||||
	assert.Equal(t, expectedState, &genstate)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestMigrateAuthz(t *testing.T) {
 | 
					 | 
				
			||||||
	appMap, ctx := migrateToV17AndGetAppMap(t)
 | 
					 | 
				
			||||||
	var genstate authz.GenesisState
 | 
					 | 
				
			||||||
	err := ctx.Codec.UnmarshalJSON(appMap[authz.ModuleName], &genstate)
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
	assert.Equal(t, genstate, authz.GenesisState{
 | 
					 | 
				
			||||||
		Authorization: []authz.GrantAuthorization{},
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestMigrateBridge(t *testing.T) {
 | 
					 | 
				
			||||||
	appMap, ctx := migrateToV17AndGetAppMap(t)
 | 
					 | 
				
			||||||
	var genstate bridgetypes.GenesisState
 | 
					 | 
				
			||||||
	err := ctx.Codec.UnmarshalJSON(appMap[bridgetypes.ModuleName], &genstate)
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	assert.Len(t, genstate.ERC20BridgePairs, 0)
 | 
					 | 
				
			||||||
	assert.Equal(t, genstate.NextWithdrawSequence, sdk.OneInt())
 | 
					 | 
				
			||||||
	assert.Equal(t, genstate.Params, bridgetypes.Params{
 | 
					 | 
				
			||||||
		BridgeEnabled:          false,
 | 
					 | 
				
			||||||
		EnabledERC20Tokens:     bridgetypes.EnabledERC20Tokens{},
 | 
					 | 
				
			||||||
		Relayer:                sdk.AccAddress{},
 | 
					 | 
				
			||||||
		EnabledConversionPairs: bridgetypes.ConversionPairs{},
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestMigrateIncentive(t *testing.T) {
 | 
					 | 
				
			||||||
	appMap, ctx := migrateToV17AndGetAppMap(t)
 | 
					 | 
				
			||||||
	var genstate incentivetypes.GenesisState
 | 
					 | 
				
			||||||
	err := ctx.Codec.UnmarshalJSON(appMap[incentivetypes.ModuleName], &genstate)
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
	assert.Len(t, genstate.SavingsClaims, 0)
 | 
					 | 
				
			||||||
	assert.Len(t, genstate.SavingsRewardState.AccumulationTimes, 0)
 | 
					 | 
				
			||||||
	assert.Len(t, genstate.SavingsRewardState.MultiRewardIndexes, 0)
 | 
					 | 
				
			||||||
	assert.Len(t, genstate.Params.SavingsRewardPeriods, 0)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestMigrateSavings(t *testing.T) {
 | 
					 | 
				
			||||||
	appMap, ctx := migrateToV17AndGetAppMap(t)
 | 
					 | 
				
			||||||
	var genstate savingstypes.GenesisState
 | 
					 | 
				
			||||||
	err := ctx.Codec.UnmarshalJSON(appMap[savingstypes.ModuleName], &genstate)
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
	assert.Len(t, genstate.Deposits, 0)
 | 
					 | 
				
			||||||
	assert.Equal(t, genstate.Params, savingstypes.Params{
 | 
					 | 
				
			||||||
		SupportedDenoms: []string{},
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestMigrateFull(t *testing.T) {
 | 
					 | 
				
			||||||
	t.Skip()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// File: https://s3.us-west-2.amazonaws.com/levi.testing.kava.io/kava-9-4-19-export-genesis.json
 | 
					 | 
				
			||||||
	// Height: 1145621
 | 
					 | 
				
			||||||
	genDoc, err := tmtypes.GenesisDocFromFile(filepath.Join("testdata", "kava-9-4-19-export-genesis.json"))
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
	ctx := newClientContext()
 | 
					 | 
				
			||||||
	newGenDoc, err := Migrate(genDoc, ctx)
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var appMap genutiltypes.AppMap
 | 
					 | 
				
			||||||
	err = tmjson.Unmarshal(newGenDoc.AppState, &appMap)
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
	config := app.MakeEncodingConfig()
 | 
					 | 
				
			||||||
	err = app.ModuleBasics.ValidateGenesis(ctx.Codec, config.TxConfig, appMap)
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
	tApp := app.NewTestApp()
 | 
					 | 
				
			||||||
	require.NotPanics(t, func() {
 | 
					 | 
				
			||||||
		tApp.InitializeFromGenesisStatesWithTimeAndChainID(newGenDoc.GenesisTime, newGenDoc.ChainID, app.GenesisState(appMap))
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func migrateToV17AndGetAppMap(t *testing.T) (genutiltypes.AppMap, client.Context) {
 | 
					 | 
				
			||||||
	genDoc, err := tmtypes.GenesisDocFromFile(filepath.Join("testdata", "genesis-v16.json"))
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ctx := newClientContext()
 | 
					 | 
				
			||||||
	actualGenDoc, err := Migrate(genDoc, ctx)
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var appMap genutiltypes.AppMap
 | 
					 | 
				
			||||||
	err = tmjson.Unmarshal(actualGenDoc.AppState, &appMap)
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return appMap, ctx
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func getTestDataJSON(filename string) string {
 | 
					 | 
				
			||||||
	file := filepath.Join("testdata", filename)
 | 
					 | 
				
			||||||
	data, err := ioutil.ReadFile(file)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		panic(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return string(data)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func newClientContext() client.Context {
 | 
					 | 
				
			||||||
	config := app.MakeEncodingConfig()
 | 
					 | 
				
			||||||
	return client.Context{}.
 | 
					 | 
				
			||||||
		WithCodec(config.Marshaler).
 | 
					 | 
				
			||||||
		WithLegacyAmino(config.Amino).
 | 
					 | 
				
			||||||
		WithInterfaceRegistry(config.InterfaceRegistry)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,45 +0,0 @@
 | 
				
			|||||||
# Kava-10 Rollback Instructions
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
In the event that the Kava-10 relaunch is unsuccessful, we will restart the Kava-9 chain using the last known state.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
In order to restore the previous chain, the following data must be recovered by validators:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- The database that contains the state of the previous chain (in ~/.kava/data by default)
 | 
					 | 
				
			||||||
- The priv_validator_state.json file of the validator (in ~/.kava/data by default)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
If you don't have the database data, the Kava developer team or another validator will share a copy of the database via Amazon s3 or a similar service. You will be able to download a copy of the data and verify it before starting your node.
 | 
					 | 
				
			||||||
If you don't have the backup priv_validator_state.json file, you will not have double sign protection on the first block. If this is the case, it's best to consult in the validator discord before starting your node.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Restoring state procedure
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
1. Stop your node
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```sh
 | 
					 | 
				
			||||||
kava stop
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
2. Copy the contents of your backup data directory back to the $KAVA_HOME/data directory. By default this is ~/.kava/data.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```sh
 | 
					 | 
				
			||||||
# Assumes backup is stored in "backup" directory
 | 
					 | 
				
			||||||
rm -rf ~/.kava/data
 | 
					 | 
				
			||||||
mv backup/.kava/data ~/.kava/data
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
3. Install the previous version of kava
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```sh
 | 
					 | 
				
			||||||
# from kava directory
 | 
					 | 
				
			||||||
git checkout v0.16.1
 | 
					 | 
				
			||||||
make install
 | 
					 | 
				
			||||||
## verify version
 | 
					 | 
				
			||||||
kava version --long
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
4. Start kava process
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```sh
 | 
					 | 
				
			||||||
### be sure to remove --halt-time flag if it is set
 | 
					 | 
				
			||||||
sudo systemctl daemon-reload
 | 
					 | 
				
			||||||
sudo systemctl start kava
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
							
								
								
									
										2327
									
								
								migrate/v0_17/testdata/genesis-v16.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2327
									
								
								migrate/v0_17/testdata/genesis-v16.json
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2366
									
								
								migrate/v0_17/testdata/genesis-v17.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2366
									
								
								migrate/v0_17/testdata/genesis-v17.json
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										20
									
								
								proto/kava/evmutil/v1beta1/conversion_pair.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								proto/kava/evmutil/v1beta1/conversion_pair.proto
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					syntax = "proto3";
 | 
				
			||||||
 | 
					package kava.evmutil.v1beta1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "gogoproto/gogo.proto";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					option go_package                    = "github.com/kava-labs/kava/x/evmutil/types";
 | 
				
			||||||
 | 
					option (gogoproto.equal_all)         = true;
 | 
				
			||||||
 | 
					option (gogoproto.verbose_equal_all) = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ConversionPair defines a Kava ERC20 address and corresponding denom that is
 | 
				
			||||||
 | 
					// allowed to be converted between ERC20 and sdk.Coin
 | 
				
			||||||
 | 
					message ConversionPair {
 | 
				
			||||||
 | 
					  option (gogoproto.goproto_getters) = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // ERC20 address of the token on the Kava EVM
 | 
				
			||||||
 | 
					  bytes kava_erc20_address = 1 [(gogoproto.customname) = "KavaERC20Address", (gogoproto.casttype) = "HexBytes"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Denom of the corresponding sdk.Coin
 | 
				
			||||||
 | 
					  string denom = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -3,19 +3,24 @@ package kava.evmutil.v1beta1;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import "gogoproto/gogo.proto";
 | 
					import "gogoproto/gogo.proto";
 | 
				
			||||||
import "cosmos_proto/cosmos.proto";
 | 
					import "cosmos_proto/cosmos.proto";
 | 
				
			||||||
 | 
					import "kava/evmutil/v1beta1/conversion_pair.proto";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
option go_package = "github.com/kava-labs/kava/x/evmutil/types";
 | 
					option go_package                    = "github.com/kava-labs/kava/x/evmutil/types";
 | 
				
			||||||
 | 
					option (gogoproto.equal_all)         = true;
 | 
				
			||||||
 | 
					option (gogoproto.verbose_equal_all) = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GenesisState defines the evmutil module's genesis state.
 | 
					// GenesisState defines the evmutil module's genesis state.
 | 
				
			||||||
message GenesisState {
 | 
					message GenesisState {
 | 
				
			||||||
  option (gogoproto.goproto_getters) = false;
 | 
					  option (gogoproto.goproto_getters) = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  repeated Account accounts = 1 [(gogoproto.nullable) = false];
 | 
					  repeated Account accounts = 1 [(gogoproto.nullable) = false];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // params defines all the parameters of the module.
 | 
				
			||||||
 | 
					  Params params = 2 [(gogoproto.nullable) = false];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BalanceAccount defines an account in the evmutil module.
 | 
					// BalanceAccount defines an account in the evmutil module.
 | 
				
			||||||
message Account {
 | 
					message Account {
 | 
				
			||||||
  option (gogoproto.equal)           = false;
 | 
					 | 
				
			||||||
  option (gogoproto.goproto_getters) = false;
 | 
					  option (gogoproto.goproto_getters) = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bytes address = 1 [
 | 
					  bytes address = 1 [
 | 
				
			||||||
@ -30,3 +35,11 @@ message Account {
 | 
				
			|||||||
    (gogoproto.nullable)   = false
 | 
					    (gogoproto.nullable)   = false
 | 
				
			||||||
  ];
 | 
					  ];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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
 | 
				
			||||||
 | 
					      [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "ConversionPairs"];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										26
									
								
								proto/kava/evmutil/v1beta1/query.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								proto/kava/evmutil/v1beta1/query.proto
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					syntax = "proto3";
 | 
				
			||||||
 | 
					package kava.evmutil.v1beta1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "gogoproto/gogo.proto";
 | 
				
			||||||
 | 
					import "google/api/annotations.proto";
 | 
				
			||||||
 | 
					import "kava/evmutil/v1beta1/genesis.proto";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					option go_package                    = "github.com/kava-labs/kava/x/evmutil/types";
 | 
				
			||||||
 | 
					option (gogoproto.equal_all)         = true;
 | 
				
			||||||
 | 
					option (gogoproto.verbose_equal_all) = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Query defines the gRPC querier service for evmutil module
 | 
				
			||||||
 | 
					service Query {
 | 
				
			||||||
 | 
					  // Params queries all parameters of the evmutil module.
 | 
				
			||||||
 | 
					  rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
 | 
				
			||||||
 | 
					    option (google.api.http).get = "/kava/evmutil/v1beta1/params";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// QueryParamsRequest defines the request type for querying x/evmutil parameters.
 | 
				
			||||||
 | 
					message QueryParamsRequest {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// QueryParamsResponse defines the response type for querying x/evmutil parameters.
 | 
				
			||||||
 | 
					message QueryParamsResponse {
 | 
				
			||||||
 | 
					  Params params = 1 [(gogoproto.nullable) = false];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										52
									
								
								proto/kava/evmutil/v1beta1/tx.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								proto/kava/evmutil/v1beta1/tx.proto
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					syntax = "proto3";
 | 
				
			||||||
 | 
					package kava.evmutil.v1beta1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "gogoproto/gogo.proto";
 | 
				
			||||||
 | 
					import "cosmos/base/v1beta1/coin.proto";
 | 
				
			||||||
 | 
					import "cosmos_proto/cosmos.proto";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					option go_package                    = "github.com/kava-labs/kava/x/evmutil/types";
 | 
				
			||||||
 | 
					option (gogoproto.equal_all)         = true;
 | 
				
			||||||
 | 
					option (gogoproto.verbose_equal_all) = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Msg defines the evmutil Msg service.
 | 
				
			||||||
 | 
					service Msg {
 | 
				
			||||||
 | 
					  // ConvertCoinToERC20 defines a method for converting sdk.Coin to Kava ERC20.
 | 
				
			||||||
 | 
					  rpc ConvertCoinToERC20(MsgConvertCoinToERC20) returns (MsgConvertCoinToERC20Response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // ConvertERC20ToCoin defines a method for converting Kava ERC20 to sdk.Coin.
 | 
				
			||||||
 | 
					  rpc ConvertERC20ToCoin(MsgConvertERC20ToCoin) returns (MsgConvertERC20ToCoinResponse);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MsgConvertCoinToERC20 defines a conversion from sdk.Coin to Kava ERC20.
 | 
				
			||||||
 | 
					message MsgConvertCoinToERC20 {
 | 
				
			||||||
 | 
					  // Kava bech32 address initiating the conversion.
 | 
				
			||||||
 | 
					  string initiator = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
 | 
				
			||||||
 | 
					  // 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MsgConvertCoinToERC20Response defines the response value from Msg/ConvertCoinToERC20.
 | 
				
			||||||
 | 
					message MsgConvertCoinToERC20Response {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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 [(cosmos_proto.scalar) = "cosmos.AddressString"];
 | 
				
			||||||
 | 
					  // EVM 0x hex address of the ERC20 contract.
 | 
				
			||||||
 | 
					  string kava_erc20_address = 3 [(gogoproto.customname) = "KavaERC20Address"];
 | 
				
			||||||
 | 
					  // ERC20 token amount to convert.
 | 
				
			||||||
 | 
					  string amount = 4 [
 | 
				
			||||||
 | 
					    (cosmos_proto.scalar)  = "cosmos.Int",
 | 
				
			||||||
 | 
					    (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
 | 
				
			||||||
 | 
					    (gogoproto.nullable)   = false
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MsgConvertERC20ToCoinResponse defines the response value from
 | 
				
			||||||
 | 
					// Msg/MsgConvertERC20ToCoin.
 | 
				
			||||||
 | 
					message MsgConvertERC20ToCoinResponse {}
 | 
				
			||||||
							
								
								
									
										73
									
								
								x/evmutil/client/cli/address.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								x/evmutil/client/cli/address.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,73 @@
 | 
				
			|||||||
 | 
					package cli
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ParseAddrFromHexOrBech32 parses a string address that can be either a hex or
 | 
				
			||||||
 | 
					//Bech32 string.
 | 
				
			||||||
 | 
					func ParseAddrFromHexOrBech32(addrString string) (common.Address, error) {
 | 
				
			||||||
 | 
						if common.IsHexAddress(addrString) {
 | 
				
			||||||
 | 
							return common.HexToAddress(addrString), nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cfg := sdk.GetConfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !strings.HasPrefix(addrString, cfg.GetBech32AccountAddrPrefix()) {
 | 
				
			||||||
 | 
							return common.Address{}, fmt.Errorf("receiver '%s' is not a hex or bech32 address (prefix does not match)", addrString)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						accAddr, err := sdk.AccAddressFromBech32(addrString)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return common.Address{}, fmt.Errorf("receiver '%s' is not a hex or bech32 address (could not parse as bech32 string)", addrString)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return common.BytesToAddress(accAddr), nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ParseOrQueryConversionPairAddress returns an EVM address of the provided
 | 
				
			||||||
 | 
					// ERC20 contract address string or denom. If an address string, just returns
 | 
				
			||||||
 | 
					// the parsed address. If a denom, fetches params, searches the enabled
 | 
				
			||||||
 | 
					// conversion pairs, and returns corresponding ERC20 contract address.
 | 
				
			||||||
 | 
					func ParseOrQueryConversionPairAddress(
 | 
				
			||||||
 | 
						queryClient types.QueryClient,
 | 
				
			||||||
 | 
						addrOrDenom string,
 | 
				
			||||||
 | 
					) (common.Address, error) {
 | 
				
			||||||
 | 
						if common.IsHexAddress(addrOrDenom) {
 | 
				
			||||||
 | 
							return common.HexToAddress(addrOrDenom), nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := sdk.ValidateDenom(addrOrDenom); err != nil {
 | 
				
			||||||
 | 
							return common.Address{}, fmt.Errorf(
 | 
				
			||||||
 | 
								"Kava ERC20 '%s' is not a valid hex address or denom",
 | 
				
			||||||
 | 
								addrOrDenom,
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Valid denom, try looking up as denom to get corresponding Kava ERC20 address
 | 
				
			||||||
 | 
						paramsRes, err := queryClient.Params(
 | 
				
			||||||
 | 
							context.Background(),
 | 
				
			||||||
 | 
							&types.QueryParamsRequest{},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return common.Address{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, pair := range paramsRes.Params.EnabledConversionPairs {
 | 
				
			||||||
 | 
							if pair.Denom == addrOrDenom {
 | 
				
			||||||
 | 
								return pair.GetAddress().Address, nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return common.Address{}, fmt.Errorf(
 | 
				
			||||||
 | 
							"Kava ERC20 '%s' is not a valid hex address or denom (did not match any denoms in queried enabled conversion pairs)",
 | 
				
			||||||
 | 
							addrOrDenom,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										129
									
								
								x/evmutil/client/cli/evm.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								x/evmutil/client/cli/evm.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,129 @@
 | 
				
			|||||||
 | 
					package cli
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/client"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/x/auth/signing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/accounts/abi"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common/hexutil"
 | 
				
			||||||
 | 
						ethtypes "github.com/ethereum/go-ethereum/core/types"
 | 
				
			||||||
 | 
						"github.com/tharsis/ethermint/crypto/hd"
 | 
				
			||||||
 | 
						"github.com/tharsis/ethermint/server/config"
 | 
				
			||||||
 | 
						etherminttypes "github.com/tharsis/ethermint/types"
 | 
				
			||||||
 | 
						evmtypes "github.com/tharsis/ethermint/x/evm/types"
 | 
				
			||||||
 | 
						feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CanSignEthTx returns an error if the signing key algorithm is not eth_secp256k1.
 | 
				
			||||||
 | 
					func CanSignEthTx(ctx client.Context) error {
 | 
				
			||||||
 | 
						keyInfo, err := ctx.Keyring.KeyByAddress(ctx.FromAddress)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if keyInfo.GetAlgo() != hd.EthSecp256k1Type {
 | 
				
			||||||
 | 
							return fmt.Errorf("from address does not support %v", hd.EthSecp256k1Type)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PackContractCallData creates a smart contract method call data with the
 | 
				
			||||||
 | 
					// provided method and args.
 | 
				
			||||||
 | 
					func PackContractCallData(abi abi.ABI, method string, args ...interface{}) ([]byte, error) {
 | 
				
			||||||
 | 
						data, err := abi.Pack(method, args...)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("failed to create transaction data: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return data, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CreateEthCallContractTx creates and signs a Eth transaction wrapped in a
 | 
				
			||||||
 | 
					// cosmos Tx.
 | 
				
			||||||
 | 
					func CreateEthCallContractTx(
 | 
				
			||||||
 | 
						ctx client.Context,
 | 
				
			||||||
 | 
						contractAddr *common.Address,
 | 
				
			||||||
 | 
						data []byte,
 | 
				
			||||||
 | 
					) (signing.Tx, error) {
 | 
				
			||||||
 | 
						evmQueryClient := evmtypes.NewQueryClient(ctx)
 | 
				
			||||||
 | 
						feemarketQueryClient := feemarkettypes.NewQueryClient(ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						chainID, err := etherminttypes.ParseChainID(ctx.ChainID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("failed to parse chain ID: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						evmParamsRes, err := evmQueryClient.Params(context.Background(), &evmtypes.QueryParamsRequest{})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("failed to fetch evm params: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Estimate Gas
 | 
				
			||||||
 | 
						from := common.BytesToAddress(ctx.FromAddress.Bytes())
 | 
				
			||||||
 | 
						transactionArgs := evmtypes.TransactionArgs{
 | 
				
			||||||
 | 
							From: &from,
 | 
				
			||||||
 | 
							To:   contractAddr,
 | 
				
			||||||
 | 
							Data: (*hexutil.Bytes)(&data),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						args, err := json.Marshal(transactionArgs)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("failed to marshal transaction args for gas estimate: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						res, err := evmQueryClient.EstimateGas(context.Background(), &evmtypes.EthCallRequest{
 | 
				
			||||||
 | 
							Args:   args,
 | 
				
			||||||
 | 
							GasCap: config.DefaultGasCap,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("failed to estimate gas from EVM: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Fetch base fee
 | 
				
			||||||
 | 
						basefeeRes, err := feemarketQueryClient.BaseFee(
 | 
				
			||||||
 | 
							context.Background(),
 | 
				
			||||||
 | 
							&feemarkettypes.QueryBaseFeeRequest{},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("failed to fetch basefee from feemarket: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Fetch account nonce, ignore error to use use 0 nonce if first tx
 | 
				
			||||||
 | 
						_, accSeq, _ := ctx.AccountRetriever.GetAccountNumberSequence(ctx, ctx.FromAddress)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Create MsgEthereumTx
 | 
				
			||||||
 | 
						ethTx := evmtypes.NewTx(
 | 
				
			||||||
 | 
							chainID,
 | 
				
			||||||
 | 
							accSeq,                      // nonce
 | 
				
			||||||
 | 
							contractAddr,                // to
 | 
				
			||||||
 | 
							nil,                         // amount
 | 
				
			||||||
 | 
							res.Gas,                     // gasLimit
 | 
				
			||||||
 | 
							nil,                         // gasPrice
 | 
				
			||||||
 | 
							basefeeRes.BaseFee.BigInt(), // gasFeeCap
 | 
				
			||||||
 | 
							big.NewInt(1),               // gasTipCap
 | 
				
			||||||
 | 
							data,                        // input
 | 
				
			||||||
 | 
							ðtypes.AccessList{},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Must set from address before signing
 | 
				
			||||||
 | 
						ethTx.From = from.String()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Sign Ethereum TX (not the cosmos Msg)
 | 
				
			||||||
 | 
						signer := ethtypes.LatestSignerForChainID(chainID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Must sign with a `/ethermint.crypto.v1.ethsecp256k1.PubKey` and not
 | 
				
			||||||
 | 
						// `/cosmos.crypto.secp256k1.PubKey` or this will panic with the following:
 | 
				
			||||||
 | 
						// panic: wrong size for signature: got 64, want 65
 | 
				
			||||||
 | 
						if err := ethTx.Sign(signer, ctx.Keyring); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ethTx.BuildTx(ctx.TxConfig.NewTxBuilder(), evmParamsRes.Params.EvmDenom)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										63
									
								
								x/evmutil/client/cli/query.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								x/evmutil/client/cli/query.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,63 @@
 | 
				
			|||||||
 | 
					package cli
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/client"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/client/flags"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/version"
 | 
				
			||||||
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetQueryCmd returns the cli query commands for this module
 | 
				
			||||||
 | 
					func GetQueryCmd() *cobra.Command {
 | 
				
			||||||
 | 
						evmutilQueryCmd := &cobra.Command{
 | 
				
			||||||
 | 
							Use:                        "evmutil",
 | 
				
			||||||
 | 
							Short:                      "Querying commands for the evmutil module",
 | 
				
			||||||
 | 
							DisableFlagParsing:         true,
 | 
				
			||||||
 | 
							SuggestionsMinimumDistance: 2,
 | 
				
			||||||
 | 
							RunE:                       client.ValidateCmd,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmds := []*cobra.Command{
 | 
				
			||||||
 | 
							QueryParamsCmd(),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, cmd := range cmds {
 | 
				
			||||||
 | 
							flags.AddQueryFlagsToCmd(cmd)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						evmutilQueryCmd.AddCommand(cmds...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return evmutilQueryCmd
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// QueryParamsCmd queries the evmutil module parameters
 | 
				
			||||||
 | 
					func QueryParamsCmd() *cobra.Command {
 | 
				
			||||||
 | 
						return &cobra.Command{
 | 
				
			||||||
 | 
							Use:   "params",
 | 
				
			||||||
 | 
							Short: "Query the evmutil module parameters",
 | 
				
			||||||
 | 
							Example: fmt.Sprintf(
 | 
				
			||||||
 | 
								"%[1]s q %[2]s params",
 | 
				
			||||||
 | 
								version.AppName, types.ModuleName,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							Args: cobra.NoArgs,
 | 
				
			||||||
 | 
							RunE: func(cmd *cobra.Command, args []string) error {
 | 
				
			||||||
 | 
								clientCtx, err := client.GetClientQueryContext(cmd)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								queryClient := types.NewQueryClient(clientCtx)
 | 
				
			||||||
 | 
								res, err := queryClient.Params(context.Background(), &types.QueryParamsRequest{})
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return clientCtx.PrintProto(&res.Params)
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										122
									
								
								x/evmutil/client/cli/tx.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								x/evmutil/client/cli/tx.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,122 @@
 | 
				
			|||||||
 | 
					package cli
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/client"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/client/flags"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/client/tx"
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/version"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetTxCmd returns the transaction commands for this module
 | 
				
			||||||
 | 
					func GetTxCmd() *cobra.Command {
 | 
				
			||||||
 | 
						txCmd := &cobra.Command{
 | 
				
			||||||
 | 
							Use:                        types.ModuleName,
 | 
				
			||||||
 | 
							Short:                      fmt.Sprintf("%s transactions subcommands", types.ModuleName),
 | 
				
			||||||
 | 
							DisableFlagParsing:         true,
 | 
				
			||||||
 | 
							SuggestionsMinimumDistance: 2,
 | 
				
			||||||
 | 
							RunE:                       client.ValidateCmd,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmds := []*cobra.Command{
 | 
				
			||||||
 | 
							getCmdMsgConvertCoinToERC20(),
 | 
				
			||||||
 | 
							getCmdConvertERC20ToCoin(),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, cmd := range cmds {
 | 
				
			||||||
 | 
							flags.AddTxFlagsToCmd(cmd)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						txCmd.AddCommand(cmds...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return txCmd
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getCmdMsgConvertCoinToERC20() *cobra.Command {
 | 
				
			||||||
 | 
						return &cobra.Command{
 | 
				
			||||||
 | 
							Use:   "convert-coin-to-erc20 [Kava ERC20 address] [coin]",
 | 
				
			||||||
 | 
							Short: "converts sdk.Coin to erc20 tokens on Kava eth co-chain",
 | 
				
			||||||
 | 
							Example: fmt.Sprintf(
 | 
				
			||||||
 | 
								`%s tx %s convert-coin-to-erc20 0x7Bbf300890857b8c241b219C6a489431669b3aFA 500000000erc20/usdc --from <key> --gas 2000000`,
 | 
				
			||||||
 | 
								version.AppName, types.ModuleName,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							Args: cobra.ExactArgs(2),
 | 
				
			||||||
 | 
							RunE: func(cmd *cobra.Command, args []string) error {
 | 
				
			||||||
 | 
								clientCtx, err := client.GetClientTxContext(cmd)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								receiver := args[0]
 | 
				
			||||||
 | 
								if !common.IsHexAddress(receiver) {
 | 
				
			||||||
 | 
									return fmt.Errorf("receiver '%s' is an invalid hex address", args[0])
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								coin, err := sdk.ParseCoinNormalized(args[1])
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								signer := clientCtx.GetFromAddress()
 | 
				
			||||||
 | 
								msg := types.NewMsgConvertCoinToERC20(signer.String(), receiver, coin)
 | 
				
			||||||
 | 
								if err := msg.ValidateBasic(); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getCmdConvertERC20ToCoin() *cobra.Command {
 | 
				
			||||||
 | 
						return &cobra.Command{
 | 
				
			||||||
 | 
							Use:   "convert-erc20-to-coin [Kava receiver address] [Kava ERC20 address] [amount]",
 | 
				
			||||||
 | 
							Short: "burns ERC20 tokens on Kava EVM co-chain and unlocks on Ethereum",
 | 
				
			||||||
 | 
							Example: fmt.Sprintf(`
 | 
				
			||||||
 | 
					%[1]s tx %[2]s convert-erc20-to-coin kava10wlnqzyss4accfqmyxwx5jy5x9nfkwh6qm7n4t 0xeA7100edA2f805356291B0E55DaD448599a72C6d 1000000000000000 --from <key> --gas 1000000
 | 
				
			||||||
 | 
					`, version.AppName, types.ModuleName,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							Args: cobra.ExactArgs(3),
 | 
				
			||||||
 | 
							RunE: func(cmd *cobra.Command, args []string) error {
 | 
				
			||||||
 | 
								clientCtx, err := client.GetClientTxContext(cmd)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								receiver, err := sdk.AccAddressFromBech32(args[0])
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return fmt.Errorf("receiver '%s' is not a bech32 address", args[0])
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								signer := clientCtx.GetFromAddress()
 | 
				
			||||||
 | 
								initiator, err := ParseAddrFromHexOrBech32(signer.String())
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								amount, ok := sdk.NewIntFromString(args[2])
 | 
				
			||||||
 | 
								if !ok {
 | 
				
			||||||
 | 
									return fmt.Errorf("amount '%s' is invalid", args[2])
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if !common.IsHexAddress(args[1]) {
 | 
				
			||||||
 | 
									return fmt.Errorf("contractAddr '%s' is not a hex address", args[1])
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								contractAddr := types.NewInternalEVMAddress(common.HexToAddress(args[1]))
 | 
				
			||||||
 | 
								msg := types.NewMsgConvertERC20ToCoin(types.NewInternalEVMAddress(initiator), receiver, contractAddr, amount)
 | 
				
			||||||
 | 
								if err := msg.ValidateBasic(); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										86
									
								
								x/evmutil/client/cli/tx_util.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								x/evmutil/client/cli/tx_util.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,86 @@
 | 
				
			|||||||
 | 
					package cli
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bufio"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/client"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/client/input"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/x/auth/signing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GenerateOrBroadcastTx checks CLI flags and generates or broadcasts a
 | 
				
			||||||
 | 
					// transaction this is used over tx.GenerateOrBroadcastTxCLI as it does not sign
 | 
				
			||||||
 | 
					// the message.
 | 
				
			||||||
 | 
					func GenerateOrBroadcastTx(clientCtx client.Context, signingTx signing.Tx) error {
 | 
				
			||||||
 | 
						// These manual flag checks are required as we use broadcast the tx
 | 
				
			||||||
 | 
						// directly via BroadcastTx instead of tx.GenerateOrBroadcastTxCLI
 | 
				
			||||||
 | 
						// which handles flags for us.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if clientCtx.GenerateOnly {
 | 
				
			||||||
 | 
							if err := PrintTx(clientCtx, signingTx); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := ConfirmTx(clientCtx, signingTx); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						txBytes, err := clientCtx.TxConfig.TxEncoder()(signingTx)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						res, err := clientCtx.BroadcastTx(txBytes)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return clientCtx.PrintProto(res)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PrintTx outputs a signing.Tx in JSON format, ie. when the GenerateOnly flag
 | 
				
			||||||
 | 
					// is enabled.
 | 
				
			||||||
 | 
					func PrintTx(clientCtx client.Context, signingTx signing.Tx) error {
 | 
				
			||||||
 | 
						json, err := clientCtx.TxConfig.TxJSONEncoder()(signingTx)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return clientCtx.PrintString(fmt.Sprintf("%s\n", json))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ConfirmTx outputs the transaction to be signed and requests confirmation
 | 
				
			||||||
 | 
					// if the SkipConfirm flag is not enabled.
 | 
				
			||||||
 | 
					func ConfirmTx(clientCtx client.Context, signingTx signing.Tx) error {
 | 
				
			||||||
 | 
						if clientCtx.SkipConfirm {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out, err := clientCtx.TxConfig.TxJSONEncoder()(signingTx)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err = fmt.Fprintf(os.Stderr, "%s\n\n", out)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buf := bufio.NewReader(os.Stdin)
 | 
				
			||||||
 | 
						ok, err := input.GetConfirmation("confirm transaction before signing and broadcasting", buf, os.Stderr)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							_, err = fmt.Fprintf(os.Stderr, "%s\n", "cancelled transaction")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -15,6 +15,8 @@ func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, gs *types.GenesisState)
 | 
				
			|||||||
		panic(fmt.Sprintf("failed to validate %s genesis state: %s", types.ModuleName, err))
 | 
							panic(fmt.Sprintf("failed to validate %s genesis state: %s", types.ModuleName, err))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						keeper.SetParams(ctx, gs.Params)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, account := range gs.Accounts {
 | 
						for _, account := range gs.Accounts {
 | 
				
			||||||
		keeper.SetAccount(ctx, account)
 | 
							keeper.SetAccount(ctx, account)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -23,5 +25,5 @@ func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, gs *types.GenesisState)
 | 
				
			|||||||
// ExportGenesis returns a GenesisState for a given context and keeper.
 | 
					// ExportGenesis returns a GenesisState for a given context and keeper.
 | 
				
			||||||
func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) *types.GenesisState {
 | 
					func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) *types.GenesisState {
 | 
				
			||||||
	accounts := keeper.GetAllAccounts(ctx)
 | 
						accounts := keeper.GetAllAccounts(ctx)
 | 
				
			||||||
	return types.NewGenesisState(accounts)
 | 
						return types.NewGenesisState(accounts, keeper.GetParams(ctx))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -20,9 +20,12 @@ func (suite *genesisTestSuite) SetupTest() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *genesisTestSuite) TestInitGenesis_SetAccounts() {
 | 
					func (s *genesisTestSuite) TestInitGenesis_SetAccounts() {
 | 
				
			||||||
	gs := types.NewGenesisState([]types.Account{
 | 
						gs := types.NewGenesisState(
 | 
				
			||||||
		{Address: s.Addrs[0], Balance: sdk.NewInt(100)},
 | 
							[]types.Account{
 | 
				
			||||||
	})
 | 
								{Address: s.Addrs[0], Balance: sdk.NewInt(100)},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							types.DefaultParams(),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
	accounts := s.Keeper.GetAllAccounts(s.Ctx)
 | 
						accounts := s.Keeper.GetAllAccounts(s.Ctx)
 | 
				
			||||||
	s.Require().Len(accounts, 0)
 | 
						s.Require().Len(accounts, 0)
 | 
				
			||||||
	evmutil.InitGenesis(s.Ctx, s.Keeper, gs)
 | 
						evmutil.InitGenesis(s.Ctx, s.Keeper, gs)
 | 
				
			||||||
@ -33,10 +36,30 @@ func (s *genesisTestSuite) TestInitGenesis_SetAccounts() {
 | 
				
			|||||||
	s.Require().Equal(account.Balance, sdk.NewInt(100))
 | 
						s.Require().Equal(account.Balance, sdk.NewInt(100))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *genesisTestSuite) TestInitGenesis_SetParams() {
 | 
				
			||||||
 | 
						params := types.DefaultParams()
 | 
				
			||||||
 | 
						conversionPair := types.ConversionPair{
 | 
				
			||||||
 | 
							KavaERC20Address: testutil.MustNewInternalEVMAddressFromString("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2").Bytes(),
 | 
				
			||||||
 | 
							Denom:            "weth",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						params.EnabledConversionPairs = []types.ConversionPair{conversionPair}
 | 
				
			||||||
 | 
						gs := types.NewGenesisState(
 | 
				
			||||||
 | 
							[]types.Account{},
 | 
				
			||||||
 | 
							params,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						evmutil.InitGenesis(s.Ctx, s.Keeper, gs)
 | 
				
			||||||
 | 
						params = s.Keeper.GetParams(s.Ctx)
 | 
				
			||||||
 | 
						s.Require().Len(params.EnabledConversionPairs, 1)
 | 
				
			||||||
 | 
						s.Require().Equal(conversionPair, params.EnabledConversionPairs[0])
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *genesisTestSuite) TestInitGenesis_ValidateFail() {
 | 
					func (s *genesisTestSuite) TestInitGenesis_ValidateFail() {
 | 
				
			||||||
	gs := types.NewGenesisState([]types.Account{
 | 
						gs := types.NewGenesisState(
 | 
				
			||||||
		{Address: s.Addrs[0], Balance: sdk.NewInt(-100)},
 | 
							[]types.Account{
 | 
				
			||||||
	})
 | 
								{Address: s.Addrs[0], Balance: sdk.NewInt(-100)},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							types.DefaultParams(),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
	s.Require().Panics(func() {
 | 
						s.Require().Panics(func() {
 | 
				
			||||||
		evmutil.InitGenesis(s.Ctx, s.Keeper, gs)
 | 
							evmutil.InitGenesis(s.Ctx, s.Keeper, gs)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@ -50,8 +73,16 @@ func (s *genesisTestSuite) TestExportGenesis() {
 | 
				
			|||||||
	for _, account := range accounts {
 | 
						for _, account := range accounts {
 | 
				
			||||||
		s.Keeper.SetAccount(s.Ctx, account)
 | 
							s.Keeper.SetAccount(s.Ctx, account)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						params := types.DefaultParams()
 | 
				
			||||||
 | 
						params.EnabledConversionPairs = []types.ConversionPair{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								KavaERC20Address: testutil.MustNewInternalEVMAddressFromString("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2").Bytes(),
 | 
				
			||||||
 | 
								Denom:            "weth"},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						s.Keeper.SetParams(s.Ctx, params)
 | 
				
			||||||
	gs := evmutil.ExportGenesis(s.Ctx, s.Keeper)
 | 
						gs := evmutil.ExportGenesis(s.Ctx, s.Keeper)
 | 
				
			||||||
	s.Require().Equal(gs.Accounts, accounts)
 | 
						s.Require().Equal(gs.Accounts, accounts)
 | 
				
			||||||
 | 
						s.Require().Equal(params, gs.Params)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestGenesisTestSuite(t *testing.T) {
 | 
					func TestGenesisTestSuite(t *testing.T) {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										223
									
								
								x/evmutil/keeper/conversion.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										223
									
								
								x/evmutil/keeper/conversion.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,223 @@
 | 
				
			|||||||
 | 
					package keeper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MintConversionPairCoin mints the given amount of a ConversionPair denom and
 | 
				
			||||||
 | 
					// sends it to the provided address.
 | 
				
			||||||
 | 
					func (k Keeper) MintConversionPairCoin(
 | 
				
			||||||
 | 
						ctx sdk.Context,
 | 
				
			||||||
 | 
						pair types.ConversionPair,
 | 
				
			||||||
 | 
						amount *big.Int,
 | 
				
			||||||
 | 
						recipient sdk.AccAddress,
 | 
				
			||||||
 | 
					) (sdk.Coin, error) {
 | 
				
			||||||
 | 
						coin := sdk.NewCoin(pair.Denom, sdk.NewIntFromBigInt(amount))
 | 
				
			||||||
 | 
						coins := sdk.NewCoins(coin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := k.bankKeeper.MintCoins(ctx, types.ModuleName, coins); err != nil {
 | 
				
			||||||
 | 
							return sdk.Coin{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, recipient, coins); err != nil {
 | 
				
			||||||
 | 
							return sdk.Coin{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return coin, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// BurnConversionPairCoin transfers the provided amount to the module account
 | 
				
			||||||
 | 
					// then burns it.
 | 
				
			||||||
 | 
					func (k Keeper) BurnConversionPairCoin(
 | 
				
			||||||
 | 
						ctx sdk.Context,
 | 
				
			||||||
 | 
						pair types.ConversionPair,
 | 
				
			||||||
 | 
						coin sdk.Coin,
 | 
				
			||||||
 | 
						account sdk.AccAddress,
 | 
				
			||||||
 | 
					) error {
 | 
				
			||||||
 | 
						coins := sdk.NewCoins(coin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, account, types.ModuleName, coins); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := k.bankKeeper.BurnCoins(ctx, types.ModuleName, coins); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ConvertCoinToERC20 converts an sdk.Coin from the originating account to an
 | 
				
			||||||
 | 
					// ERC20 to the receiver account.
 | 
				
			||||||
 | 
					func (k Keeper) ConvertCoinToERC20(
 | 
				
			||||||
 | 
						ctx sdk.Context,
 | 
				
			||||||
 | 
						initiatorAccount sdk.AccAddress,
 | 
				
			||||||
 | 
						receiverAccount types.InternalEVMAddress,
 | 
				
			||||||
 | 
						coin sdk.Coin,
 | 
				
			||||||
 | 
					) error {
 | 
				
			||||||
 | 
						pair, err := k.GetEnabledConversionPairFromDenom(ctx, coin.Denom)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							// Coin not in enabled conversion pair list
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := k.BurnConversionPairCoin(ctx, pair, coin, initiatorAccount); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := k.UnlockERC20Tokens(ctx, pair, coin.Amount.BigInt(), receiverAccount); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.EventManager().EmitEvent(sdk.NewEvent(
 | 
				
			||||||
 | 
							types.EventTypeConvertCoinToERC20,
 | 
				
			||||||
 | 
							sdk.NewAttribute(types.AttributeKeyInitiator, initiatorAccount.String()),
 | 
				
			||||||
 | 
							sdk.NewAttribute(types.AttributeKeyReceiver, receiverAccount.String()),
 | 
				
			||||||
 | 
							sdk.NewAttribute(types.AttributeKeyERC20Address, pair.GetAddress().String()),
 | 
				
			||||||
 | 
							sdk.NewAttribute(types.AttributeKeyAmount, coin.String()),
 | 
				
			||||||
 | 
						))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ConvertERC20ToCoin converts an ERC20 coin from the originating account to an
 | 
				
			||||||
 | 
					// sdk.Coin to the receiver account.
 | 
				
			||||||
 | 
					func (k Keeper) ConvertERC20ToCoin(
 | 
				
			||||||
 | 
						ctx sdk.Context,
 | 
				
			||||||
 | 
						initiator types.InternalEVMAddress,
 | 
				
			||||||
 | 
						receiver sdk.AccAddress,
 | 
				
			||||||
 | 
						contractAddr types.InternalEVMAddress,
 | 
				
			||||||
 | 
						amount sdk.Int,
 | 
				
			||||||
 | 
					) error {
 | 
				
			||||||
 | 
						// Check that the contract is enabled to convert to coin
 | 
				
			||||||
 | 
						pair, err := k.GetEnabledConversionPairFromERC20Address(ctx, contractAddr)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							// contract not in enabled conversion pair list
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// lock erc20 tokens
 | 
				
			||||||
 | 
						if err := k.LockERC20Tokens(ctx, pair, amount.BigInt(), initiator); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// mint conversion pair coin
 | 
				
			||||||
 | 
						coin, err := k.MintConversionPairCoin(ctx, pair, amount.BigInt(), receiver)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.EventManager().EmitEvent(sdk.NewEvent(
 | 
				
			||||||
 | 
							types.EventTypeConvertERC20ToCoin,
 | 
				
			||||||
 | 
							sdk.NewAttribute(types.AttributeKeyERC20Address, contractAddr.String()),
 | 
				
			||||||
 | 
							sdk.NewAttribute(types.AttributeKeyInitiator, initiator.String()),
 | 
				
			||||||
 | 
							sdk.NewAttribute(types.AttributeKeyReceiver, receiver.String()),
 | 
				
			||||||
 | 
							sdk.NewAttribute(types.AttributeKeyAmount, coin.String()),
 | 
				
			||||||
 | 
						))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UnlockERC20Tokens transfers the given amount of a conversion pair ERC20 token
 | 
				
			||||||
 | 
					// to the provided account.
 | 
				
			||||||
 | 
					func (k Keeper) UnlockERC20Tokens(
 | 
				
			||||||
 | 
						ctx sdk.Context,
 | 
				
			||||||
 | 
						pair types.ConversionPair,
 | 
				
			||||||
 | 
						amount *big.Int,
 | 
				
			||||||
 | 
						receiver types.InternalEVMAddress,
 | 
				
			||||||
 | 
					) error {
 | 
				
			||||||
 | 
						contractAddr := pair.GetAddress()
 | 
				
			||||||
 | 
						startBal, err := k.QueryERC20BalanceOf(ctx, contractAddr, receiver)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return sdkerrors.Wrapf(types.ErrEVMCall, "failed to retrieve balance %s", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						res, err := k.CallEVM(
 | 
				
			||||||
 | 
							ctx,
 | 
				
			||||||
 | 
							types.ERC20MintableBurnableContract.ABI, // abi
 | 
				
			||||||
 | 
							types.ModuleEVMAddress,                  // from addr
 | 
				
			||||||
 | 
							pair.GetAddress(),                       // contract addr
 | 
				
			||||||
 | 
							"transfer",                              // method
 | 
				
			||||||
 | 
							// Transfer ERC20 args
 | 
				
			||||||
 | 
							receiver.Address,
 | 
				
			||||||
 | 
							amount,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// validate end bal
 | 
				
			||||||
 | 
						endBal, err := k.QueryERC20BalanceOf(ctx, contractAddr, receiver)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return sdkerrors.Wrapf(types.ErrEVMCall, "failed to retrieve balance %s", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						expectedEndBal := big.NewInt(0).Add(startBal, amount)
 | 
				
			||||||
 | 
						if expectedEndBal.Cmp(endBal) != 0 {
 | 
				
			||||||
 | 
							return sdkerrors.Wrapf(
 | 
				
			||||||
 | 
								types.ErrBalanceInvariance,
 | 
				
			||||||
 | 
								"invalid token balance - expected: %v, actual: %v",
 | 
				
			||||||
 | 
								expectedEndBal, endBal,
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check for unexpected `Approval` event in logs
 | 
				
			||||||
 | 
						if err := k.monitorApprovalEvent(res); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// LockERC20Tokens transfers the given amount of a conversion pair ERC20 token
 | 
				
			||||||
 | 
					// from the initiator account to the module account.
 | 
				
			||||||
 | 
					func (k Keeper) LockERC20Tokens(
 | 
				
			||||||
 | 
						ctx sdk.Context,
 | 
				
			||||||
 | 
						pair types.ConversionPair,
 | 
				
			||||||
 | 
						amount *big.Int,
 | 
				
			||||||
 | 
						initiator types.InternalEVMAddress,
 | 
				
			||||||
 | 
					) error {
 | 
				
			||||||
 | 
						contractAddr := pair.GetAddress()
 | 
				
			||||||
 | 
						initiatorStartBal, err := k.QueryERC20BalanceOf(ctx, contractAddr, initiator)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return sdkerrors.Wrapf(types.ErrEVMCall, "failed to retrieve balance %s", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						res, err := k.CallEVM(
 | 
				
			||||||
 | 
							ctx,
 | 
				
			||||||
 | 
							types.ERC20MintableBurnableContract.ABI, // abi
 | 
				
			||||||
 | 
							initiator.Address,                       // from addr
 | 
				
			||||||
 | 
							contractAddr,                            // contract addr
 | 
				
			||||||
 | 
							"transfer",                              // method
 | 
				
			||||||
 | 
							// Transfer ERC20 args
 | 
				
			||||||
 | 
							types.ModuleEVMAddress,
 | 
				
			||||||
 | 
							amount,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// validate end bal
 | 
				
			||||||
 | 
						initiatorEndBal, err := k.QueryERC20BalanceOf(ctx, contractAddr, initiator)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return sdkerrors.Wrapf(types.ErrEVMCall, "failed to retrieve balance %s", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						expectedEndBal := big.NewInt(0).Sub(initiatorStartBal, amount)
 | 
				
			||||||
 | 
						if expectedEndBal.Cmp(initiatorEndBal) != 0 {
 | 
				
			||||||
 | 
							return sdkerrors.Wrapf(
 | 
				
			||||||
 | 
								types.ErrBalanceInvariance,
 | 
				
			||||||
 | 
								"invalid token balance - expected: %v, actual: %v",
 | 
				
			||||||
 | 
								expectedEndBal, initiatorEndBal,
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check for unexpected `Approval` event in logs
 | 
				
			||||||
 | 
						if err := k.monitorApprovalEvent(res); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										345
									
								
								x/evmutil/keeper/conversion_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										345
									
								
								x/evmutil/keeper/conversion_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,345 @@
 | 
				
			|||||||
 | 
					package keeper_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/suite"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/testutil"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ConversionTestSuite struct {
 | 
				
			||||||
 | 
						testutil.Suite
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestConversionTestSuite(t *testing.T) {
 | 
				
			||||||
 | 
						suite.Run(t, new(ConversionTestSuite))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ConversionTestSuite) TestMint() {
 | 
				
			||||||
 | 
						pair := types.NewConversionPair(
 | 
				
			||||||
 | 
							testutil.MustNewInternalEVMAddressFromString("0x000000000000000000000000000000000000000A"),
 | 
				
			||||||
 | 
							"erc20/usdc",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						amount := big.NewInt(100)
 | 
				
			||||||
 | 
						recipient := suite.Key1.PubKey().Address().Bytes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						coin, err := suite.Keeper.MintConversionPairCoin(suite.Ctx, pair, amount, recipient)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						suite.Require().Equal(sdk.NewCoin(pair.Denom, sdk.NewIntFromBigInt(amount)), coin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bal := suite.App.GetBankKeeper().GetBalance(suite.Ctx, recipient, pair.Denom)
 | 
				
			||||||
 | 
						suite.Require().Equal(amount, bal.Amount.BigInt(), "minted amount should increase balance")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ConversionTestSuite) TestBurn_InsufficientBalance() {
 | 
				
			||||||
 | 
						pair := types.NewConversionPair(
 | 
				
			||||||
 | 
							testutil.MustNewInternalEVMAddressFromString("0x000000000000000000000000000000000000000A"),
 | 
				
			||||||
 | 
							"erc20/usdc",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						amount := sdk.NewInt(100)
 | 
				
			||||||
 | 
						recipient := suite.Key1.PubKey().Address().Bytes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := suite.Keeper.BurnConversionPairCoin(suite.Ctx, pair, sdk.NewCoin(pair.Denom, amount), recipient)
 | 
				
			||||||
 | 
						suite.Require().Error(err)
 | 
				
			||||||
 | 
						suite.Require().Equal("0erc20/usdc is smaller than 100erc20/usdc: insufficient funds", err.Error())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ConversionTestSuite) TestBurn() {
 | 
				
			||||||
 | 
						pair := types.NewConversionPair(
 | 
				
			||||||
 | 
							testutil.MustNewInternalEVMAddressFromString("0x000000000000000000000000000000000000000A"),
 | 
				
			||||||
 | 
							"erc20/usdc",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						amount := sdk.NewInt(100)
 | 
				
			||||||
 | 
						recipient := suite.Key1.PubKey().Address().Bytes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						coin, err := suite.Keeper.MintConversionPairCoin(suite.Ctx, pair, amount.BigInt(), recipient)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						suite.Require().Equal(sdk.NewCoin(pair.Denom, amount), coin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bal := suite.App.GetBankKeeper().GetBalance(suite.Ctx, recipient, pair.Denom)
 | 
				
			||||||
 | 
						suite.Require().Equal(amount, bal.Amount, "minted amount should increase balance")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = suite.Keeper.BurnConversionPairCoin(suite.Ctx, pair, sdk.NewCoin(pair.Denom, amount), recipient)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bal = suite.App.GetBankKeeper().GetBalance(suite.Ctx, recipient, pair.Denom)
 | 
				
			||||||
 | 
						suite.Require().Equal(sdk.ZeroInt(), bal.Amount, "balance should be zero after burn")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ConversionTestSuite) TestUnlockERC20Tokens() {
 | 
				
			||||||
 | 
						contractAddr := suite.DeployERC20()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pair := types.NewConversionPair(
 | 
				
			||||||
 | 
							contractAddr,
 | 
				
			||||||
 | 
							"erc20/usdc",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						amount := big.NewInt(100)
 | 
				
			||||||
 | 
						recipient := types.NewInternalEVMAddress(common.BytesToAddress(suite.Key1.PubKey().Address()))
 | 
				
			||||||
 | 
						moduleAddr := types.NewInternalEVMAddress(types.ModuleEVMAddress)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Mint some initial balance for module account to transfer
 | 
				
			||||||
 | 
						err := suite.Keeper.MintERC20(
 | 
				
			||||||
 | 
							suite.Ctx,
 | 
				
			||||||
 | 
							pair.GetAddress(), // contractAddr
 | 
				
			||||||
 | 
							moduleAddr,        //receiver
 | 
				
			||||||
 | 
							amount,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = suite.Keeper.UnlockERC20Tokens(suite.Ctx, pair, amount, recipient)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check balance of recipient
 | 
				
			||||||
 | 
						bal := suite.GetERC20BalanceOf(
 | 
				
			||||||
 | 
							types.ERC20MintableBurnableContract.ABI,
 | 
				
			||||||
 | 
							pair.GetAddress(),
 | 
				
			||||||
 | 
							recipient,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().Equal(amount, bal, "balance should increase by unlock amount")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check balance of module account
 | 
				
			||||||
 | 
						bal = suite.GetERC20BalanceOf(
 | 
				
			||||||
 | 
							types.ERC20MintableBurnableContract.ABI,
 | 
				
			||||||
 | 
							pair.GetAddress(),
 | 
				
			||||||
 | 
							moduleAddr,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().Equal(
 | 
				
			||||||
 | 
							// String() due to non-equal struct values for 0
 | 
				
			||||||
 | 
							big.NewInt(0).String(),
 | 
				
			||||||
 | 
							bal.String(),
 | 
				
			||||||
 | 
							"balance should decrease module account by unlock amount",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ConversionTestSuite) TestUnlockERC20Tokens_Insufficient() {
 | 
				
			||||||
 | 
						contractAddr := suite.DeployERC20()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pair := types.NewConversionPair(
 | 
				
			||||||
 | 
							contractAddr,
 | 
				
			||||||
 | 
							"erc20/usdc",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						amount := big.NewInt(100)
 | 
				
			||||||
 | 
						recipient := types.NewInternalEVMAddress(common.BytesToAddress(suite.Key1.PubKey().Address()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Module account has 0 balance, cannot unlock
 | 
				
			||||||
 | 
						err := suite.Keeper.UnlockERC20Tokens(suite.Ctx, pair, amount, recipient)
 | 
				
			||||||
 | 
						suite.Require().Error(err)
 | 
				
			||||||
 | 
						suite.Require().Contains(err.Error(), "execution reverted: ERC20: transfer amount exceeds balance")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ConversionTestSuite) TestConvertCoinToERC20() {
 | 
				
			||||||
 | 
						contractAddr := suite.DeployERC20()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pair := types.NewConversionPair(
 | 
				
			||||||
 | 
							contractAddr,
 | 
				
			||||||
 | 
							"erc20/usdc",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						amount := big.NewInt(100)
 | 
				
			||||||
 | 
						originAcc := sdk.AccAddress(suite.Key1.PubKey().Address().Bytes())
 | 
				
			||||||
 | 
						recipientAcc := types.NewInternalEVMAddress(common.BytesToAddress(suite.Key2.PubKey().Address()))
 | 
				
			||||||
 | 
						moduleAddr := types.NewInternalEVMAddress(types.ModuleEVMAddress)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Starting balance of origin account
 | 
				
			||||||
 | 
						coin, err := suite.Keeper.MintConversionPairCoin(suite.Ctx, pair, amount, originAcc)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						suite.Require().Equal(sdk.NewCoin(pair.Denom, sdk.NewIntFromBigInt(amount)), coin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Mint same initial balance for module account as backing erc20 supply
 | 
				
			||||||
 | 
						err = suite.Keeper.MintERC20(
 | 
				
			||||||
 | 
							suite.Ctx,
 | 
				
			||||||
 | 
							pair.GetAddress(), // contractAddr
 | 
				
			||||||
 | 
							moduleAddr,        //receiver
 | 
				
			||||||
 | 
							amount,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = suite.Keeper.ConvertCoinToERC20(
 | 
				
			||||||
 | 
							suite.Ctx,
 | 
				
			||||||
 | 
							originAcc,
 | 
				
			||||||
 | 
							recipientAcc,
 | 
				
			||||||
 | 
							sdk.NewCoin(pair.Denom, sdk.NewIntFromBigInt(amount)),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Source should decrease
 | 
				
			||||||
 | 
						bal := suite.App.GetBankKeeper().GetBalance(suite.Ctx, originAcc, pair.Denom)
 | 
				
			||||||
 | 
						suite.Require().Equal(sdk.ZeroInt(), bal.Amount, "conversion should decrease source balance")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Module bal should also decrease
 | 
				
			||||||
 | 
						moduleBal := suite.GetERC20BalanceOf(
 | 
				
			||||||
 | 
							types.ERC20MintableBurnableContract.ABI,
 | 
				
			||||||
 | 
							pair.GetAddress(),
 | 
				
			||||||
 | 
							moduleAddr,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().Equal(
 | 
				
			||||||
 | 
							// String() due to non-equal struct values for 0
 | 
				
			||||||
 | 
							big.NewInt(0).String(),
 | 
				
			||||||
 | 
							moduleBal.String(),
 | 
				
			||||||
 | 
							"balance should decrease module account by unlock amount",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Recipient balance should increase by same amount
 | 
				
			||||||
 | 
						recipientBal := suite.GetERC20BalanceOf(
 | 
				
			||||||
 | 
							types.ERC20MintableBurnableContract.ABI,
 | 
				
			||||||
 | 
							pair.GetAddress(),
 | 
				
			||||||
 | 
							recipientAcc,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().Equal(
 | 
				
			||||||
 | 
							// String() due to non-equal struct values for 0
 | 
				
			||||||
 | 
							amount,
 | 
				
			||||||
 | 
							recipientBal,
 | 
				
			||||||
 | 
							"recipient balance should increase",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						suite.EventsContains(suite.GetEvents(),
 | 
				
			||||||
 | 
							sdk.NewEvent(
 | 
				
			||||||
 | 
								types.EventTypeConvertCoinToERC20,
 | 
				
			||||||
 | 
								sdk.NewAttribute(types.AttributeKeyInitiator, originAcc.String()),
 | 
				
			||||||
 | 
								sdk.NewAttribute(types.AttributeKeyReceiver, recipientAcc.String()),
 | 
				
			||||||
 | 
								sdk.NewAttribute(types.AttributeKeyERC20Address, pair.GetAddress().String()),
 | 
				
			||||||
 | 
								sdk.NewAttribute(types.AttributeKeyAmount, coin.String()),
 | 
				
			||||||
 | 
							))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ConversionTestSuite) TestConvertCoinToERC20_InsufficientBalance() {
 | 
				
			||||||
 | 
						contractAddr := suite.DeployERC20()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pair := types.NewConversionPair(
 | 
				
			||||||
 | 
							contractAddr,
 | 
				
			||||||
 | 
							"erc20/usdc",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						amount := big.NewInt(100)
 | 
				
			||||||
 | 
						originAcc := sdk.AccAddress(suite.Key1.PubKey().Address().Bytes())
 | 
				
			||||||
 | 
						recipientAcc := types.NewInternalEVMAddress(common.BytesToAddress(suite.Key2.PubKey().Address()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := suite.Keeper.ConvertCoinToERC20(
 | 
				
			||||||
 | 
							suite.Ctx,
 | 
				
			||||||
 | 
							originAcc,
 | 
				
			||||||
 | 
							recipientAcc,
 | 
				
			||||||
 | 
							sdk.NewCoin(pair.Denom, sdk.NewIntFromBigInt(amount)),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						suite.Require().Error(err)
 | 
				
			||||||
 | 
						suite.Require().Equal("0erc20/usdc is smaller than 100erc20/usdc: insufficient funds", err.Error())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ConversionTestSuite) TestConvertCoinToERC20_NotEnabled() {
 | 
				
			||||||
 | 
						contractAddr := suite.DeployERC20()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pair := types.NewConversionPair(
 | 
				
			||||||
 | 
							contractAddr,
 | 
				
			||||||
 | 
							"erc20/notenabled",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						amount := big.NewInt(100)
 | 
				
			||||||
 | 
						originAcc := sdk.AccAddress(suite.Key1.PubKey().Address().Bytes())
 | 
				
			||||||
 | 
						recipientAcc := types.NewInternalEVMAddress(common.BytesToAddress(suite.Key2.PubKey().Address()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := suite.Keeper.ConvertCoinToERC20(
 | 
				
			||||||
 | 
							suite.Ctx,
 | 
				
			||||||
 | 
							originAcc,
 | 
				
			||||||
 | 
							recipientAcc,
 | 
				
			||||||
 | 
							sdk.NewCoin(pair.Denom, sdk.NewIntFromBigInt(amount)),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						suite.Require().Error(err)
 | 
				
			||||||
 | 
						suite.Require().Equal("erc20/notenabled: ERC20 token not enabled to convert to sdk.Coin", err.Error())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ConversionTestSuite) TestConvertERC20ToCoin() {
 | 
				
			||||||
 | 
						contractAddr := suite.DeployERC20()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pair := types.NewConversionPair(
 | 
				
			||||||
 | 
							contractAddr,
 | 
				
			||||||
 | 
							"erc20/usdc",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						totalAmt := big.NewInt(100)
 | 
				
			||||||
 | 
						userAddr := sdk.AccAddress(suite.Key1.PubKey().Address().Bytes())
 | 
				
			||||||
 | 
						userEvmAddr := types.NewInternalEVMAddress(common.BytesToAddress(suite.Key1.PubKey().Address()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Mint same initial balance for user account
 | 
				
			||||||
 | 
						err := suite.Keeper.MintERC20(
 | 
				
			||||||
 | 
							suite.Ctx,
 | 
				
			||||||
 | 
							pair.GetAddress(), // contractAddr
 | 
				
			||||||
 | 
							userEvmAddr,       //receiver
 | 
				
			||||||
 | 
							totalAmt,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						convertAmt := sdk.NewInt(50)
 | 
				
			||||||
 | 
						err = suite.Keeper.ConvertERC20ToCoin(
 | 
				
			||||||
 | 
							suite.Ctx,
 | 
				
			||||||
 | 
							userEvmAddr,
 | 
				
			||||||
 | 
							userAddr,
 | 
				
			||||||
 | 
							pair.GetAddress(),
 | 
				
			||||||
 | 
							convertAmt,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// bank balance should decrease
 | 
				
			||||||
 | 
						bal := suite.App.GetBankKeeper().GetBalance(suite.Ctx, userAddr, pair.Denom)
 | 
				
			||||||
 | 
						suite.Require().Equal(convertAmt, bal.Amount, "conversion should decrease source balance")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Module bal should also decrease
 | 
				
			||||||
 | 
						userBal := suite.GetERC20BalanceOf(
 | 
				
			||||||
 | 
							types.ERC20MintableBurnableContract.ABI,
 | 
				
			||||||
 | 
							pair.GetAddress(),
 | 
				
			||||||
 | 
							userEvmAddr,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().Equal(
 | 
				
			||||||
 | 
							// String() due to non-equal struct values for 0
 | 
				
			||||||
 | 
							big.NewInt(50).String(),
 | 
				
			||||||
 | 
							userBal.String(),
 | 
				
			||||||
 | 
							"balance should decrease module account by unlock amount",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						suite.EventsContains(suite.GetEvents(),
 | 
				
			||||||
 | 
							sdk.NewEvent(
 | 
				
			||||||
 | 
								types.EventTypeConvertERC20ToCoin,
 | 
				
			||||||
 | 
								sdk.NewAttribute(types.AttributeKeyERC20Address, pair.GetAddress().String()),
 | 
				
			||||||
 | 
								sdk.NewAttribute(types.AttributeKeyInitiator, userEvmAddr.String()),
 | 
				
			||||||
 | 
								sdk.NewAttribute(types.AttributeKeyReceiver, userAddr.String()),
 | 
				
			||||||
 | 
								sdk.NewAttribute(types.AttributeKeyAmount, sdk.NewCoin(pair.Denom, convertAmt).String()),
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ConversionTestSuite) TestConvertERC20ToCoin_EmptyContract() {
 | 
				
			||||||
 | 
						contractAddr := testutil.MustNewInternalEVMAddressFromString("0x15932E26f5BD4923d46a2b205191C4b5d5f43FE3")
 | 
				
			||||||
 | 
						pair := types.NewConversionPair(
 | 
				
			||||||
 | 
							contractAddr,
 | 
				
			||||||
 | 
							"erc20/usdc",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						userAddr := sdk.AccAddress(suite.Key1.PubKey().Address().Bytes())
 | 
				
			||||||
 | 
						userEvmAddr := types.NewInternalEVMAddress(common.BytesToAddress(suite.Key1.PubKey().Address()))
 | 
				
			||||||
 | 
						convertAmt := sdk.NewInt(100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Trying to convert erc20 from an empty contract should fail
 | 
				
			||||||
 | 
						err := suite.Keeper.ConvertERC20ToCoin(
 | 
				
			||||||
 | 
							suite.Ctx,
 | 
				
			||||||
 | 
							userEvmAddr,
 | 
				
			||||||
 | 
							userAddr,
 | 
				
			||||||
 | 
							pair.GetAddress(),
 | 
				
			||||||
 | 
							convertAmt,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().Error(err)
 | 
				
			||||||
 | 
						suite.Require().ErrorContains(err, "contract call failed: method 'balanceOf'")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// bank balance should not change
 | 
				
			||||||
 | 
						bal := suite.App.GetBankKeeper().GetBalance(suite.Ctx, userAddr, pair.Denom)
 | 
				
			||||||
 | 
						suite.Require().Equal(sdk.ZeroInt(), bal.Amount)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										144
									
								
								x/evmutil/keeper/erc20.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								x/evmutil/keeper/erc20.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,144 @@
 | 
				
			|||||||
 | 
					package keeper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/core/vm"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/crypto"
 | 
				
			||||||
 | 
						evmtypes "github.com/tharsis/ethermint/x/evm/types"
 | 
				
			||||||
 | 
						"google.golang.org/grpc/codes"
 | 
				
			||||||
 | 
						"google.golang.org/grpc/status"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						erc20BalanceOfMethod = "balanceOf"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeployTestMintableERC20Contract deploys an ERC20 contract on the EVM as the
 | 
				
			||||||
 | 
					// module account and returns the address of the contract. This contract has
 | 
				
			||||||
 | 
					// minting permissions for the module account.
 | 
				
			||||||
 | 
					// Derived from tharsis/evmos
 | 
				
			||||||
 | 
					// https://github.com/tharsis/evmos/blob/ee54f496551df937915ff6f74a94732a35abc505/x/erc20/keeper/evm.go
 | 
				
			||||||
 | 
					func (k Keeper) DeployTestMintableERC20Contract(
 | 
				
			||||||
 | 
						ctx sdk.Context,
 | 
				
			||||||
 | 
						name string,
 | 
				
			||||||
 | 
						symbol string,
 | 
				
			||||||
 | 
						decimals uint8,
 | 
				
			||||||
 | 
					) (types.InternalEVMAddress, error) {
 | 
				
			||||||
 | 
						ctorArgs, err := types.ERC20MintableBurnableContract.ABI.Pack(
 | 
				
			||||||
 | 
							"", // Empty string for contract constructor
 | 
				
			||||||
 | 
							name,
 | 
				
			||||||
 | 
							symbol,
 | 
				
			||||||
 | 
							decimals,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return types.InternalEVMAddress{}, sdkerrors.Wrapf(err, "token %v is invalid", name)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data := make([]byte, len(types.ERC20MintableBurnableContract.Bin)+len(ctorArgs))
 | 
				
			||||||
 | 
						copy(
 | 
				
			||||||
 | 
							data[:len(types.ERC20MintableBurnableContract.Bin)],
 | 
				
			||||||
 | 
							types.ERC20MintableBurnableContract.Bin,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						copy(
 | 
				
			||||||
 | 
							data[len(types.ERC20MintableBurnableContract.Bin):],
 | 
				
			||||||
 | 
							ctorArgs,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nonce, err := k.accountKeeper.GetSequence(ctx, types.ModuleEVMAddress.Bytes())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return types.InternalEVMAddress{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						contractAddr := crypto.CreateAddress(types.ModuleEVMAddress, nonce)
 | 
				
			||||||
 | 
						_, err = k.CallEVMWithData(ctx, types.ModuleEVMAddress, nil, data)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return types.InternalEVMAddress{}, fmt.Errorf("failed to deploy ERC20 for %s: %w", name, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return types.NewInternalEVMAddress(contractAddr), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MintERC20 mints the given amount of an ERC20 token to an address. This is
 | 
				
			||||||
 | 
					// unchecked and should only be called after permission and enabled ERC20 checks.
 | 
				
			||||||
 | 
					func (k Keeper) MintERC20(
 | 
				
			||||||
 | 
						ctx sdk.Context,
 | 
				
			||||||
 | 
						contractAddr types.InternalEVMAddress,
 | 
				
			||||||
 | 
						receiver types.InternalEVMAddress,
 | 
				
			||||||
 | 
						amount *big.Int,
 | 
				
			||||||
 | 
					) error {
 | 
				
			||||||
 | 
						_, err := k.CallEVM(
 | 
				
			||||||
 | 
							ctx,
 | 
				
			||||||
 | 
							types.ERC20MintableBurnableContract.ABI,
 | 
				
			||||||
 | 
							types.ModuleEVMAddress,
 | 
				
			||||||
 | 
							contractAddr,
 | 
				
			||||||
 | 
							"mint",
 | 
				
			||||||
 | 
							// Mint ERC20 args
 | 
				
			||||||
 | 
							receiver.Address,
 | 
				
			||||||
 | 
							amount,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (k Keeper) QueryERC20BalanceOf(
 | 
				
			||||||
 | 
						ctx sdk.Context,
 | 
				
			||||||
 | 
						contractAddr types.InternalEVMAddress,
 | 
				
			||||||
 | 
						account types.InternalEVMAddress,
 | 
				
			||||||
 | 
					) (*big.Int, error) {
 | 
				
			||||||
 | 
						res, err := k.CallEVM(
 | 
				
			||||||
 | 
							ctx,
 | 
				
			||||||
 | 
							types.ERC20MintableBurnableContract.ABI,
 | 
				
			||||||
 | 
							types.ModuleEVMAddress,
 | 
				
			||||||
 | 
							contractAddr,
 | 
				
			||||||
 | 
							erc20BalanceOfMethod,
 | 
				
			||||||
 | 
							// balanceOf ERC20 args
 | 
				
			||||||
 | 
							account.Address,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if res.Failed() {
 | 
				
			||||||
 | 
							if res.VmError == vm.ErrExecutionReverted.Error() {
 | 
				
			||||||
 | 
								// Unpacks revert
 | 
				
			||||||
 | 
								return nil, evmtypes.NewExecErrorWithReason(res.Ret)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return nil, status.Error(codes.Internal, res.VmError)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						anyOutput, err := types.ERC20MintableBurnableContract.ABI.Unpack(erc20BalanceOfMethod, res.Ret)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf(
 | 
				
			||||||
 | 
								"failed to unpack method %v response: %w",
 | 
				
			||||||
 | 
								erc20BalanceOfMethod,
 | 
				
			||||||
 | 
								err,
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(anyOutput) != 1 {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf(
 | 
				
			||||||
 | 
								"invalid ERC20 %v call return outputs %v, expected %v",
 | 
				
			||||||
 | 
								erc20BalanceOfMethod,
 | 
				
			||||||
 | 
								len(anyOutput),
 | 
				
			||||||
 | 
								1,
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bal, ok := anyOutput[0].(*big.Int)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf(
 | 
				
			||||||
 | 
								"invalid ERC20 return type %T, expected %T",
 | 
				
			||||||
 | 
								anyOutput[0],
 | 
				
			||||||
 | 
								&big.Int{},
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return bal, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										86
									
								
								x/evmutil/keeper/erc20_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								x/evmutil/keeper/erc20_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,86 @@
 | 
				
			|||||||
 | 
					package keeper_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/suite"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/testutil"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ERC20TestSuite struct {
 | 
				
			||||||
 | 
						testutil.Suite
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						contractAddr types.InternalEVMAddress
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestERC20TestSuite(t *testing.T) {
 | 
				
			||||||
 | 
						suite.Run(t, new(ERC20TestSuite))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ERC20TestSuite) SetupTest() {
 | 
				
			||||||
 | 
						suite.Suite.SetupTest()
 | 
				
			||||||
 | 
						suite.contractAddr = suite.DeployERC20()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ERC20TestSuite) TestERC20QueryBalanceOf_Empty() {
 | 
				
			||||||
 | 
						bal, err := suite.Keeper.QueryERC20BalanceOf(
 | 
				
			||||||
 | 
							suite.Ctx,
 | 
				
			||||||
 | 
							suite.contractAddr,
 | 
				
			||||||
 | 
							suite.Key1Addr,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						suite.Require().True(bal.Cmp(big.NewInt(0)) == 0, "balance should be 0")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ERC20TestSuite) TestERC20QueryBalanceOf_NonEmpty() {
 | 
				
			||||||
 | 
						// Mint some tokens for the address
 | 
				
			||||||
 | 
						err := suite.Keeper.MintERC20(
 | 
				
			||||||
 | 
							suite.Ctx,
 | 
				
			||||||
 | 
							suite.contractAddr,
 | 
				
			||||||
 | 
							suite.Key1Addr,
 | 
				
			||||||
 | 
							big.NewInt(10),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bal, err := suite.Keeper.QueryERC20BalanceOf(
 | 
				
			||||||
 | 
							suite.Ctx,
 | 
				
			||||||
 | 
							suite.contractAddr,
 | 
				
			||||||
 | 
							suite.Key1Addr,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						suite.Require().Equal(big.NewInt(10), bal, "balance should be 10")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ERC20TestSuite) TestERC20Mint() {
 | 
				
			||||||
 | 
						contractAddr := suite.DeployERC20()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We can't test mint by module account like the Unauthorized test as we
 | 
				
			||||||
 | 
						// cannot sign as the module account. Instead, we test the keeper method for
 | 
				
			||||||
 | 
						// minting.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						receiver := common.BytesToAddress(suite.Key2.PubKey().Address())
 | 
				
			||||||
 | 
						amount := big.NewInt(1234)
 | 
				
			||||||
 | 
						err := suite.App.GetEvmutilKeeper().MintERC20(suite.Ctx, contractAddr, types.NewInternalEVMAddress(receiver), amount)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Query ERC20.balanceOf()
 | 
				
			||||||
 | 
						addr := common.BytesToAddress(suite.Key1.PubKey().Address())
 | 
				
			||||||
 | 
						res, err := suite.QueryContract(
 | 
				
			||||||
 | 
							types.ERC20MintableBurnableContract.ABI,
 | 
				
			||||||
 | 
							addr,
 | 
				
			||||||
 | 
							suite.Key1,
 | 
				
			||||||
 | 
							contractAddr,
 | 
				
			||||||
 | 
							"balanceOf",
 | 
				
			||||||
 | 
							receiver,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						suite.Require().Len(res, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						balance, ok := res[0].(*big.Int)
 | 
				
			||||||
 | 
						suite.Require().True(ok, "balanceOf should respond with *big.Int")
 | 
				
			||||||
 | 
						suite.Require().Equal(big.NewInt(1234), balance)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										152
									
								
								x/evmutil/keeper/evm.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								x/evmutil/keeper/evm.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,152 @@
 | 
				
			|||||||
 | 
					// Derived from https://github.com/tharsis/evmos/blob/0bfaf0db7be47153bc651e663176ba8deca960b5/x/erc20/keeper/evm.go
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//      http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package keeper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/accounts/abi"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common/hexutil"
 | 
				
			||||||
 | 
						ethtypes "github.com/ethereum/go-ethereum/core/types"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/crypto"
 | 
				
			||||||
 | 
						"github.com/tharsis/ethermint/server/config"
 | 
				
			||||||
 | 
						evmtypes "github.com/tharsis/ethermint/x/evm/types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CallEVM performs a smart contract method call using given args
 | 
				
			||||||
 | 
					func (k Keeper) CallEVM(
 | 
				
			||||||
 | 
						ctx sdk.Context,
 | 
				
			||||||
 | 
						abi abi.ABI,
 | 
				
			||||||
 | 
						from common.Address,
 | 
				
			||||||
 | 
						contract types.InternalEVMAddress,
 | 
				
			||||||
 | 
						method string,
 | 
				
			||||||
 | 
						args ...interface{},
 | 
				
			||||||
 | 
					) (*evmtypes.MsgEthereumTxResponse, error) {
 | 
				
			||||||
 | 
						data, err := abi.Pack(method, args...)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, sdkerrors.Wrap(
 | 
				
			||||||
 | 
								types.ErrABIPack,
 | 
				
			||||||
 | 
								sdkerrors.Wrap(err, "failed to create transaction data").Error(),
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp, err := k.CallEVMWithData(ctx, from, &contract, data)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, sdkerrors.Wrapf(err, "contract call failed: method '%s', contract '%s'", method, contract)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return resp, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CallEVMWithData performs a smart contract method call using contract data
 | 
				
			||||||
 | 
					// Derived from tharsis/evmos
 | 
				
			||||||
 | 
					// https://github.com/tharsis/evmos/blob/ee54f496551df937915ff6f74a94732a35abc505/x/erc20/keeper/evm.go
 | 
				
			||||||
 | 
					func (k Keeper) CallEVMWithData(
 | 
				
			||||||
 | 
						ctx sdk.Context,
 | 
				
			||||||
 | 
						from common.Address,
 | 
				
			||||||
 | 
						contract *types.InternalEVMAddress,
 | 
				
			||||||
 | 
						data []byte,
 | 
				
			||||||
 | 
					) (*evmtypes.MsgEthereumTxResponse, error) {
 | 
				
			||||||
 | 
						nonce, err := k.accountKeeper.GetSequence(ctx, from.Bytes())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// To param needs to be nil to correctly apply txs to create contracts
 | 
				
			||||||
 | 
						// Default common.Address value is 0x0000000000000000000000000000000000000000, not nil
 | 
				
			||||||
 | 
						// which Ethermint handles differently -- erc20_test will fail
 | 
				
			||||||
 | 
						// https://github.com/tharsis/ethermint/blob/caa1c5a6c6b7ed8ba4aaf6e0b0848f6be5ba6668/x/evm/keeper/state_transition.go#L357
 | 
				
			||||||
 | 
						var to *common.Address
 | 
				
			||||||
 | 
						if contract != nil {
 | 
				
			||||||
 | 
							to = &contract.Address
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						transactionArgs := evmtypes.TransactionArgs{
 | 
				
			||||||
 | 
							From: &from,
 | 
				
			||||||
 | 
							To:   to,
 | 
				
			||||||
 | 
							Data: (*hexutil.Bytes)(&data),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						args, err := json.Marshal(transactionArgs)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// EstimateGas applies the transaction against current block state to get
 | 
				
			||||||
 | 
						// optimal gas value. Since this is done right before the ApplyMessage
 | 
				
			||||||
 | 
						// below, it should essentially do the same thing but without affecting
 | 
				
			||||||
 | 
						// state. While this is an *estimate* in regular use, this should be an
 | 
				
			||||||
 | 
						// accurate exact amount in this case, as both the chain state and tx used
 | 
				
			||||||
 | 
						// to estimate and apply are the exact same (ie. no txs between estimate and
 | 
				
			||||||
 | 
						// apply, tx order is the same, etc.)
 | 
				
			||||||
 | 
						gasRes, err := k.evmKeeper.EstimateGas(sdk.WrapSDKContext(ctx), &evmtypes.EthCallRequest{
 | 
				
			||||||
 | 
							Args:   args,
 | 
				
			||||||
 | 
							GasCap: config.DefaultGasCap,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, sdkerrors.Wrap(evmtypes.ErrVMExecution, err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msg := ethtypes.NewMessage(
 | 
				
			||||||
 | 
							from,
 | 
				
			||||||
 | 
							to,
 | 
				
			||||||
 | 
							nonce,
 | 
				
			||||||
 | 
							big.NewInt(0), // amount
 | 
				
			||||||
 | 
							gasRes.Gas,    // gasLimit
 | 
				
			||||||
 | 
							big.NewInt(0), // gasFeeCap
 | 
				
			||||||
 | 
							big.NewInt(0), // gasTipCap
 | 
				
			||||||
 | 
							big.NewInt(0), // gasPrice
 | 
				
			||||||
 | 
							data,
 | 
				
			||||||
 | 
							ethtypes.AccessList{}, // AccessList
 | 
				
			||||||
 | 
							true,                  // checkNonce
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						res, err := k.evmKeeper.ApplyMessage(ctx, msg, evmtypes.NewNoOpTracer(), true)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if res.Failed() {
 | 
				
			||||||
 | 
							return nil, sdkerrors.Wrap(evmtypes.ErrVMExecution, res.VmError)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return res, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// monitorApprovalEvent returns an error if the given transactions logs include
 | 
				
			||||||
 | 
					// an unexpected `Approval` event
 | 
				
			||||||
 | 
					func (k Keeper) monitorApprovalEvent(res *evmtypes.MsgEthereumTxResponse) error {
 | 
				
			||||||
 | 
						if res == nil || len(res.Logs) == 0 {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						logApprovalSig := []byte("Approval(address,address,uint256)")
 | 
				
			||||||
 | 
						logApprovalSigHash := crypto.Keccak256Hash(logApprovalSig)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, log := range res.Logs {
 | 
				
			||||||
 | 
							if log.Topics[0] == logApprovalSigHash.Hex() {
 | 
				
			||||||
 | 
								return sdkerrors.Wrapf(
 | 
				
			||||||
 | 
									types.ErrUnexpectedContractEvent, "unexpected contract Approval event",
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										35
									
								
								x/evmutil/keeper/grpc_query.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								x/evmutil/keeper/grpc_query.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					package keeper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"google.golang.org/grpc/codes"
 | 
				
			||||||
 | 
						"google.golang.org/grpc/status"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type queryServer struct {
 | 
				
			||||||
 | 
						keeper Keeper
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewQueryServerImpl creates a new server for handling gRPC queries.
 | 
				
			||||||
 | 
					func NewQueryServerImpl(k Keeper) types.QueryServer {
 | 
				
			||||||
 | 
						return &queryServer{keeper: k}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ types.QueryServer = queryServer{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Params queries module params
 | 
				
			||||||
 | 
					func (s queryServer) Params(stdCtx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
 | 
				
			||||||
 | 
						if req == nil {
 | 
				
			||||||
 | 
							return nil, status.Errorf(codes.InvalidArgument, "empty request")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx := sdk.UnwrapSDKContext(stdCtx)
 | 
				
			||||||
 | 
						params := s.keeper.GetParams(ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &types.QueryParamsResponse{Params: params}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										37
									
								
								x/evmutil/keeper/grpc_query_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								x/evmutil/keeper/grpc_query_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					package keeper_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/suite"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/keeper"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/testutil"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type GrpcQueryTestSuite struct {
 | 
				
			||||||
 | 
						testutil.Suite
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msgServer types.MsgServer
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *GrpcQueryTestSuite) SetupTest() {
 | 
				
			||||||
 | 
						suite.Suite.SetupTest()
 | 
				
			||||||
 | 
						suite.msgServer = keeper.NewMsgServerImpl(suite.App.GetEvmutilKeeper())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestGrpcQueryTestSuite(t *testing.T) {
 | 
				
			||||||
 | 
						suite.Run(t, new(GrpcQueryTestSuite))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *GrpcQueryTestSuite) TestQueryParams() {
 | 
				
			||||||
 | 
						params, err := suite.QueryClient.Params(
 | 
				
			||||||
 | 
							context.Background(),
 | 
				
			||||||
 | 
							&types.QueryParamsRequest{},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						suite.Require().Len(params.Params.EnabledConversionPairs, 1)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -11,6 +11,8 @@ import (
 | 
				
			|||||||
func RegisterInvariants(ir sdk.InvariantRegistry, bankK types.BankKeeper, k Keeper) {
 | 
					func RegisterInvariants(ir sdk.InvariantRegistry, bankK types.BankKeeper, k Keeper) {
 | 
				
			||||||
	ir.RegisterRoute(types.ModuleName, "fully-backed", FullyBackedInvariant(bankK, k))
 | 
						ir.RegisterRoute(types.ModuleName, "fully-backed", FullyBackedInvariant(bankK, k))
 | 
				
			||||||
	ir.RegisterRoute(types.ModuleName, "small-balances", SmallBalancesInvariant(bankK, k))
 | 
						ir.RegisterRoute(types.ModuleName, "small-balances", SmallBalancesInvariant(bankK, k))
 | 
				
			||||||
 | 
						// Disable this invariant due to some issues with it requiring some staking params to be set in genesis.
 | 
				
			||||||
 | 
						// ir.RegisterRoute(types.ModuleName, "backed-conversion-coins", BackedCoinsInvariant(bankK, k))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AllInvariants runs all invariants of the swap module
 | 
					// AllInvariants runs all invariants of the swap module
 | 
				
			||||||
@ -19,8 +21,10 @@ func AllInvariants(bankK types.BankKeeper, k Keeper) sdk.Invariant {
 | 
				
			|||||||
		if res, stop := FullyBackedInvariant(bankK, k)(ctx); stop {
 | 
							if res, stop := FullyBackedInvariant(bankK, k)(ctx); stop {
 | 
				
			||||||
			return res, stop
 | 
								return res, stop
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		res, stop := SmallBalancesInvariant(bankK, k)(ctx)
 | 
							if res, stop := BackedCoinsInvariant(bankK, k)(ctx); stop {
 | 
				
			||||||
		return res, stop
 | 
								return res, stop
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return SmallBalancesInvariant(bankK, k)(ctx)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -64,3 +68,40 @@ func SmallBalancesInvariant(_ types.BankKeeper, k Keeper) sdk.Invariant {
 | 
				
			|||||||
		return message, broken
 | 
							return message, broken
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// BackedCoinsInvariant iterates all conversion pairs and asserts that the
 | 
				
			||||||
 | 
					// sdk.Coin balances are less than the module ERC20 balance.
 | 
				
			||||||
 | 
					// **Note:** This compares <= and not == as anyone can send tokens to the
 | 
				
			||||||
 | 
					// ERC20 contract address and break the invariant if a strict equal check.
 | 
				
			||||||
 | 
					func BackedCoinsInvariant(_ types.BankKeeper, k Keeper) sdk.Invariant {
 | 
				
			||||||
 | 
						broken := false
 | 
				
			||||||
 | 
						message := sdk.FormatInvariant(
 | 
				
			||||||
 | 
							types.ModuleName,
 | 
				
			||||||
 | 
							"backed coins broken",
 | 
				
			||||||
 | 
							"coin supply is greater than module account ERC20 tokens",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return func(ctx sdk.Context) (string, bool) {
 | 
				
			||||||
 | 
							params := k.GetParams(ctx)
 | 
				
			||||||
 | 
							for _, pair := range params.EnabledConversionPairs {
 | 
				
			||||||
 | 
								erc20Balance, err := k.QueryERC20BalanceOf(
 | 
				
			||||||
 | 
									ctx,
 | 
				
			||||||
 | 
									pair.GetAddress(),
 | 
				
			||||||
 | 
									types.NewInternalEVMAddress(types.ModuleEVMAddress),
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									panic(err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								supply := k.bankKeeper.GetSupply(ctx, pair.Denom)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Must be true: sdk.Coin supply < ERC20 balanceOf(module account)
 | 
				
			||||||
 | 
								if supply.Amount.BigInt().Cmp(erc20Balance) > 0 {
 | 
				
			||||||
 | 
									broken = true
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return message, broken
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
package keeper_test
 | 
					package keeper_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
@ -14,7 +15,8 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type invariantTestSuite struct {
 | 
					type invariantTestSuite struct {
 | 
				
			||||||
	testutil.Suite
 | 
						testutil.Suite
 | 
				
			||||||
	invariants map[string]map[string]sdk.Invariant
 | 
						invariants   map[string]map[string]sdk.Invariant
 | 
				
			||||||
 | 
						contractAddr types.InternalEVMAddress
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestInvariantTestSuite(t *testing.T) {
 | 
					func TestInvariantTestSuite(t *testing.T) {
 | 
				
			||||||
@ -23,6 +25,9 @@ func TestInvariantTestSuite(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (suite *invariantTestSuite) SetupTest() {
 | 
					func (suite *invariantTestSuite) SetupTest() {
 | 
				
			||||||
	suite.Suite.SetupTest()
 | 
						suite.Suite.SetupTest()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						suite.contractAddr = suite.DeployERC20()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	suite.invariants = make(map[string]map[string]sdk.Invariant)
 | 
						suite.invariants = make(map[string]map[string]sdk.Invariant)
 | 
				
			||||||
	keeper.RegisterInvariants(suite, suite.BankKeeper, suite.Keeper)
 | 
						keeper.RegisterInvariants(suite, suite.BankKeeper, suite.Keeper)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -40,6 +45,23 @@ func (suite *invariantTestSuite) SetupValidState() {
 | 
				
			|||||||
			sdk.NewCoin("ukava", sdk.NewInt(2)), // ( sum of all minor balances ) / conversion multiplier
 | 
								sdk.NewCoin("ukava", sdk.NewInt(2)), // ( sum of all minor balances ) / conversion multiplier
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := suite.Keeper.MintERC20(suite.Ctx, suite.contractAddr, suite.Key1Addr, big.NewInt(1000000))
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// key1 ERC20 bal -10000, sdk.Coin +1000
 | 
				
			||||||
 | 
						// Module account balance 0 -> 1000
 | 
				
			||||||
 | 
						_, err = suite.Keeper.CallEVM(
 | 
				
			||||||
 | 
							suite.Ctx,
 | 
				
			||||||
 | 
							types.ERC20MintableBurnableContract.ABI,
 | 
				
			||||||
 | 
							suite.Key1Addr.Address,
 | 
				
			||||||
 | 
							suite.contractAddr,
 | 
				
			||||||
 | 
							"convertToCoin",
 | 
				
			||||||
 | 
							// convertToCoin ERC20 args
 | 
				
			||||||
 | 
							suite.Key1Addr.Address,
 | 
				
			||||||
 | 
							big.NewInt(1000),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RegisterRoutes implements sdk.InvariantRegistry
 | 
					// RegisterRoutes implements sdk.InvariantRegistry
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,7 @@ import (
 | 
				
			|||||||
	"github.com/cosmos/cosmos-sdk/codec"
 | 
						"github.com/cosmos/cosmos-sdk/codec"
 | 
				
			||||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
 | 
						sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
 | 
				
			||||||
 | 
						paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/kava-labs/kava/x/evmutil/types"
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@ -13,16 +14,37 @@ import (
 | 
				
			|||||||
// Keeper of the evmutil store.
 | 
					// Keeper of the evmutil store.
 | 
				
			||||||
// This keeper stores additional data related to evm accounts.
 | 
					// This keeper stores additional data related to evm accounts.
 | 
				
			||||||
type Keeper struct {
 | 
					type Keeper struct {
 | 
				
			||||||
	cdc      codec.Codec
 | 
						cdc           codec.Codec
 | 
				
			||||||
	storeKey sdk.StoreKey
 | 
						storeKey      sdk.StoreKey
 | 
				
			||||||
 | 
						paramSubspace paramtypes.Subspace
 | 
				
			||||||
 | 
						bankKeeper    types.BankKeeper
 | 
				
			||||||
 | 
						evmKeeper     types.EvmKeeper
 | 
				
			||||||
 | 
						accountKeeper types.AccountKeeper
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewKeeper creates an evmutil keeper.
 | 
					// NewKeeper creates an evmutil keeper.
 | 
				
			||||||
func NewKeeper(cdc codec.Codec, storeKey sdk.StoreKey) Keeper {
 | 
					func NewKeeper(
 | 
				
			||||||
	return Keeper{
 | 
						cdc codec.Codec,
 | 
				
			||||||
		cdc:      cdc,
 | 
						storeKey sdk.StoreKey,
 | 
				
			||||||
		storeKey: storeKey,
 | 
						params paramtypes.Subspace,
 | 
				
			||||||
 | 
						bk types.BankKeeper,
 | 
				
			||||||
 | 
						ak types.AccountKeeper,
 | 
				
			||||||
 | 
					) Keeper {
 | 
				
			||||||
 | 
						if !params.HasKeyTable() {
 | 
				
			||||||
 | 
							params = params.WithKeyTable(types.ParamKeyTable())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return Keeper{
 | 
				
			||||||
 | 
							cdc:           cdc,
 | 
				
			||||||
 | 
							storeKey:      storeKey,
 | 
				
			||||||
 | 
							paramSubspace: params,
 | 
				
			||||||
 | 
							bankKeeper:    bk,
 | 
				
			||||||
 | 
							accountKeeper: ak,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (k *Keeper) SetEvmKeeper(evmKeeper types.EvmKeeper) {
 | 
				
			||||||
 | 
						k.evmKeeper = evmKeeper
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetAllAccounts returns all accounts.
 | 
					// GetAllAccounts returns all accounts.
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										104
									
								
								x/evmutil/keeper/msg_server.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								x/evmutil/keeper/msg_server.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,104 @@
 | 
				
			|||||||
 | 
					package keeper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type msgServer struct {
 | 
				
			||||||
 | 
						keeper Keeper
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewMsgServerImpl returns an implementation of the evmutil MsgServer interface
 | 
				
			||||||
 | 
					// for the provided Keeper.
 | 
				
			||||||
 | 
					func NewMsgServerImpl(keeper Keeper) types.MsgServer {
 | 
				
			||||||
 | 
						return &msgServer{keeper: keeper}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ types.MsgServer = msgServer{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ConvertCoinToERC20 handles a MsgConvertCoinToERC20 message to convert
 | 
				
			||||||
 | 
					// sdk.Coin to Kava EVM tokens.
 | 
				
			||||||
 | 
					func (s msgServer) ConvertCoinToERC20(
 | 
				
			||||||
 | 
						goCtx context.Context,
 | 
				
			||||||
 | 
						msg *types.MsgConvertCoinToERC20,
 | 
				
			||||||
 | 
					) (*types.MsgConvertCoinToERC20Response, error) {
 | 
				
			||||||
 | 
						ctx := sdk.UnwrapSDKContext(goCtx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						initiator, err := sdk.AccAddressFromBech32(msg.Initiator)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("invalid Initiator address: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						receiver, err := types.NewInternalEVMAddressFromString(msg.Receiver)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("invalid Receiver address: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := s.keeper.ConvertCoinToERC20(
 | 
				
			||||||
 | 
							ctx,
 | 
				
			||||||
 | 
							initiator,
 | 
				
			||||||
 | 
							receiver,
 | 
				
			||||||
 | 
							*msg.Amount,
 | 
				
			||||||
 | 
						); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.EventManager().EmitEvent(
 | 
				
			||||||
 | 
							sdk.NewEvent(
 | 
				
			||||||
 | 
								sdk.EventTypeMessage,
 | 
				
			||||||
 | 
								sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
 | 
				
			||||||
 | 
								sdk.NewAttribute(sdk.AttributeKeySender, msg.Initiator),
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &types.MsgConvertCoinToERC20Response{}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ConvertERC20ToCoin handles a MsgConvertERC20ToCoin message to convert
 | 
				
			||||||
 | 
					// sdk.Coin to Kava EVM tokens.
 | 
				
			||||||
 | 
					func (s msgServer) ConvertERC20ToCoin(
 | 
				
			||||||
 | 
						goCtx context.Context,
 | 
				
			||||||
 | 
						msg *types.MsgConvertERC20ToCoin,
 | 
				
			||||||
 | 
					) (*types.MsgConvertERC20ToCoinResponse, error) {
 | 
				
			||||||
 | 
						ctx := sdk.UnwrapSDKContext(goCtx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						initiator, err := types.NewInternalEVMAddressFromString(msg.Initiator)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("invalid initiator address: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						receiver, err := sdk.AccAddressFromBech32(msg.Receiver)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("invalid receiver address: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						contractAddr, err := types.NewInternalEVMAddressFromString(msg.KavaERC20Address)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("invalid contract address: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := s.keeper.ConvertERC20ToCoin(
 | 
				
			||||||
 | 
							ctx,
 | 
				
			||||||
 | 
							initiator,
 | 
				
			||||||
 | 
							receiver,
 | 
				
			||||||
 | 
							contractAddr,
 | 
				
			||||||
 | 
							msg.Amount,
 | 
				
			||||||
 | 
						); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.EventManager().EmitEvent(
 | 
				
			||||||
 | 
							sdk.NewEvent(
 | 
				
			||||||
 | 
								sdk.EventTypeMessage,
 | 
				
			||||||
 | 
								sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
 | 
				
			||||||
 | 
								sdk.NewAttribute(sdk.AttributeKeySender, msg.Initiator),
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &types.MsgConvertERC20ToCoinResponse{}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										266
									
								
								x/evmutil/keeper/msg_server_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										266
									
								
								x/evmutil/keeper/msg_server_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,266 @@
 | 
				
			|||||||
 | 
					package keeper_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common/math"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/keeper"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/testutil"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/suite"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type MsgServerSuite struct {
 | 
				
			||||||
 | 
						testutil.Suite
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msgServer types.MsgServer
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *MsgServerSuite) SetupTest() {
 | 
				
			||||||
 | 
						suite.Suite.SetupTest()
 | 
				
			||||||
 | 
						suite.msgServer = keeper.NewMsgServerImpl(suite.App.GetEvmutilKeeper())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestMsgServerSuite(t *testing.T) {
 | 
				
			||||||
 | 
						suite.Run(t, new(MsgServerSuite))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *MsgServerSuite) TestConvertCoinToERC20() {
 | 
				
			||||||
 | 
						invoker, err := sdk.AccAddressFromBech32("kava123fxg0l602etulhhcdm0vt7l57qya5wjcrwhzz")
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = suite.App.FundAccount(suite.Ctx, invoker, sdk.NewCoins(sdk.NewCoin("erc20/usdc", sdk.NewInt(10000))))
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						contractAddr := suite.DeployERC20()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pair := types.NewConversionPair(
 | 
				
			||||||
 | 
							contractAddr,
 | 
				
			||||||
 | 
							"erc20/usdc",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Module account should have starting balance
 | 
				
			||||||
 | 
						pairStartingBal := big.NewInt(10000)
 | 
				
			||||||
 | 
						err = suite.Keeper.MintERC20(
 | 
				
			||||||
 | 
							suite.Ctx,
 | 
				
			||||||
 | 
							pair.GetAddress(), // contractAddr
 | 
				
			||||||
 | 
							types.NewInternalEVMAddress(types.ModuleEVMAddress), //receiver
 | 
				
			||||||
 | 
							pairStartingBal,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						type errArgs struct {
 | 
				
			||||||
 | 
							expectPass bool
 | 
				
			||||||
 | 
							contains   string
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							name    string
 | 
				
			||||||
 | 
							msg     types.MsgConvertCoinToERC20
 | 
				
			||||||
 | 
							errArgs errArgs
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"valid",
 | 
				
			||||||
 | 
								types.NewMsgConvertCoinToERC20(
 | 
				
			||||||
 | 
									invoker.String(),
 | 
				
			||||||
 | 
									"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
 | 
				
			||||||
 | 
									sdk.NewCoin("erc20/usdc", sdk.NewInt(1234)),
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - odd length hex address",
 | 
				
			||||||
 | 
								types.NewMsgConvertCoinToERC20(
 | 
				
			||||||
 | 
									invoker.String(),
 | 
				
			||||||
 | 
									"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc",
 | 
				
			||||||
 | 
									sdk.NewCoin("erc20/usdc", sdk.NewInt(1234)),
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "invalid Receiver address: string is not a hex address",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							// Amount coin is not validated by msg_server, but on msg itself
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range tests {
 | 
				
			||||||
 | 
							suite.Run(tc.name, func() {
 | 
				
			||||||
 | 
								_, err := suite.msgServer.ConvertCoinToERC20(sdk.WrapSDKContext(suite.Ctx), &tc.msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if tc.errArgs.expectPass {
 | 
				
			||||||
 | 
									suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									bal := suite.GetERC20BalanceOf(
 | 
				
			||||||
 | 
										types.ERC20MintableBurnableContract.ABI,
 | 
				
			||||||
 | 
										pair.GetAddress(),
 | 
				
			||||||
 | 
										testutil.MustNewInternalEVMAddressFromString(tc.msg.Receiver),
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									suite.Require().Equal(tc.msg.Amount.Amount.BigInt(), bal, "balance should match converted amount")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// msg server event
 | 
				
			||||||
 | 
									suite.EventsContains(suite.GetEvents(),
 | 
				
			||||||
 | 
										sdk.NewEvent(
 | 
				
			||||||
 | 
											sdk.EventTypeMessage,
 | 
				
			||||||
 | 
											sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
 | 
				
			||||||
 | 
											sdk.NewAttribute(sdk.AttributeKeySender, tc.msg.Initiator),
 | 
				
			||||||
 | 
										))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// keeper event
 | 
				
			||||||
 | 
									suite.EventsContains(suite.GetEvents(),
 | 
				
			||||||
 | 
										sdk.NewEvent(
 | 
				
			||||||
 | 
											types.EventTypeConvertCoinToERC20,
 | 
				
			||||||
 | 
											sdk.NewAttribute(types.AttributeKeyInitiator, tc.msg.Initiator),
 | 
				
			||||||
 | 
											sdk.NewAttribute(types.AttributeKeyReceiver, tc.msg.Receiver),
 | 
				
			||||||
 | 
											sdk.NewAttribute(types.AttributeKeyERC20Address, pair.GetAddress().String()),
 | 
				
			||||||
 | 
											sdk.NewAttribute(types.AttributeKeyAmount, tc.msg.Amount.String()),
 | 
				
			||||||
 | 
										))
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									suite.Require().Error(err)
 | 
				
			||||||
 | 
									suite.Require().Contains(err.Error(), tc.errArgs.contains)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *MsgServerSuite) TestConvertERC20ToCoin() {
 | 
				
			||||||
 | 
						contractAddr := suite.DeployERC20()
 | 
				
			||||||
 | 
						pair := types.NewConversionPair(
 | 
				
			||||||
 | 
							contractAddr,
 | 
				
			||||||
 | 
							"erc20/usdc",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// give invoker account some erc20 usdc to begin with
 | 
				
			||||||
 | 
						invoker := testutil.MustNewInternalEVMAddressFromString("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")
 | 
				
			||||||
 | 
						pairStartingBal := big.NewInt(10_000_000)
 | 
				
			||||||
 | 
						err := suite.Keeper.MintERC20(
 | 
				
			||||||
 | 
							suite.Ctx,
 | 
				
			||||||
 | 
							pair.GetAddress(), // contractAddr
 | 
				
			||||||
 | 
							invoker,           //receiver
 | 
				
			||||||
 | 
							pairStartingBal,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						invokerCosmosAddr, err := sdk.AccAddressFromHex(invoker.String()[2:])
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// create user account, otherwise `CallEVMWithData` will fail due to failing to get user account when finding its sequence.
 | 
				
			||||||
 | 
						err = suite.App.FundAccount(suite.Ctx, invokerCosmosAddr, sdk.NewCoins(sdk.NewCoin(pair.Denom, sdk.ZeroInt())))
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						type errArgs struct {
 | 
				
			||||||
 | 
							expectPass bool
 | 
				
			||||||
 | 
							contains   string
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							name           string
 | 
				
			||||||
 | 
							msg            types.MsgConvertERC20ToCoin
 | 
				
			||||||
 | 
							approvalAmount *big.Int
 | 
				
			||||||
 | 
							errArgs        errArgs
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"valid",
 | 
				
			||||||
 | 
								types.NewMsgConvertERC20ToCoin(
 | 
				
			||||||
 | 
									invoker,
 | 
				
			||||||
 | 
									invokerCosmosAddr,
 | 
				
			||||||
 | 
									contractAddr,
 | 
				
			||||||
 | 
									sdk.NewInt(10_000),
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								math.MaxBig256,
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - invalid hex address",
 | 
				
			||||||
 | 
								types.MsgConvertERC20ToCoin{
 | 
				
			||||||
 | 
									Initiator:        "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc",
 | 
				
			||||||
 | 
									Receiver:         invokerCosmosAddr.String(),
 | 
				
			||||||
 | 
									KavaERC20Address: contractAddr.String(),
 | 
				
			||||||
 | 
									Amount:           sdk.NewInt(10_000),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								math.MaxBig256,
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "invalid initiator address: string is not a hex address",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - insufficient coins",
 | 
				
			||||||
 | 
								types.NewMsgConvertERC20ToCoin(
 | 
				
			||||||
 | 
									invoker,
 | 
				
			||||||
 | 
									invokerCosmosAddr,
 | 
				
			||||||
 | 
									contractAddr,
 | 
				
			||||||
 | 
									sdk.NewIntFromBigInt(pairStartingBal).Add(sdk.OneInt()),
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								math.MaxBig256,
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "transfer amount exceeds balance",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - contract address",
 | 
				
			||||||
 | 
								types.NewMsgConvertERC20ToCoin(
 | 
				
			||||||
 | 
									invoker,
 | 
				
			||||||
 | 
									invokerCosmosAddr,
 | 
				
			||||||
 | 
									testutil.MustNewInternalEVMAddressFromString("0x7Bbf300890857b8c241b219C6a489431669b3aFA"),
 | 
				
			||||||
 | 
									sdk.NewInt(10_000),
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								math.MaxBig256,
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "ERC20 token not enabled to convert to sdk.Coin",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range tests {
 | 
				
			||||||
 | 
							suite.Run(tc.name, func() {
 | 
				
			||||||
 | 
								_, err := suite.msgServer.ConvertERC20ToCoin(sdk.WrapSDKContext(suite.Ctx), &tc.msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if tc.errArgs.expectPass {
 | 
				
			||||||
 | 
									suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// validate user balance after conversion
 | 
				
			||||||
 | 
									bal := suite.GetERC20BalanceOf(
 | 
				
			||||||
 | 
										types.ERC20MintableBurnableContract.ABI,
 | 
				
			||||||
 | 
										pair.GetAddress(),
 | 
				
			||||||
 | 
										testutil.MustNewInternalEVMAddressFromString(tc.msg.Initiator),
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
									expectedBal := sdk.NewIntFromBigInt(pairStartingBal).Sub(tc.msg.Amount)
 | 
				
			||||||
 | 
									suite.Require().Equal(expectedBal.BigInt(), bal, "user erc20 balance is invalid")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// validate user coin balance
 | 
				
			||||||
 | 
									coinBal := suite.App.GetBankKeeper().GetBalance(suite.Ctx, invokerCosmosAddr, pair.Denom)
 | 
				
			||||||
 | 
									suite.Require().Equal(tc.msg.Amount, coinBal.Amount, "user coin balance is invalid")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// msg server event
 | 
				
			||||||
 | 
									suite.EventsContains(suite.GetEvents(),
 | 
				
			||||||
 | 
										sdk.NewEvent(
 | 
				
			||||||
 | 
											sdk.EventTypeMessage,
 | 
				
			||||||
 | 
											sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
 | 
				
			||||||
 | 
											sdk.NewAttribute(sdk.AttributeKeySender, tc.msg.Initiator),
 | 
				
			||||||
 | 
										))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// keeper event
 | 
				
			||||||
 | 
									suite.EventsContains(suite.GetEvents(),
 | 
				
			||||||
 | 
										sdk.NewEvent(
 | 
				
			||||||
 | 
											types.EventTypeConvertERC20ToCoin,
 | 
				
			||||||
 | 
											sdk.NewAttribute(types.AttributeKeyERC20Address, pair.GetAddress().String()),
 | 
				
			||||||
 | 
											sdk.NewAttribute(types.AttributeKeyInitiator, tc.msg.Initiator),
 | 
				
			||||||
 | 
											sdk.NewAttribute(types.AttributeKeyReceiver, tc.msg.Receiver),
 | 
				
			||||||
 | 
											sdk.NewAttribute(types.AttributeKeyAmount, sdk.NewCoin(pair.Denom, tc.msg.Amount).String()),
 | 
				
			||||||
 | 
										))
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									suite.Require().Error(err)
 | 
				
			||||||
 | 
									suite.Require().Contains(err.Error(), tc.errArgs.contains)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										51
									
								
								x/evmutil/keeper/params.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								x/evmutil/keeper/params.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					package keeper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetParams returns the total set of evm parameters.
 | 
				
			||||||
 | 
					func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
 | 
				
			||||||
 | 
						k.paramSubspace.GetParamSet(ctx, ¶ms)
 | 
				
			||||||
 | 
						return params
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SetParams sets the evm parameters to the param space.
 | 
				
			||||||
 | 
					func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
 | 
				
			||||||
 | 
						k.paramSubspace.SetParamSet(ctx, ¶ms)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetEnabledConversionPairFromERC20Address returns an ConversionPair from the internal contract address.
 | 
				
			||||||
 | 
					func (k Keeper) GetEnabledConversionPairFromERC20Address(
 | 
				
			||||||
 | 
						ctx sdk.Context,
 | 
				
			||||||
 | 
						address types.InternalEVMAddress,
 | 
				
			||||||
 | 
					) (types.ConversionPair, error) {
 | 
				
			||||||
 | 
						params := k.GetParams(ctx)
 | 
				
			||||||
 | 
						for _, pair := range params.EnabledConversionPairs {
 | 
				
			||||||
 | 
							if bytes.Equal(pair.KavaERC20Address, address.Bytes()) {
 | 
				
			||||||
 | 
								return pair, nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return types.ConversionPair{}, sdkerrors.Wrap(types.ErrConversionNotEnabled, address.String())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetEnabledConversionPairFromDenom returns an ConversionPair from the sdk.Coin denom.
 | 
				
			||||||
 | 
					func (k Keeper) GetEnabledConversionPairFromDenom(
 | 
				
			||||||
 | 
						ctx sdk.Context,
 | 
				
			||||||
 | 
						denom string,
 | 
				
			||||||
 | 
					) (types.ConversionPair, error) {
 | 
				
			||||||
 | 
						params := k.GetParams(ctx)
 | 
				
			||||||
 | 
						for _, pair := range params.EnabledConversionPairs {
 | 
				
			||||||
 | 
							if pair.Denom == denom {
 | 
				
			||||||
 | 
								return pair, nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return types.ConversionPair{}, sdkerrors.Wrap(types.ErrConversionNotEnabled, denom)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										36
									
								
								x/evmutil/keeper/params_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								x/evmutil/keeper/params_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					package keeper_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/suite"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/testutil"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ParamsTestSuite struct {
 | 
				
			||||||
 | 
						testutil.Suite
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestParamsSuite(t *testing.T) {
 | 
				
			||||||
 | 
						suite.Run(t, new(ParamsTestSuite))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ParamsTestSuite) TestEnabledConversionPair() {
 | 
				
			||||||
 | 
						pairAddr := testutil.MustNewInternalEVMAddressFromString("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")
 | 
				
			||||||
 | 
						expPair := types.ConversionPair{
 | 
				
			||||||
 | 
							KavaERC20Address: pairAddr.Bytes(),
 | 
				
			||||||
 | 
							Denom:            "weth",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						params := types.DefaultParams()
 | 
				
			||||||
 | 
						params.EnabledConversionPairs = []types.ConversionPair{expPair}
 | 
				
			||||||
 | 
						suite.Keeper.SetParams(suite.Ctx, params)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						actualPair, err := suite.Keeper.GetEnabledConversionPairFromERC20Address(
 | 
				
			||||||
 | 
							suite.Ctx,
 | 
				
			||||||
 | 
							pairAddr,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						suite.Require().Equal(expPair, actualPair)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
package evmutil
 | 
					package evmutil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gorilla/mux"
 | 
						"github.com/gorilla/mux"
 | 
				
			||||||
@ -15,6 +16,7 @@ import (
 | 
				
			|||||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
	"github.com/cosmos/cosmos-sdk/types/module"
 | 
						"github.com/cosmos/cosmos-sdk/types/module"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/client/cli"
 | 
				
			||||||
	"github.com/kava-labs/kava/x/evmutil/keeper"
 | 
						"github.com/kava-labs/kava/x/evmutil/keeper"
 | 
				
			||||||
	"github.com/kava-labs/kava/x/evmutil/types"
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@ -44,7 +46,9 @@ func (AppModuleBasic) Name() string {
 | 
				
			|||||||
func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {}
 | 
					func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RegisterInterfaces registers the module's interface types
 | 
					// RegisterInterfaces registers the module's interface types
 | 
				
			||||||
func (a AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry) {}
 | 
					func (a AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry) {
 | 
				
			||||||
 | 
						types.RegisterInterfaces(reg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DefaultGenesis default genesis state
 | 
					// DefaultGenesis default genesis state
 | 
				
			||||||
func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage {
 | 
					func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage {
 | 
				
			||||||
@ -66,13 +70,21 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncod
 | 
				
			|||||||
func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) {}
 | 
					func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for evmutil module.
 | 
					// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for evmutil module.
 | 
				
			||||||
func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {}
 | 
					func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
 | 
				
			||||||
 | 
						if err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)); err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetTxCmd returns evmutil module's root tx command.
 | 
					// GetTxCmd returns evmutil module's root tx command.
 | 
				
			||||||
func (a AppModuleBasic) GetTxCmd() *cobra.Command { return nil }
 | 
					func (a AppModuleBasic) GetTxCmd() *cobra.Command {
 | 
				
			||||||
 | 
						return cli.GetTxCmd()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetQueryCmd returns evmutil module's root query command.
 | 
					// GetQueryCmd returns evmutil module's root query command.
 | 
				
			||||||
func (AppModuleBasic) GetQueryCmd() *cobra.Command { return nil }
 | 
					func (AppModuleBasic) GetQueryCmd() *cobra.Command {
 | 
				
			||||||
 | 
						return cli.GetQueryCmd()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					// ----------------------------------------------------------------------------
 | 
				
			||||||
// AppModule
 | 
					// AppModule
 | 
				
			||||||
@ -104,7 +116,7 @@ func (am AppModule) Name() string {
 | 
				
			|||||||
func (am AppModule) Route() sdk.Route { return sdk.Route{} }
 | 
					func (am AppModule) Route() sdk.Route { return sdk.Route{} }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// QuerierRoute returns evmutil module's query routing key.
 | 
					// QuerierRoute returns evmutil module's query routing key.
 | 
				
			||||||
func (AppModule) QuerierRoute() string { return types.ModuleName }
 | 
					func (AppModule) QuerierRoute() string { return "" }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LegacyQuerierHandler returns evmutil module's Querier.
 | 
					// LegacyQuerierHandler returns evmutil module's Querier.
 | 
				
			||||||
func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier {
 | 
					func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier {
 | 
				
			||||||
@ -113,7 +125,10 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// RegisterServices registers a GRPC query service to respond to the
 | 
					// RegisterServices registers a GRPC query service to respond to the
 | 
				
			||||||
// module-specific GRPC queries.
 | 
					// module-specific GRPC queries.
 | 
				
			||||||
func (am AppModule) RegisterServices(cfg module.Configurator) {}
 | 
					func (am AppModule) RegisterServices(cfg module.Configurator) {
 | 
				
			||||||
 | 
						types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper))
 | 
				
			||||||
 | 
						types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServerImpl(am.keeper))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RegisterInvariants registers evmutil module's invariants.
 | 
					// RegisterInvariants registers evmutil module's invariants.
 | 
				
			||||||
func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {
 | 
					func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,29 +1,63 @@
 | 
				
			|||||||
package testutil
 | 
					package testutil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/hex"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/baseapp"
 | 
				
			||||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
	authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
 | 
						authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
 | 
				
			||||||
 | 
						authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
 | 
				
			||||||
	bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
 | 
						bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
 | 
				
			||||||
 | 
						minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
 | 
				
			||||||
 | 
						stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/accounts/abi"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common/hexutil"
 | 
				
			||||||
 | 
						ethtypes "github.com/ethereum/go-ethereum/core/types"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/core/vm"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/crypto"
 | 
				
			||||||
	"github.com/stretchr/testify/suite"
 | 
						"github.com/stretchr/testify/suite"
 | 
				
			||||||
 | 
						abci "github.com/tendermint/tendermint/abci/types"
 | 
				
			||||||
 | 
						"github.com/tendermint/tendermint/crypto/tmhash"
 | 
				
			||||||
	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
 | 
						tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
 | 
				
			||||||
 | 
						tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
 | 
				
			||||||
	tmtime "github.com/tendermint/tendermint/types/time"
 | 
						tmtime "github.com/tendermint/tendermint/types/time"
 | 
				
			||||||
 | 
						"github.com/tendermint/tendermint/version"
 | 
				
			||||||
 | 
						"github.com/tharsis/ethermint/crypto/ethsecp256k1"
 | 
				
			||||||
 | 
						"github.com/tharsis/ethermint/server/config"
 | 
				
			||||||
 | 
						etherminttests "github.com/tharsis/ethermint/tests"
 | 
				
			||||||
 | 
						etherminttypes "github.com/tharsis/ethermint/types"
 | 
				
			||||||
	evmtypes "github.com/tharsis/ethermint/x/evm/types"
 | 
						evmtypes "github.com/tharsis/ethermint/x/evm/types"
 | 
				
			||||||
 | 
						feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/kava-labs/kava/app"
 | 
						"github.com/kava-labs/kava/app"
 | 
				
			||||||
	"github.com/kava-labs/kava/x/evmutil/keeper"
 | 
						"github.com/kava-labs/kava/x/evmutil/keeper"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Suite struct {
 | 
					type Suite struct {
 | 
				
			||||||
	suite.Suite
 | 
						suite.Suite
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	App           app.TestApp
 | 
						App            app.TestApp
 | 
				
			||||||
	Ctx           sdk.Context
 | 
						Ctx            sdk.Context
 | 
				
			||||||
	BankKeeper    bankkeeper.Keeper
 | 
						Address        common.Address
 | 
				
			||||||
	AccountKeeper authkeeper.AccountKeeper
 | 
						BankKeeper     bankkeeper.Keeper
 | 
				
			||||||
	Keeper        keeper.Keeper
 | 
						AccountKeeper  authkeeper.AccountKeeper
 | 
				
			||||||
	EvmBankKeeper keeper.EvmBankKeeper
 | 
						Keeper         keeper.Keeper
 | 
				
			||||||
	Addrs         []sdk.AccAddress
 | 
						EvmBankKeeper  keeper.EvmBankKeeper
 | 
				
			||||||
	EvmModuleAddr sdk.AccAddress
 | 
						Addrs          []sdk.AccAddress
 | 
				
			||||||
 | 
						EvmModuleAddr  sdk.AccAddress
 | 
				
			||||||
 | 
						QueryClient    types.QueryClient
 | 
				
			||||||
 | 
						QueryClientEvm evmtypes.QueryClient
 | 
				
			||||||
 | 
						Key1           *ethsecp256k1.PrivKey
 | 
				
			||||||
 | 
						Key1Addr       types.InternalEVMAddress
 | 
				
			||||||
 | 
						Key2           *ethsecp256k1.PrivKey
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *Suite) SetupTest() {
 | 
					func (suite *Suite) SetupTest() {
 | 
				
			||||||
@ -37,13 +71,114 @@ func (suite *Suite) SetupTest() {
 | 
				
			|||||||
	suite.EvmBankKeeper = keeper.NewEvmBankKeeper(tApp.GetEvmutilKeeper(), suite.BankKeeper, suite.AccountKeeper)
 | 
						suite.EvmBankKeeper = keeper.NewEvmBankKeeper(tApp.GetEvmutilKeeper(), suite.BankKeeper, suite.AccountKeeper)
 | 
				
			||||||
	suite.EvmModuleAddr = suite.AccountKeeper.GetModuleAddress(evmtypes.ModuleName)
 | 
						suite.EvmModuleAddr = suite.AccountKeeper.GetModuleAddress(evmtypes.ModuleName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// test evm user keys that have no minting permissions
 | 
				
			||||||
 | 
						key1, err := ethsecp256k1.GenerateKey()
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						suite.Key1 = key1
 | 
				
			||||||
 | 
						suite.Key1Addr = types.NewInternalEVMAddress(common.BytesToAddress(suite.Key1.PubKey().Address()))
 | 
				
			||||||
 | 
						suite.Key2, err = ethsecp256k1.GenerateKey()
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, addrs := app.GeneratePrivKeyAddressPairs(4)
 | 
						_, addrs := app.GeneratePrivKeyAddressPairs(4)
 | 
				
			||||||
	suite.Addrs = addrs
 | 
						suite.Addrs = addrs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	evmGenesis := evmtypes.DefaultGenesisState()
 | 
						evmGenesis := evmtypes.DefaultGenesisState()
 | 
				
			||||||
	evmGenesis.Params.EvmDenom = "akava"
 | 
						evmGenesis.Params.EvmDenom = "akava"
 | 
				
			||||||
	gs := app.GenesisState{evmtypes.ModuleName: suite.App.AppCodec().MustMarshalJSON(evmGenesis)}
 | 
					
 | 
				
			||||||
	suite.App.InitializeFromGenesisStates(gs)
 | 
						feemarketGenesis := feemarkettypes.DefaultGenesisState()
 | 
				
			||||||
 | 
						feemarketGenesis.Params.EnableHeight = 1
 | 
				
			||||||
 | 
						feemarketGenesis.Params.NoBaseFee = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cdc := suite.App.AppCodec()
 | 
				
			||||||
 | 
						coins := sdk.NewCoins(sdk.NewInt64Coin("ukava", 1000_000_000_000_000_000))
 | 
				
			||||||
 | 
						authGS := app.NewFundedGenStateWithSameCoins(cdc, coins, []sdk.AccAddress{
 | 
				
			||||||
 | 
							sdk.AccAddress(suite.Key1.PubKey().Address()),
 | 
				
			||||||
 | 
							sdk.AccAddress(suite.Key2.PubKey().Address()),
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gs := app.GenesisState{
 | 
				
			||||||
 | 
							evmtypes.ModuleName:       cdc.MustMarshalJSON(evmGenesis),
 | 
				
			||||||
 | 
							feemarkettypes.ModuleName: cdc.MustMarshalJSON(feemarketGenesis),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						suite.App.InitializeFromGenesisStates(authGS, gs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// consensus key - needed to set up evm module
 | 
				
			||||||
 | 
						consPriv, err := ethsecp256k1.GenerateKey()
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						consAddress := sdk.ConsAddress(consPriv.PubKey().Address())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// InitializeFromGenesisStates commits first block so we start at 2 here
 | 
				
			||||||
 | 
						suite.Ctx = suite.App.NewContext(false, tmproto.Header{
 | 
				
			||||||
 | 
							Height:          suite.App.LastBlockHeight() + 1,
 | 
				
			||||||
 | 
							ChainID:         "kavatest_1-1",
 | 
				
			||||||
 | 
							Time:            time.Now().UTC(),
 | 
				
			||||||
 | 
							ProposerAddress: consAddress.Bytes(),
 | 
				
			||||||
 | 
							Version: tmversion.Consensus{
 | 
				
			||||||
 | 
								Block: version.BlockProtocol,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							LastBlockId: tmproto.BlockID{
 | 
				
			||||||
 | 
								Hash: tmhash.Sum([]byte("block_id")),
 | 
				
			||||||
 | 
								PartSetHeader: tmproto.PartSetHeader{
 | 
				
			||||||
 | 
									Total: 11,
 | 
				
			||||||
 | 
									Hash:  tmhash.Sum([]byte("partset_header")),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							AppHash:            tmhash.Sum([]byte("app")),
 | 
				
			||||||
 | 
							DataHash:           tmhash.Sum([]byte("data")),
 | 
				
			||||||
 | 
							EvidenceHash:       tmhash.Sum([]byte("evidence")),
 | 
				
			||||||
 | 
							ValidatorsHash:     tmhash.Sum([]byte("validators")),
 | 
				
			||||||
 | 
							NextValidatorsHash: tmhash.Sum([]byte("next_validators")),
 | 
				
			||||||
 | 
							ConsensusHash:      tmhash.Sum([]byte("consensus")),
 | 
				
			||||||
 | 
							LastResultsHash:    tmhash.Sum([]byte("last_result")),
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We need to set the validator as calling the EVM looks up the validator address
 | 
				
			||||||
 | 
						// https://github.com/tharsis/ethermint/blob/f21592ebfe74da7590eb42ed926dae970b2a9a3f/x/evm/keeper/state_transition.go#L487
 | 
				
			||||||
 | 
						// evmkeeper.EVMConfig() will return error "failed to load evm config" if not set
 | 
				
			||||||
 | 
						acc := ðerminttypes.EthAccount{
 | 
				
			||||||
 | 
							BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(suite.Address.Bytes()), nil, 0, 0),
 | 
				
			||||||
 | 
							CodeHash:    common.BytesToHash(crypto.Keccak256(nil)).String(),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						suite.AccountKeeper.SetAccount(suite.Ctx, acc)
 | 
				
			||||||
 | 
						valAddr := sdk.ValAddress(suite.Address.Bytes())
 | 
				
			||||||
 | 
						validator, err := stakingtypes.NewValidator(valAddr, consPriv.PubKey(), stakingtypes.Description{})
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						err = suite.App.GetStakingKeeper().SetValidatorByConsAddr(suite.Ctx, validator)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						suite.App.GetStakingKeeper().SetValidator(suite.Ctx, validator)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// add conversion pair for first module deployed contract to evmutil params
 | 
				
			||||||
 | 
						suite.Keeper.SetParams(suite.Ctx, types.NewParams(
 | 
				
			||||||
 | 
							types.NewConversionPairs(
 | 
				
			||||||
 | 
								types.NewConversionPair(
 | 
				
			||||||
 | 
									// First contract this module deploys
 | 
				
			||||||
 | 
									MustNewInternalEVMAddressFromString("0x15932E26f5BD4923d46a2b205191C4b5d5f43FE3"),
 | 
				
			||||||
 | 
									"erc20/usdc",
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						queryHelper := baseapp.NewQueryServerTestHelper(suite.Ctx, suite.App.InterfaceRegistry())
 | 
				
			||||||
 | 
						evmtypes.RegisterQueryServer(queryHelper, suite.App.GetEvmKeeper())
 | 
				
			||||||
 | 
						suite.QueryClientEvm = evmtypes.NewQueryClient(queryHelper)
 | 
				
			||||||
 | 
						types.RegisterQueryServer(queryHelper, keeper.NewQueryServerImpl(suite.App.GetEvmutilKeeper()))
 | 
				
			||||||
 | 
						suite.QueryClient = types.NewQueryClient(queryHelper)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We need to commit so that the ethermint feemarket beginblock runs to set the minfee
 | 
				
			||||||
 | 
						// feeMarketKeeper.GetBaseFee() will return nil otherwise
 | 
				
			||||||
 | 
						suite.Commit()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *Suite) Commit() {
 | 
				
			||||||
 | 
						_ = suite.App.Commit()
 | 
				
			||||||
 | 
						header := suite.Ctx.BlockHeader()
 | 
				
			||||||
 | 
						header.Height += 1
 | 
				
			||||||
 | 
						suite.App.BeginBlock(abci.RequestBeginBlock{
 | 
				
			||||||
 | 
							Header: header,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// update ctx
 | 
				
			||||||
 | 
						suite.Ctx = suite.App.NewContext(false, header)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *Suite) FundAccountWithKava(addr sdk.AccAddress, coins sdk.Coins) {
 | 
					func (suite *Suite) FundAccountWithKava(addr sdk.AccAddress, coins sdk.Coins) {
 | 
				
			||||||
@ -72,3 +207,206 @@ func (suite *Suite) FundModuleAccountWithKava(moduleName string, coins sdk.Coins
 | 
				
			|||||||
		suite.Require().NoError(err)
 | 
							suite.Require().NoError(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *Suite) DeployERC20() types.InternalEVMAddress {
 | 
				
			||||||
 | 
						// make sure module account is created
 | 
				
			||||||
 | 
						// qq: any better ways to do this?
 | 
				
			||||||
 | 
						suite.App.FundModuleAccount(
 | 
				
			||||||
 | 
							suite.Ctx,
 | 
				
			||||||
 | 
							types.ModuleName,
 | 
				
			||||||
 | 
							sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(0))),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						contractAddr, err := suite.Keeper.DeployTestMintableERC20Contract(suite.Ctx, "USDC", "USDC", uint8(18))
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						suite.Require().Greater(len(contractAddr.Address), 0)
 | 
				
			||||||
 | 
						return contractAddr
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *Suite) GetERC20BalanceOf(
 | 
				
			||||||
 | 
						contractAbi abi.ABI,
 | 
				
			||||||
 | 
						contractAddr types.InternalEVMAddress,
 | 
				
			||||||
 | 
						accountAddr types.InternalEVMAddress,
 | 
				
			||||||
 | 
					) *big.Int {
 | 
				
			||||||
 | 
						// Query ERC20.balanceOf()
 | 
				
			||||||
 | 
						addr := common.BytesToAddress(suite.Key1.PubKey().Address())
 | 
				
			||||||
 | 
						res, err := suite.QueryContract(
 | 
				
			||||||
 | 
							types.ERC20MintableBurnableContract.ABI,
 | 
				
			||||||
 | 
							addr,
 | 
				
			||||||
 | 
							suite.Key1,
 | 
				
			||||||
 | 
							contractAddr,
 | 
				
			||||||
 | 
							"balanceOf",
 | 
				
			||||||
 | 
							accountAddr.Address,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						suite.Require().Len(res, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						balance, ok := res[0].(*big.Int)
 | 
				
			||||||
 | 
						suite.Require().True(ok, "balanceOf should respond with *big.Int")
 | 
				
			||||||
 | 
						return balance
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *Suite) QueryContract(
 | 
				
			||||||
 | 
						contractAbi abi.ABI,
 | 
				
			||||||
 | 
						from common.Address,
 | 
				
			||||||
 | 
						fromKey *ethsecp256k1.PrivKey,
 | 
				
			||||||
 | 
						contract types.InternalEVMAddress,
 | 
				
			||||||
 | 
						method string,
 | 
				
			||||||
 | 
						args ...interface{},
 | 
				
			||||||
 | 
					) ([]interface{}, error) {
 | 
				
			||||||
 | 
						// Pack query args
 | 
				
			||||||
 | 
						data, err := contractAbi.Pack(method, args...)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Send TX
 | 
				
			||||||
 | 
						res, err := suite.SendTx(contract, from, fromKey, data)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check for VM errors and unpack returned data
 | 
				
			||||||
 | 
						switch res.VmError {
 | 
				
			||||||
 | 
						case vm.ErrExecutionReverted.Error():
 | 
				
			||||||
 | 
							response, err := abi.UnpackRevert(res.Ret)
 | 
				
			||||||
 | 
							suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return nil, errors.New(response)
 | 
				
			||||||
 | 
						case "": // No error, continue
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							panic(fmt.Sprintf("unhandled vm error response: %v", res.VmError))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Unpack response
 | 
				
			||||||
 | 
						unpackedRes, err := contractAbi.Unpack(method, res.Ret)
 | 
				
			||||||
 | 
						suite.Require().NoErrorf(err, "failed to unpack method %v response", method)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return unpackedRes, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SendTx submits a transaction to the block.
 | 
				
			||||||
 | 
					func (suite *Suite) SendTx(
 | 
				
			||||||
 | 
						contractAddr types.InternalEVMAddress,
 | 
				
			||||||
 | 
						from common.Address,
 | 
				
			||||||
 | 
						signerKey *ethsecp256k1.PrivKey,
 | 
				
			||||||
 | 
						transferData []byte,
 | 
				
			||||||
 | 
					) (*evmtypes.MsgEthereumTxResponse, error) {
 | 
				
			||||||
 | 
						ctx := sdk.WrapSDKContext(suite.Ctx)
 | 
				
			||||||
 | 
						chainID := suite.App.GetEvmKeeper().ChainID()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						args, err := json.Marshal(&evmtypes.TransactionArgs{
 | 
				
			||||||
 | 
							To:   &contractAddr.Address,
 | 
				
			||||||
 | 
							From: &from,
 | 
				
			||||||
 | 
							Data: (*hexutil.Bytes)(&transferData),
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						gasRes, err := suite.QueryClientEvm.EstimateGas(ctx, &evmtypes.EthCallRequest{
 | 
				
			||||||
 | 
							Args:   args,
 | 
				
			||||||
 | 
							GasCap: config.DefaultGasCap,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nonce := suite.App.GetEvmKeeper().GetNonce(suite.Ctx, suite.Address)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						baseFee := suite.App.GetFeeMarketKeeper().GetBaseFee(suite.Ctx)
 | 
				
			||||||
 | 
						suite.Require().NotNil(baseFee, "base fee is nil")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Mint the max gas to the FeeCollector to ensure balance in case of refund
 | 
				
			||||||
 | 
						suite.MintFeeCollector(sdk.NewCoins(
 | 
				
			||||||
 | 
							sdk.NewCoin(
 | 
				
			||||||
 | 
								"ukava",
 | 
				
			||||||
 | 
								sdk.NewInt(baseFee.Int64()*int64(gasRes.Gas*2)),
 | 
				
			||||||
 | 
							)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ercTransferTx := evmtypes.NewTx(
 | 
				
			||||||
 | 
							chainID,
 | 
				
			||||||
 | 
							nonce,
 | 
				
			||||||
 | 
							&contractAddr.Address,
 | 
				
			||||||
 | 
							nil,          // amount
 | 
				
			||||||
 | 
							gasRes.Gas*2, // gasLimit, TODO: runs out of gas with just res.Gas, ex: estimated was 21572 but used 24814
 | 
				
			||||||
 | 
							nil,          // gasPrice
 | 
				
			||||||
 | 
							suite.App.GetFeeMarketKeeper().GetBaseFee(suite.Ctx), // gasFeeCap
 | 
				
			||||||
 | 
							big.NewInt(1), // gasTipCap
 | 
				
			||||||
 | 
							transferData,
 | 
				
			||||||
 | 
							ðtypes.AccessList{}, // accesses
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ercTransferTx.From = hex.EncodeToString(signerKey.PubKey().Address())
 | 
				
			||||||
 | 
						err = ercTransferTx.Sign(ethtypes.LatestSignerForChainID(chainID), etherminttests.NewSigner(signerKey))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rsp, err := suite.App.GetEvmKeeper().EthereumTx(ctx, ercTransferTx)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Do not check vm error here since we want to check for errors later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rsp, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *Suite) MintFeeCollector(coins sdk.Coins) {
 | 
				
			||||||
 | 
						err := suite.App.GetBankKeeper().MintCoins(suite.Ctx, minttypes.ModuleName, coins)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						err = suite.App.GetBankKeeper().SendCoinsFromModuleToModule(
 | 
				
			||||||
 | 
							suite.Ctx,
 | 
				
			||||||
 | 
							minttypes.ModuleName,
 | 
				
			||||||
 | 
							authtypes.FeeCollectorName,
 | 
				
			||||||
 | 
							coins,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetEvents returns emitted events on the sdk context
 | 
				
			||||||
 | 
					func (suite *Suite) GetEvents() sdk.Events {
 | 
				
			||||||
 | 
						return suite.Ctx.EventManager().Events()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// EventsContains asserts that the expected event is in the provided events
 | 
				
			||||||
 | 
					func (suite *Suite) EventsContains(events sdk.Events, expectedEvent sdk.Event) {
 | 
				
			||||||
 | 
						foundMatch := false
 | 
				
			||||||
 | 
						for _, event := range events {
 | 
				
			||||||
 | 
							if event.Type == expectedEvent.Type {
 | 
				
			||||||
 | 
								if reflect.DeepEqual(attrsToMap(expectedEvent.Attributes), attrsToMap(event.Attributes)) {
 | 
				
			||||||
 | 
									foundMatch = true
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						suite.Truef(foundMatch, "event of type %s not found or did not match", expectedEvent.Type)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// EventsDoNotContain asserts that the event is **not** is in the provided events
 | 
				
			||||||
 | 
					func (suite *Suite) EventsDoNotContain(events sdk.Events, eventType string) {
 | 
				
			||||||
 | 
						foundMatch := false
 | 
				
			||||||
 | 
						for _, event := range events {
 | 
				
			||||||
 | 
							if event.Type == eventType {
 | 
				
			||||||
 | 
								foundMatch = true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						suite.Falsef(foundMatch, "event of type %s should not be found, but was found", eventType)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func attrsToMap(attrs []abci.EventAttribute) []sdk.Attribute {
 | 
				
			||||||
 | 
						out := []sdk.Attribute{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, attr := range attrs {
 | 
				
			||||||
 | 
							out = append(out, sdk.NewAttribute(string(attr.Key), string(attr.Value)))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return out
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MustNewInternalEVMAddressFromString returns a new InternalEVMAddress from a
 | 
				
			||||||
 | 
					// hex string. This will panic if the input hex string is invalid.
 | 
				
			||||||
 | 
					func MustNewInternalEVMAddressFromString(addrStr string) types.InternalEVMAddress {
 | 
				
			||||||
 | 
						addr, err := types.NewInternalEVMAddressFromString(addrStr)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return addr
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										33
									
								
								x/evmutil/types/address.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								x/evmutil/types/address.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					package types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// InternalEVMAddress is a type alias of common.Address to represent an address
 | 
				
			||||||
 | 
					// on the Kava EVM.
 | 
				
			||||||
 | 
					type InternalEVMAddress struct {
 | 
				
			||||||
 | 
						common.Address
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewInternalEVMAddress returns a new InternalEVMAddress from a common.Address.
 | 
				
			||||||
 | 
					func NewInternalEVMAddress(addr common.Address) InternalEVMAddress {
 | 
				
			||||||
 | 
						return InternalEVMAddress{
 | 
				
			||||||
 | 
							Address: addr,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewInternalEVMAddressFromString returns a new InternalEVMAddress from a hex
 | 
				
			||||||
 | 
					// string. Returns an error if hex string is invalid.
 | 
				
			||||||
 | 
					func NewInternalEVMAddressFromString(addrStr string) (InternalEVMAddress, error) {
 | 
				
			||||||
 | 
						if !common.IsHexAddress(addrStr) {
 | 
				
			||||||
 | 
							return InternalEVMAddress{}, fmt.Errorf("string is not a hex address %v", addrStr)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// common.HexToAddress ignores hex decoding errors
 | 
				
			||||||
 | 
						addr := common.HexToAddress(addrStr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NewInternalEVMAddress(addr), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										25
									
								
								x/evmutil/types/bytes.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								x/evmutil/types/bytes.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					package types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common/hexutil"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// HexBytes represents a byte slice that marshals into a 0x representation
 | 
				
			||||||
 | 
					type HexBytes []byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MarshalJSON marshals HexBytes into a 0x json string
 | 
				
			||||||
 | 
					func (b HexBytes) MarshalJSON() ([]byte, error) {
 | 
				
			||||||
 | 
						return json.Marshal(hexutil.Encode(b))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UnmarshalJSON unmarshals a 0x json string into bytes
 | 
				
			||||||
 | 
					func (b *HexBytes) UnmarshalJSON(input []byte) error {
 | 
				
			||||||
 | 
						return (*hexutil.Bytes)(b).UnmarshalJSON(input)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// String implements Stringer and returns the 0x representation
 | 
				
			||||||
 | 
					func (b HexBytes) String() string {
 | 
				
			||||||
 | 
						return hexutil.Encode(b)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										32
									
								
								x/evmutil/types/bytes_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								x/evmutil/types/bytes_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					package types_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/require"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestHexBytes(t *testing.T) {
 | 
				
			||||||
 | 
						testCases := []struct {
 | 
				
			||||||
 | 
							input  types.HexBytes
 | 
				
			||||||
 | 
							output string
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{[]byte{}, "0x"}, // empty slice is 0x
 | 
				
			||||||
 | 
							{[]byte{0}, "0x00"},
 | 
				
			||||||
 | 
							{[]byte{1}, "0x01"},
 | 
				
			||||||
 | 
							{[]byte{1, 2, 3}, "0x010203"},
 | 
				
			||||||
 | 
							{[]byte{255}, "0xff"},
 | 
				
			||||||
 | 
							{[]byte{16, 16}, "0x1010"},
 | 
				
			||||||
 | 
							{[]byte{16, 16}, "0x1010"},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range testCases {
 | 
				
			||||||
 | 
							bz, err := json.Marshal(tc.input)
 | 
				
			||||||
 | 
							require.NoError(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							require.Equal(t, fmt.Sprintf("\"%s\"", tc.output), string(bz))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										36
									
								
								x/evmutil/types/codec.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								x/evmutil/types/codec.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					package types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/codec"
 | 
				
			||||||
 | 
						cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
 | 
				
			||||||
 | 
						cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/types/msgservice"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RegisterLegacyAminoCodec registers the necessary evmutil interfaces and concrete types
 | 
				
			||||||
 | 
					// on the provided LegacyAmino codec. These types are used for Amino JSON serialization.
 | 
				
			||||||
 | 
					func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
 | 
				
			||||||
 | 
						cdc.RegisterConcrete(&MsgConvertCoinToERC20{}, "evmutil/MsgConvertCoinToERC20", nil)
 | 
				
			||||||
 | 
						cdc.RegisterConcrete(&MsgConvertERC20ToCoin{}, "evmutil/MsgConvertERC20ToCoin", nil)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
 | 
				
			||||||
 | 
						registry.RegisterImplementations((*sdk.Msg)(nil),
 | 
				
			||||||
 | 
							&MsgConvertCoinToERC20{},
 | 
				
			||||||
 | 
							&MsgConvertERC20ToCoin{},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						amino     = codec.NewLegacyAmino()
 | 
				
			||||||
 | 
						ModuleCdc = codec.NewAminoCodec(amino)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						RegisterLegacyAminoCodec(amino)
 | 
				
			||||||
 | 
						cryptocodec.RegisterCrypto(amino)
 | 
				
			||||||
 | 
						amino.Seal()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										48
									
								
								x/evmutil/types/contract.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								x/evmutil/types/contract.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					// Derived from https://github.com/tharsis/evmos/blob/0bfaf0db7be47153bc651e663176ba8deca960b5/contracts/erc20.go
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//      http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						// Embed ERC20 JSON files
 | 
				
			||||||
 | 
						_ "embed"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
 | 
						evmtypes "github.com/tharsis/ethermint/x/evm/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						//go:embed ethermint_json/ERC20MintableBurnable.json
 | 
				
			||||||
 | 
						ERC20MintableBurnableJSON []byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ERC20MintableBurnableContract is the compiled erc20 contract
 | 
				
			||||||
 | 
						ERC20MintableBurnableContract evmtypes.CompiledContract
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ERC20MintableBurnableAddress is the erc20 module address
 | 
				
			||||||
 | 
						ERC20MintableBurnableAddress common.Address
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						ERC20MintableBurnableAddress = ModuleEVMAddress
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := json.Unmarshal(ERC20MintableBurnableJSON, &ERC20MintableBurnableContract)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(ERC20MintableBurnableContract.Bin) == 0 {
 | 
				
			||||||
 | 
							panic("load contract failed")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										89
									
								
								x/evmutil/types/conversion_pair.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								x/evmutil/types/conversion_pair.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,89 @@
 | 
				
			|||||||
 | 
					package types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						bytes "bytes"
 | 
				
			||||||
 | 
						"encoding/hex"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewConversionPair returns a new ConversionPair.
 | 
				
			||||||
 | 
					func NewConversionPair(address InternalEVMAddress, denom string) ConversionPair {
 | 
				
			||||||
 | 
						return ConversionPair{
 | 
				
			||||||
 | 
							KavaERC20Address: address.Address.Bytes(),
 | 
				
			||||||
 | 
							Denom:            denom,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetAddress returns the InternalEVMAddress of the Kava ERC20 address.
 | 
				
			||||||
 | 
					func (pair ConversionPair) GetAddress() InternalEVMAddress {
 | 
				
			||||||
 | 
						return NewInternalEVMAddress(common.BytesToAddress(pair.KavaERC20Address))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Validate returns an error if the ConversionPair is invalid.
 | 
				
			||||||
 | 
					func (pair ConversionPair) Validate() error {
 | 
				
			||||||
 | 
						if err := sdk.ValidateDenom(pair.Denom); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("conversion pair denom invalid: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(pair.KavaERC20Address) != common.AddressLength {
 | 
				
			||||||
 | 
							return fmt.Errorf("address length is %v but expected %v", len(pair.KavaERC20Address), common.AddressLength)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if bytes.Equal(pair.KavaERC20Address, common.Address{}.Bytes()) {
 | 
				
			||||||
 | 
							return fmt.Errorf("address cannot be zero value %v", hex.EncodeToString(pair.KavaERC20Address))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ConversionPairs defines a slice of ConversionPair.
 | 
				
			||||||
 | 
					type ConversionPairs []ConversionPair
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewConversionPairs returns ConversionPairs from the provided values.
 | 
				
			||||||
 | 
					func NewConversionPairs(pairs ...ConversionPair) ConversionPairs {
 | 
				
			||||||
 | 
						return ConversionPairs(pairs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (pairs ConversionPairs) Validate() error {
 | 
				
			||||||
 | 
						// Check for duplicates for both addrs and denoms
 | 
				
			||||||
 | 
						addrs := map[string]bool{}
 | 
				
			||||||
 | 
						denoms := map[string]bool{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, pair := range pairs {
 | 
				
			||||||
 | 
							if addrs[hex.EncodeToString(pair.KavaERC20Address)] {
 | 
				
			||||||
 | 
								return fmt.Errorf(
 | 
				
			||||||
 | 
									"found duplicate enabled conversion pair internal ERC20 address %s",
 | 
				
			||||||
 | 
									hex.EncodeToString(pair.KavaERC20Address),
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if denoms[pair.Denom] {
 | 
				
			||||||
 | 
								return fmt.Errorf(
 | 
				
			||||||
 | 
									"found duplicate enabled conversion pair denom %s",
 | 
				
			||||||
 | 
									pair.Denom,
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err := pair.Validate(); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							addrs[hex.EncodeToString(pair.KavaERC20Address)] = true
 | 
				
			||||||
 | 
							denoms[pair.Denom] = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// validateConversionPairs validates an interface as ConversionPairs
 | 
				
			||||||
 | 
					func validateConversionPairs(i interface{}) error {
 | 
				
			||||||
 | 
						pairs, ok := i.(ConversionPairs)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return fmt.Errorf("invalid parameter type: %T", i)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return pairs.Validate()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										428
									
								
								x/evmutil/types/conversion_pair.pb.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										428
									
								
								x/evmutil/types/conversion_pair.pb.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,428 @@
 | 
				
			|||||||
 | 
					// Code generated by protoc-gen-gogo. DO NOT EDIT.
 | 
				
			||||||
 | 
					// source: kava/evmutil/v1beta1/conversion_pair.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						bytes "bytes"
 | 
				
			||||||
 | 
						fmt "fmt"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						proto "github.com/gogo/protobuf/proto"
 | 
				
			||||||
 | 
						io "io"
 | 
				
			||||||
 | 
						math "math"
 | 
				
			||||||
 | 
						math_bits "math/bits"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Reference imports to suppress errors if they are not otherwise used.
 | 
				
			||||||
 | 
					var _ = proto.Marshal
 | 
				
			||||||
 | 
					var _ = fmt.Errorf
 | 
				
			||||||
 | 
					var _ = math.Inf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is a compile-time assertion to ensure that this generated file
 | 
				
			||||||
 | 
					// is compatible with the proto package it is being compiled against.
 | 
				
			||||||
 | 
					// A compilation error at this line likely means your copy of the
 | 
				
			||||||
 | 
					// proto package needs to be updated.
 | 
				
			||||||
 | 
					const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ConversionPair defines a Kava ERC20 address and corresponding denom that is
 | 
				
			||||||
 | 
					// allowed to be converted between ERC20 and sdk.Coin
 | 
				
			||||||
 | 
					type ConversionPair struct {
 | 
				
			||||||
 | 
						// ERC20 address of the token on the Kava EVM
 | 
				
			||||||
 | 
						KavaERC20Address HexBytes `protobuf:"bytes,1,opt,name=kava_erc20_address,json=kavaErc20Address,proto3,casttype=HexBytes" json:"kava_erc20_address,omitempty"`
 | 
				
			||||||
 | 
						// Denom of the corresponding sdk.Coin
 | 
				
			||||||
 | 
						Denom string `protobuf:"bytes,2,opt,name=denom,proto3" json:"denom,omitempty"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *ConversionPair) Reset()         { *m = ConversionPair{} }
 | 
				
			||||||
 | 
					func (m *ConversionPair) String() string { return proto.CompactTextString(m) }
 | 
				
			||||||
 | 
					func (*ConversionPair) ProtoMessage()    {}
 | 
				
			||||||
 | 
					func (*ConversionPair) Descriptor() ([]byte, []int) {
 | 
				
			||||||
 | 
						return fileDescriptor_e1396d08199817d0, []int{0}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *ConversionPair) XXX_Unmarshal(b []byte) error {
 | 
				
			||||||
 | 
						return m.Unmarshal(b)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *ConversionPair) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 | 
				
			||||||
 | 
						if deterministic {
 | 
				
			||||||
 | 
							return xxx_messageInfo_ConversionPair.Marshal(b, m, deterministic)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							b = b[:cap(b)]
 | 
				
			||||||
 | 
							n, err := m.MarshalToSizedBuffer(b)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return b[:n], nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *ConversionPair) XXX_Merge(src proto.Message) {
 | 
				
			||||||
 | 
						xxx_messageInfo_ConversionPair.Merge(m, src)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *ConversionPair) XXX_Size() int {
 | 
				
			||||||
 | 
						return m.Size()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *ConversionPair) XXX_DiscardUnknown() {
 | 
				
			||||||
 | 
						xxx_messageInfo_ConversionPair.DiscardUnknown(m)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var xxx_messageInfo_ConversionPair proto.InternalMessageInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						proto.RegisterType((*ConversionPair)(nil), "kava.evmutil.v1beta1.ConversionPair")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						proto.RegisterFile("kava/evmutil/v1beta1/conversion_pair.proto", fileDescriptor_e1396d08199817d0)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var fileDescriptor_e1396d08199817d0 = []byte{
 | 
				
			||||||
 | 
						// 264 bytes of a gzipped FileDescriptorProto
 | 
				
			||||||
 | 
						0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0xca, 0x4e, 0x2c, 0x4b,
 | 
				
			||||||
 | 
						0xd4, 0x4f, 0x2d, 0xcb, 0x2d, 0x2d, 0xc9, 0xcc, 0xd1, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34,
 | 
				
			||||||
 | 
						0xd4, 0x4f, 0xce, 0xcf, 0x2b, 0x4b, 0x2d, 0x2a, 0xce, 0xcc, 0xcf, 0x8b, 0x2f, 0x48, 0xcc, 0x2c,
 | 
				
			||||||
 | 
						0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x01, 0xa9, 0xd5, 0x83, 0xaa, 0xd5, 0x83, 0xaa,
 | 
				
			||||||
 | 
						0x95, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0x2b, 0xd0, 0x07, 0xb1, 0x20, 0x6a, 0x95, 0x6a, 0xb8,
 | 
				
			||||||
 | 
						0xf8, 0x9c, 0xe1, 0x86, 0x04, 0x24, 0x66, 0x16, 0x09, 0xf9, 0x71, 0x09, 0x81, 0xf4, 0xc7, 0xa7,
 | 
				
			||||||
 | 
						0x16, 0x25, 0x1b, 0x19, 0xc4, 0x27, 0xa6, 0xa4, 0x14, 0xa5, 0x16, 0x17, 0x4b, 0x30, 0x2a, 0x30,
 | 
				
			||||||
 | 
						0x6a, 0xf0, 0x38, 0x29, 0x3c, 0xba, 0x27, 0x2f, 0xe0, 0x9d, 0x58, 0x96, 0xe8, 0x1a, 0xe4, 0x6c,
 | 
				
			||||||
 | 
						0x64, 0xe0, 0x08, 0x91, 0xfb, 0x75, 0x4f, 0x9e, 0xc3, 0x23, 0xb5, 0xc2, 0xa9, 0xb2, 0x24, 0xb5,
 | 
				
			||||||
 | 
						0x38, 0x48, 0x00, 0xa4, 0xd7, 0x15, 0xa4, 0x15, 0x2a, 0x2b, 0x24, 0xc2, 0xc5, 0x9a, 0x92, 0x9a,
 | 
				
			||||||
 | 
						0x97, 0x9f, 0x2b, 0xc1, 0xa4, 0xc0, 0xa8, 0xc1, 0x19, 0x04, 0xe1, 0x58, 0xb1, 0x74, 0x2c, 0x90,
 | 
				
			||||||
 | 
						0x67, 0x70, 0xf2, 0x7e, 0xf0, 0x50, 0x8e, 0x71, 0xc5, 0x23, 0x39, 0xc6, 0x13, 0x8f, 0xe4, 0x18,
 | 
				
			||||||
 | 
						0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5,
 | 
				
			||||||
 | 
						0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0xd2, 0x4c, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce,
 | 
				
			||||||
 | 
						0xcf, 0xd5, 0x07, 0x19, 0xad, 0x9b, 0x93, 0x98, 0x54, 0x0c, 0x66, 0xe9, 0x57, 0xc0, 0x83, 0xa3,
 | 
				
			||||||
 | 
						0xa4, 0xb2, 0x20, 0xb5, 0x38, 0x89, 0x0d, 0xec, 0x23, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff,
 | 
				
			||||||
 | 
						0x60, 0x36, 0x37, 0x7f, 0x2b, 0x01, 0x00, 0x00,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *ConversionPair) VerboseEqual(that interface{}) error {
 | 
				
			||||||
 | 
						if that == nil {
 | 
				
			||||||
 | 
							if this == nil {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return fmt.Errorf("that == nil && this != nil")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						that1, ok := that.(*ConversionPair)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							that2, ok := that.(ConversionPair)
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								that1 = &that2
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return fmt.Errorf("that is not of type *ConversionPair")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if that1 == nil {
 | 
				
			||||||
 | 
							if this == nil {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return fmt.Errorf("that is type *ConversionPair but is nil && this != nil")
 | 
				
			||||||
 | 
						} else if this == nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("that is type *ConversionPair but is not nil && this == nil")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !bytes.Equal(this.KavaERC20Address, that1.KavaERC20Address) {
 | 
				
			||||||
 | 
							return fmt.Errorf("KavaERC20Address this(%v) Not Equal that(%v)", this.KavaERC20Address, that1.KavaERC20Address)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if this.Denom != that1.Denom {
 | 
				
			||||||
 | 
							return fmt.Errorf("Denom this(%v) Not Equal that(%v)", this.Denom, that1.Denom)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (this *ConversionPair) Equal(that interface{}) bool {
 | 
				
			||||||
 | 
						if that == nil {
 | 
				
			||||||
 | 
							return this == nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						that1, ok := that.(*ConversionPair)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							that2, ok := that.(ConversionPair)
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								that1 = &that2
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if that1 == nil {
 | 
				
			||||||
 | 
							return this == nil
 | 
				
			||||||
 | 
						} else if this == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !bytes.Equal(this.KavaERC20Address, that1.KavaERC20Address) {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if this.Denom != that1.Denom {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *ConversionPair) Marshal() (dAtA []byte, err error) {
 | 
				
			||||||
 | 
						size := m.Size()
 | 
				
			||||||
 | 
						dAtA = make([]byte, size)
 | 
				
			||||||
 | 
						n, err := m.MarshalToSizedBuffer(dAtA[:size])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return dAtA[:n], nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *ConversionPair) MarshalTo(dAtA []byte) (int, error) {
 | 
				
			||||||
 | 
						size := m.Size()
 | 
				
			||||||
 | 
						return m.MarshalToSizedBuffer(dAtA[:size])
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *ConversionPair) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 | 
				
			||||||
 | 
						i := len(dAtA)
 | 
				
			||||||
 | 
						_ = i
 | 
				
			||||||
 | 
						var l int
 | 
				
			||||||
 | 
						_ = l
 | 
				
			||||||
 | 
						if len(m.Denom) > 0 {
 | 
				
			||||||
 | 
							i -= len(m.Denom)
 | 
				
			||||||
 | 
							copy(dAtA[i:], m.Denom)
 | 
				
			||||||
 | 
							i = encodeVarintConversionPair(dAtA, i, uint64(len(m.Denom)))
 | 
				
			||||||
 | 
							i--
 | 
				
			||||||
 | 
							dAtA[i] = 0x12
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(m.KavaERC20Address) > 0 {
 | 
				
			||||||
 | 
							i -= len(m.KavaERC20Address)
 | 
				
			||||||
 | 
							copy(dAtA[i:], m.KavaERC20Address)
 | 
				
			||||||
 | 
							i = encodeVarintConversionPair(dAtA, i, uint64(len(m.KavaERC20Address)))
 | 
				
			||||||
 | 
							i--
 | 
				
			||||||
 | 
							dAtA[i] = 0xa
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return len(dAtA) - i, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func encodeVarintConversionPair(dAtA []byte, offset int, v uint64) int {
 | 
				
			||||||
 | 
						offset -= sovConversionPair(v)
 | 
				
			||||||
 | 
						base := offset
 | 
				
			||||||
 | 
						for v >= 1<<7 {
 | 
				
			||||||
 | 
							dAtA[offset] = uint8(v&0x7f | 0x80)
 | 
				
			||||||
 | 
							v >>= 7
 | 
				
			||||||
 | 
							offset++
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						dAtA[offset] = uint8(v)
 | 
				
			||||||
 | 
						return base
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *ConversionPair) Size() (n int) {
 | 
				
			||||||
 | 
						if m == nil {
 | 
				
			||||||
 | 
							return 0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var l int
 | 
				
			||||||
 | 
						_ = l
 | 
				
			||||||
 | 
						l = len(m.KavaERC20Address)
 | 
				
			||||||
 | 
						if l > 0 {
 | 
				
			||||||
 | 
							n += 1 + l + sovConversionPair(uint64(l))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						l = len(m.Denom)
 | 
				
			||||||
 | 
						if l > 0 {
 | 
				
			||||||
 | 
							n += 1 + l + sovConversionPair(uint64(l))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return n
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func sovConversionPair(x uint64) (n int) {
 | 
				
			||||||
 | 
						return (math_bits.Len64(x|1) + 6) / 7
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func sozConversionPair(x uint64) (n int) {
 | 
				
			||||||
 | 
						return sovConversionPair(uint64((x << 1) ^ uint64((int64(x) >> 63))))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *ConversionPair) Unmarshal(dAtA []byte) error {
 | 
				
			||||||
 | 
						l := len(dAtA)
 | 
				
			||||||
 | 
						iNdEx := 0
 | 
				
			||||||
 | 
						for iNdEx < l {
 | 
				
			||||||
 | 
							preIndex := iNdEx
 | 
				
			||||||
 | 
							var wire uint64
 | 
				
			||||||
 | 
							for shift := uint(0); ; shift += 7 {
 | 
				
			||||||
 | 
								if shift >= 64 {
 | 
				
			||||||
 | 
									return ErrIntOverflowConversionPair
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if iNdEx >= l {
 | 
				
			||||||
 | 
									return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								b := dAtA[iNdEx]
 | 
				
			||||||
 | 
								iNdEx++
 | 
				
			||||||
 | 
								wire |= uint64(b&0x7F) << shift
 | 
				
			||||||
 | 
								if b < 0x80 {
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							fieldNum := int32(wire >> 3)
 | 
				
			||||||
 | 
							wireType := int(wire & 0x7)
 | 
				
			||||||
 | 
							if wireType == 4 {
 | 
				
			||||||
 | 
								return fmt.Errorf("proto: ConversionPair: wiretype end group for non-group")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if fieldNum <= 0 {
 | 
				
			||||||
 | 
								return fmt.Errorf("proto: ConversionPair: illegal tag %d (wire type %d)", fieldNum, wire)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							switch fieldNum {
 | 
				
			||||||
 | 
							case 1:
 | 
				
			||||||
 | 
								if wireType != 2 {
 | 
				
			||||||
 | 
									return fmt.Errorf("proto: wrong wireType = %d for field KavaERC20Address", wireType)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var byteLen int
 | 
				
			||||||
 | 
								for shift := uint(0); ; shift += 7 {
 | 
				
			||||||
 | 
									if shift >= 64 {
 | 
				
			||||||
 | 
										return ErrIntOverflowConversionPair
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if iNdEx >= l {
 | 
				
			||||||
 | 
										return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									b := dAtA[iNdEx]
 | 
				
			||||||
 | 
									iNdEx++
 | 
				
			||||||
 | 
									byteLen |= int(b&0x7F) << shift
 | 
				
			||||||
 | 
									if b < 0x80 {
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if byteLen < 0 {
 | 
				
			||||||
 | 
									return ErrInvalidLengthConversionPair
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								postIndex := iNdEx + byteLen
 | 
				
			||||||
 | 
								if postIndex < 0 {
 | 
				
			||||||
 | 
									return ErrInvalidLengthConversionPair
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if postIndex > l {
 | 
				
			||||||
 | 
									return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								m.KavaERC20Address = append(m.KavaERC20Address[:0], dAtA[iNdEx:postIndex]...)
 | 
				
			||||||
 | 
								if m.KavaERC20Address == nil {
 | 
				
			||||||
 | 
									m.KavaERC20Address = []byte{}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								iNdEx = postIndex
 | 
				
			||||||
 | 
							case 2:
 | 
				
			||||||
 | 
								if wireType != 2 {
 | 
				
			||||||
 | 
									return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var stringLen uint64
 | 
				
			||||||
 | 
								for shift := uint(0); ; shift += 7 {
 | 
				
			||||||
 | 
									if shift >= 64 {
 | 
				
			||||||
 | 
										return ErrIntOverflowConversionPair
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if iNdEx >= l {
 | 
				
			||||||
 | 
										return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									b := dAtA[iNdEx]
 | 
				
			||||||
 | 
									iNdEx++
 | 
				
			||||||
 | 
									stringLen |= uint64(b&0x7F) << shift
 | 
				
			||||||
 | 
									if b < 0x80 {
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								intStringLen := int(stringLen)
 | 
				
			||||||
 | 
								if intStringLen < 0 {
 | 
				
			||||||
 | 
									return ErrInvalidLengthConversionPair
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								postIndex := iNdEx + intStringLen
 | 
				
			||||||
 | 
								if postIndex < 0 {
 | 
				
			||||||
 | 
									return ErrInvalidLengthConversionPair
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if postIndex > l {
 | 
				
			||||||
 | 
									return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								m.Denom = string(dAtA[iNdEx:postIndex])
 | 
				
			||||||
 | 
								iNdEx = postIndex
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								iNdEx = preIndex
 | 
				
			||||||
 | 
								skippy, err := skipConversionPair(dAtA[iNdEx:])
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (skippy < 0) || (iNdEx+skippy) < 0 {
 | 
				
			||||||
 | 
									return ErrInvalidLengthConversionPair
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (iNdEx + skippy) > l {
 | 
				
			||||||
 | 
									return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								iNdEx += skippy
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if iNdEx > l {
 | 
				
			||||||
 | 
							return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func skipConversionPair(dAtA []byte) (n int, err error) {
 | 
				
			||||||
 | 
						l := len(dAtA)
 | 
				
			||||||
 | 
						iNdEx := 0
 | 
				
			||||||
 | 
						depth := 0
 | 
				
			||||||
 | 
						for iNdEx < l {
 | 
				
			||||||
 | 
							var wire uint64
 | 
				
			||||||
 | 
							for shift := uint(0); ; shift += 7 {
 | 
				
			||||||
 | 
								if shift >= 64 {
 | 
				
			||||||
 | 
									return 0, ErrIntOverflowConversionPair
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if iNdEx >= l {
 | 
				
			||||||
 | 
									return 0, io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								b := dAtA[iNdEx]
 | 
				
			||||||
 | 
								iNdEx++
 | 
				
			||||||
 | 
								wire |= (uint64(b) & 0x7F) << shift
 | 
				
			||||||
 | 
								if b < 0x80 {
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							wireType := int(wire & 0x7)
 | 
				
			||||||
 | 
							switch wireType {
 | 
				
			||||||
 | 
							case 0:
 | 
				
			||||||
 | 
								for shift := uint(0); ; shift += 7 {
 | 
				
			||||||
 | 
									if shift >= 64 {
 | 
				
			||||||
 | 
										return 0, ErrIntOverflowConversionPair
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if iNdEx >= l {
 | 
				
			||||||
 | 
										return 0, io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									iNdEx++
 | 
				
			||||||
 | 
									if dAtA[iNdEx-1] < 0x80 {
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							case 1:
 | 
				
			||||||
 | 
								iNdEx += 8
 | 
				
			||||||
 | 
							case 2:
 | 
				
			||||||
 | 
								var length int
 | 
				
			||||||
 | 
								for shift := uint(0); ; shift += 7 {
 | 
				
			||||||
 | 
									if shift >= 64 {
 | 
				
			||||||
 | 
										return 0, ErrIntOverflowConversionPair
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if iNdEx >= l {
 | 
				
			||||||
 | 
										return 0, io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									b := dAtA[iNdEx]
 | 
				
			||||||
 | 
									iNdEx++
 | 
				
			||||||
 | 
									length |= (int(b) & 0x7F) << shift
 | 
				
			||||||
 | 
									if b < 0x80 {
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if length < 0 {
 | 
				
			||||||
 | 
									return 0, ErrInvalidLengthConversionPair
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								iNdEx += length
 | 
				
			||||||
 | 
							case 3:
 | 
				
			||||||
 | 
								depth++
 | 
				
			||||||
 | 
							case 4:
 | 
				
			||||||
 | 
								if depth == 0 {
 | 
				
			||||||
 | 
									return 0, ErrUnexpectedEndOfGroupConversionPair
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								depth--
 | 
				
			||||||
 | 
							case 5:
 | 
				
			||||||
 | 
								iNdEx += 4
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if iNdEx < 0 {
 | 
				
			||||||
 | 
								return 0, ErrInvalidLengthConversionPair
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if depth == 0 {
 | 
				
			||||||
 | 
								return iNdEx, nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0, io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						ErrInvalidLengthConversionPair        = fmt.Errorf("proto: negative length found during unmarshaling")
 | 
				
			||||||
 | 
						ErrIntOverflowConversionPair          = fmt.Errorf("proto: integer overflow")
 | 
				
			||||||
 | 
						ErrUnexpectedEndOfGroupConversionPair = fmt.Errorf("proto: unexpected end of group")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										233
									
								
								x/evmutil/types/conversion_pairs_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										233
									
								
								x/evmutil/types/conversion_pairs_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,233 @@
 | 
				
			|||||||
 | 
					package types_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/testutil"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/require"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestConversionPairValidate(t *testing.T) {
 | 
				
			||||||
 | 
						type errArgs struct {
 | 
				
			||||||
 | 
							expectPass bool
 | 
				
			||||||
 | 
							contains   string
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							name        string
 | 
				
			||||||
 | 
							giveAddress types.InternalEVMAddress
 | 
				
			||||||
 | 
							giveDenom   string
 | 
				
			||||||
 | 
							errArgs     errArgs
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"valid",
 | 
				
			||||||
 | 
								testutil.MustNewInternalEVMAddressFromString("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
 | 
				
			||||||
 | 
								"weth",
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - empty denom",
 | 
				
			||||||
 | 
								testutil.MustNewInternalEVMAddressFromString("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
 | 
				
			||||||
 | 
								"",
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "conversion pair denom invalid: invalid denom",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - zero address",
 | 
				
			||||||
 | 
								testutil.MustNewInternalEVMAddressFromString("0x0000000000000000000000000000000000000000"),
 | 
				
			||||||
 | 
								"weth",
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "address cannot be zero value",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range tests {
 | 
				
			||||||
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
 | 
								pair := types.NewConversionPair(tc.giveAddress, tc.giveDenom)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								err := pair.Validate()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if tc.errArgs.expectPass {
 | 
				
			||||||
 | 
									require.NoError(t, err)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									require.Error(t, err)
 | 
				
			||||||
 | 
									require.Contains(t, err.Error(), tc.errArgs.contains)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestConversionPairValidate_Direct(t *testing.T) {
 | 
				
			||||||
 | 
						type errArgs struct {
 | 
				
			||||||
 | 
							expectPass bool
 | 
				
			||||||
 | 
							contains   string
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							name     string
 | 
				
			||||||
 | 
							givePair types.ConversionPair
 | 
				
			||||||
 | 
							errArgs  errArgs
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"valid",
 | 
				
			||||||
 | 
								types.ConversionPair{
 | 
				
			||||||
 | 
									KavaERC20Address: testutil.MustNewInternalEVMAddressFromString("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2").Bytes(),
 | 
				
			||||||
 | 
									Denom:            "weth",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - length",
 | 
				
			||||||
 | 
								types.ConversionPair{
 | 
				
			||||||
 | 
									KavaERC20Address: []byte{1},
 | 
				
			||||||
 | 
									Denom:            "weth",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "address length is 1 but expected 20",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range tests {
 | 
				
			||||||
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
 | 
								err := tc.givePair.Validate()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if tc.errArgs.expectPass {
 | 
				
			||||||
 | 
									require.NoError(t, err)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									require.Error(t, err)
 | 
				
			||||||
 | 
									require.Contains(t, err.Error(), tc.errArgs.contains)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestConversionPair_GetAddress(t *testing.T) {
 | 
				
			||||||
 | 
						addr := testutil.MustNewInternalEVMAddressFromString("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pair := types.NewConversionPair(
 | 
				
			||||||
 | 
							addr,
 | 
				
			||||||
 | 
							"weth",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						require.Equal(t, types.HexBytes(addr.Bytes()), pair.KavaERC20Address, "struct address should match input bytes")
 | 
				
			||||||
 | 
						require.Equal(t, addr, pair.GetAddress(), "get internal address should match input bytes")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestConversionPairs_Validate(t *testing.T) {
 | 
				
			||||||
 | 
						type errArgs struct {
 | 
				
			||||||
 | 
							expectPass bool
 | 
				
			||||||
 | 
							contains   string
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							name      string
 | 
				
			||||||
 | 
							givePairs types.ConversionPairs
 | 
				
			||||||
 | 
							errArgs   errArgs
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"valid",
 | 
				
			||||||
 | 
								types.NewConversionPairs(
 | 
				
			||||||
 | 
									types.NewConversionPair(
 | 
				
			||||||
 | 
										testutil.MustNewInternalEVMAddressFromString("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
 | 
				
			||||||
 | 
										"weth",
 | 
				
			||||||
 | 
									),
 | 
				
			||||||
 | 
									types.NewConversionPair(
 | 
				
			||||||
 | 
										testutil.MustNewInternalEVMAddressFromString("0x000000000000000000000000000000000000000A"),
 | 
				
			||||||
 | 
										"kava",
 | 
				
			||||||
 | 
									),
 | 
				
			||||||
 | 
									types.NewConversionPair(
 | 
				
			||||||
 | 
										testutil.MustNewInternalEVMAddressFromString("0x000000000000000000000000000000000000000B"),
 | 
				
			||||||
 | 
										"usdc",
 | 
				
			||||||
 | 
									),
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - duplicate address",
 | 
				
			||||||
 | 
								types.NewConversionPairs(
 | 
				
			||||||
 | 
									types.NewConversionPair(
 | 
				
			||||||
 | 
										testutil.MustNewInternalEVMAddressFromString("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
 | 
				
			||||||
 | 
										"weth",
 | 
				
			||||||
 | 
									),
 | 
				
			||||||
 | 
									types.NewConversionPair(
 | 
				
			||||||
 | 
										testutil.MustNewInternalEVMAddressFromString("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
 | 
				
			||||||
 | 
										"kava",
 | 
				
			||||||
 | 
									),
 | 
				
			||||||
 | 
									types.NewConversionPair(
 | 
				
			||||||
 | 
										testutil.MustNewInternalEVMAddressFromString("0x000000000000000000000000000000000000000B"),
 | 
				
			||||||
 | 
										"usdc",
 | 
				
			||||||
 | 
									),
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "found duplicate enabled conversion pair internal ERC20 address",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - duplicate denom",
 | 
				
			||||||
 | 
								types.NewConversionPairs(
 | 
				
			||||||
 | 
									types.NewConversionPair(
 | 
				
			||||||
 | 
										testutil.MustNewInternalEVMAddressFromString("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
 | 
				
			||||||
 | 
										"weth",
 | 
				
			||||||
 | 
									),
 | 
				
			||||||
 | 
									types.NewConversionPair(
 | 
				
			||||||
 | 
										testutil.MustNewInternalEVMAddressFromString("0x000000000000000000000000000000000000000A"),
 | 
				
			||||||
 | 
										"kava",
 | 
				
			||||||
 | 
									),
 | 
				
			||||||
 | 
									types.NewConversionPair(
 | 
				
			||||||
 | 
										testutil.MustNewInternalEVMAddressFromString("0x000000000000000000000000000000000000000B"),
 | 
				
			||||||
 | 
										"kava",
 | 
				
			||||||
 | 
									),
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "found duplicate enabled conversion pair denom kava",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - invalid pair",
 | 
				
			||||||
 | 
								types.NewConversionPairs(
 | 
				
			||||||
 | 
									types.NewConversionPair(
 | 
				
			||||||
 | 
										testutil.MustNewInternalEVMAddressFromString("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
 | 
				
			||||||
 | 
										"weth",
 | 
				
			||||||
 | 
									),
 | 
				
			||||||
 | 
									types.NewConversionPair(
 | 
				
			||||||
 | 
										testutil.MustNewInternalEVMAddressFromString("0x0000000000000000000000000000000000000000"),
 | 
				
			||||||
 | 
										"usdc",
 | 
				
			||||||
 | 
									),
 | 
				
			||||||
 | 
									types.NewConversionPair(
 | 
				
			||||||
 | 
										testutil.MustNewInternalEVMAddressFromString("0x000000000000000000000000000000000000000B"),
 | 
				
			||||||
 | 
										"kava",
 | 
				
			||||||
 | 
									),
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "address cannot be zero value",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range tests {
 | 
				
			||||||
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
 | 
								err := tc.givePairs.Validate()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if tc.errArgs.expectPass {
 | 
				
			||||||
 | 
									require.NoError(t, err)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									require.Error(t, err)
 | 
				
			||||||
 | 
									require.Contains(t, err.Error(), tc.errArgs.contains)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										14
									
								
								x/evmutil/types/errors.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								x/evmutil/types/errors.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					package types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// errors
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						ErrABIPack                 = sdkerrors.Register(ModuleName, 2, "contract ABI pack failed")
 | 
				
			||||||
 | 
						ErrEVMCall                 = sdkerrors.Register(ModuleName, 3, "EVM call unexpected error")
 | 
				
			||||||
 | 
						ErrConversionNotEnabled    = sdkerrors.Register(ModuleName, 4, "ERC20 token not enabled to convert to sdk.Coin")
 | 
				
			||||||
 | 
						ErrBalanceInvariance       = sdkerrors.Register(ModuleName, 5, "post EVM transfer balance invariant failed")
 | 
				
			||||||
 | 
						ErrUnexpectedContractEvent = sdkerrors.Register(ModuleName, 6, "unexpected contract event")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										18
									
								
								x/evmutil/types/events.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								x/evmutil/types/events.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					package types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Events for the module
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						AttributeValueCategory = ModuleName
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Event Types
 | 
				
			||||||
 | 
						EventTypeConvertERC20ToCoin = "convert_erc20_to_coin"
 | 
				
			||||||
 | 
						EventTypeConvertCoinToERC20 = "convert_coin_to_erc20"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Event Attributes - Common
 | 
				
			||||||
 | 
						AttributeKeyReceiver = "receiver"
 | 
				
			||||||
 | 
						AttributeKeyAmount   = "amount"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Event Attributes - Conversions
 | 
				
			||||||
 | 
						AttributeKeyInitiator    = "initiator"
 | 
				
			||||||
 | 
						AttributeKeyERC20Address = "erc20_address"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@ -1,19 +1,32 @@
 | 
				
			|||||||
package types
 | 
					package types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/core"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/core/vm"
 | 
				
			||||||
	evmtypes "github.com/tharsis/ethermint/x/evm/types"
 | 
						evmtypes "github.com/tharsis/ethermint/x/evm/types"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AccountKeeper defines the expected account keeper interface
 | 
					// AccountKeeper defines the expected account keeper interface
 | 
				
			||||||
type AccountKeeper interface {
 | 
					type AccountKeeper interface {
 | 
				
			||||||
	GetModuleAddress(moduleName string) sdk.AccAddress
 | 
						GetModuleAddress(moduleName string) sdk.AccAddress
 | 
				
			||||||
 | 
						GetSequence(sdk.Context, sdk.AccAddress) (uint64, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BankKeeper defines the expected bank keeper interface
 | 
					// BankKeeper defines the expected bank keeper interface
 | 
				
			||||||
type BankKeeper interface {
 | 
					type BankKeeper interface {
 | 
				
			||||||
	evmtypes.BankKeeper
 | 
						evmtypes.BankKeeper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						GetSupply(ctx sdk.Context, denom string) sdk.Coin
 | 
				
			||||||
	SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
 | 
						SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
 | 
				
			||||||
	SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error
 | 
						SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// EvmKeeper defines the expected interface needed to make EVM transactions.
 | 
				
			||||||
 | 
					type EvmKeeper interface {
 | 
				
			||||||
 | 
						// This is actually a gRPC query method
 | 
				
			||||||
 | 
						EstimateGas(ctx context.Context, req *evmtypes.EthCallRequest) (*evmtypes.EstimateGasResponse, error)
 | 
				
			||||||
 | 
						ApplyMessage(ctx sdk.Context, msg core.Message, tracer vm.EVMLogger, commit bool) (*evmtypes.MsgEthereumTxResponse, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -7,9 +7,10 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewGenesisState returns a new genesis state object for the module.
 | 
					// NewGenesisState returns a new genesis state object for the module.
 | 
				
			||||||
func NewGenesisState(accounts []Account) *GenesisState {
 | 
					func NewGenesisState(accounts []Account, params Params) *GenesisState {
 | 
				
			||||||
	return &GenesisState{
 | 
						return &GenesisState{
 | 
				
			||||||
		Accounts: accounts,
 | 
							Accounts: accounts,
 | 
				
			||||||
 | 
							Params:   params,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -17,6 +18,7 @@ func NewGenesisState(accounts []Account) *GenesisState {
 | 
				
			|||||||
func DefaultGenesisState() *GenesisState {
 | 
					func DefaultGenesisState() *GenesisState {
 | 
				
			||||||
	return NewGenesisState(
 | 
						return NewGenesisState(
 | 
				
			||||||
		[]Account{},
 | 
							[]Account{},
 | 
				
			||||||
 | 
							DefaultParams(),
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -34,6 +36,11 @@ func (gs GenesisState) Validate() error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		seenAccounts[account.Address.String()] = true
 | 
							seenAccounts[account.Address.String()] = true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := gs.Params.Validate(); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,7 @@
 | 
				
			|||||||
package types
 | 
					package types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						bytes "bytes"
 | 
				
			||||||
	fmt "fmt"
 | 
						fmt "fmt"
 | 
				
			||||||
	_ "github.com/cosmos/cosmos-proto"
 | 
						_ "github.com/cosmos/cosmos-proto"
 | 
				
			||||||
	github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types"
 | 
						github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
@ -28,6 +29,8 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
 | 
				
			|||||||
// GenesisState defines the evmutil module's genesis state.
 | 
					// GenesisState defines the evmutil module's genesis state.
 | 
				
			||||||
type GenesisState struct {
 | 
					type GenesisState struct {
 | 
				
			||||||
	Accounts []Account `protobuf:"bytes,1,rep,name=accounts,proto3" json:"accounts"`
 | 
						Accounts []Account `protobuf:"bytes,1,rep,name=accounts,proto3" json:"accounts"`
 | 
				
			||||||
 | 
						// params defines all the parameters of the module.
 | 
				
			||||||
 | 
						Params Params `protobuf:"bytes,2,opt,name=params,proto3" json:"params"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *GenesisState) Reset()         { *m = GenesisState{} }
 | 
					func (m *GenesisState) Reset()         { *m = GenesisState{} }
 | 
				
			||||||
@ -103,9 +106,57 @@ func (m *Account) XXX_DiscardUnknown() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var xxx_messageInfo_Account proto.InternalMessageInfo
 | 
					var xxx_messageInfo_Account proto.InternalMessageInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Params defines the evmutil module params
 | 
				
			||||||
 | 
					type Params struct {
 | 
				
			||||||
 | 
						// enabled_conversion_pairs defines the list of conversion pairs allowed to be
 | 
				
			||||||
 | 
						// converted between Kava ERC20 and sdk.Coin
 | 
				
			||||||
 | 
						EnabledConversionPairs ConversionPairs `protobuf:"bytes,4,rep,name=enabled_conversion_pairs,json=enabledConversionPairs,proto3,castrepeated=ConversionPairs" json:"enabled_conversion_pairs"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Params) Reset()         { *m = Params{} }
 | 
				
			||||||
 | 
					func (m *Params) String() string { return proto.CompactTextString(m) }
 | 
				
			||||||
 | 
					func (*Params) ProtoMessage()    {}
 | 
				
			||||||
 | 
					func (*Params) Descriptor() ([]byte, []int) {
 | 
				
			||||||
 | 
						return fileDescriptor_d916ab97b8e628c2, []int{2}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *Params) XXX_Unmarshal(b []byte) error {
 | 
				
			||||||
 | 
						return m.Unmarshal(b)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 | 
				
			||||||
 | 
						if deterministic {
 | 
				
			||||||
 | 
							return xxx_messageInfo_Params.Marshal(b, m, deterministic)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							b = b[:cap(b)]
 | 
				
			||||||
 | 
							n, err := m.MarshalToSizedBuffer(b)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return b[:n], nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *Params) XXX_Merge(src proto.Message) {
 | 
				
			||||||
 | 
						xxx_messageInfo_Params.Merge(m, src)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *Params) XXX_Size() int {
 | 
				
			||||||
 | 
						return m.Size()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *Params) XXX_DiscardUnknown() {
 | 
				
			||||||
 | 
						xxx_messageInfo_Params.DiscardUnknown(m)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var xxx_messageInfo_Params proto.InternalMessageInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Params) GetEnabledConversionPairs() ConversionPairs {
 | 
				
			||||||
 | 
						if m != nil {
 | 
				
			||||||
 | 
							return m.EnabledConversionPairs
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	proto.RegisterType((*GenesisState)(nil), "kava.evmutil.v1beta1.GenesisState")
 | 
						proto.RegisterType((*GenesisState)(nil), "kava.evmutil.v1beta1.GenesisState")
 | 
				
			||||||
	proto.RegisterType((*Account)(nil), "kava.evmutil.v1beta1.Account")
 | 
						proto.RegisterType((*Account)(nil), "kava.evmutil.v1beta1.Account")
 | 
				
			||||||
 | 
						proto.RegisterType((*Params)(nil), "kava.evmutil.v1beta1.Params")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
@ -113,30 +164,231 @@ func init() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var fileDescriptor_d916ab97b8e628c2 = []byte{
 | 
					var fileDescriptor_d916ab97b8e628c2 = []byte{
 | 
				
			||||||
	// 331 bytes of a gzipped FileDescriptorProto
 | 
						// 434 bytes of a gzipped FileDescriptorProto
 | 
				
			||||||
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xca, 0x4e, 0x2c, 0x4b,
 | 
						0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x41, 0x8b, 0xd3, 0x40,
 | 
				
			||||||
	0xd4, 0x4f, 0x2d, 0xcb, 0x2d, 0x2d, 0xc9, 0xcc, 0xd1, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34,
 | 
						0x14, 0xc7, 0x33, 0x5a, 0x5a, 0x9d, 0x5d, 0x10, 0xe2, 0xa2, 0x71, 0xd1, 0xc9, 0x52, 0x44, 0xaa,
 | 
				
			||||||
	0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12,
 | 
						0x90, 0x84, 0x5d, 0x6f, 0x45, 0x90, 0xc6, 0x83, 0x16, 0x2f, 0x25, 0x82, 0x07, 0x2f, 0x65, 0x92,
 | 
				
			||||||
	0x01, 0xa9, 0xd1, 0x83, 0xaa, 0xd1, 0x83, 0xaa, 0x91, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0x2b,
 | 
						0x0c, 0x31, 0x34, 0x99, 0x09, 0x99, 0x69, 0xb4, 0x47, 0x6f, 0x1e, 0xf5, 0x1b, 0x78, 0x14, 0xcf,
 | 
				
			||||||
	0xd0, 0x07, 0xb1, 0x20, 0x6a, 0xa5, 0x24, 0x93, 0xf3, 0x8b, 0x73, 0xf3, 0x8b, 0xe3, 0x21, 0x12,
 | 
						0xfd, 0x10, 0x05, 0x2f, 0xa5, 0x27, 0xf1, 0x50, 0x6b, 0xfa, 0x2d, 0x3c, 0x49, 0x32, 0xd3, 0xa2,
 | 
				
			||||||
	0x10, 0x0e, 0x44, 0x4a, 0x29, 0x94, 0x8b, 0xc7, 0x1d, 0x62, 0x6e, 0x70, 0x49, 0x62, 0x49, 0xaa,
 | 
						0x25, 0x87, 0x3d, 0x75, 0xfa, 0xe6, 0xf7, 0x7f, 0xef, 0xff, 0x7f, 0x19, 0xd8, 0x9d, 0xe0, 0x02,
 | 
				
			||||||
	0x90, 0x3d, 0x17, 0x47, 0x62, 0x72, 0x72, 0x7e, 0x69, 0x5e, 0x49, 0xb1, 0x04, 0xa3, 0x02, 0xb3,
 | 
						0x3b, 0xa4, 0x48, 0xa7, 0x22, 0x4e, 0x9c, 0xe2, 0xdc, 0x27, 0x02, 0x9f, 0x3b, 0x11, 0xa1, 0x84,
 | 
				
			||||||
	0x06, 0xb7, 0x91, 0xac, 0x1e, 0x36, 0x9b, 0xf4, 0x1c, 0x21, 0xaa, 0x9c, 0x58, 0x4e, 0xdc, 0x93,
 | 
						0xc7, 0xdc, 0xce, 0x72, 0x26, 0x98, 0x7e, 0x52, 0x31, 0xb6, 0x62, 0x6c, 0xc5, 0x9c, 0x9e, 0x44,
 | 
				
			||||||
	0x67, 0x08, 0x82, 0x6b, 0xb2, 0x62, 0xe9, 0x58, 0x20, 0xcf, 0xa0, 0x74, 0x9e, 0x91, 0x8b, 0x1d,
 | 
						0x2c, 0x62, 0x35, 0xe0, 0x54, 0x27, 0xc9, 0x9e, 0xde, 0x09, 0x18, 0x4f, 0x19, 0x1f, 0xcb, 0x0b,
 | 
				
			||||||
	0xaa, 0x42, 0x28, 0x89, 0x8b, 0x3d, 0x31, 0x25, 0xa5, 0x28, 0xb5, 0x18, 0x64, 0x22, 0xa3, 0x06,
 | 
						0xf9, 0x47, 0x5d, 0x3d, 0x6a, 0x1c, 0x15, 0x30, 0x5a, 0x90, 0x9c, 0xc7, 0x8c, 0x8e, 0x33, 0x1c,
 | 
				
			||||||
	0x8f, 0x93, 0xc7, 0xaf, 0x7b, 0xf2, 0xba, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9,
 | 
						0xe7, 0x92, 0xed, 0x7e, 0x06, 0xf0, 0xf8, 0xb9, 0x34, 0xf1, 0x4a, 0x60, 0x41, 0xf4, 0xa7, 0xf0,
 | 
				
			||||||
	0xb9, 0x50, 0x07, 0x41, 0x29, 0xdd, 0xe2, 0x94, 0x6c, 0xfd, 0x92, 0xca, 0x82, 0xd4, 0x62, 0x90,
 | 
						0x1a, 0x0e, 0x02, 0x36, 0xa5, 0x82, 0x1b, 0xe0, 0xec, 0x6a, 0xef, 0xe8, 0xe2, 0x9e, 0xdd, 0x64,
 | 
				
			||||||
	0x15, 0x8e, 0x10, 0x8d, 0x97, 0xb6, 0xe8, 0x0a, 0x43, 0x9d, 0x0d, 0x15, 0x71, 0xaa, 0x2c, 0x49,
 | 
						0xcb, 0x1e, 0x48, 0xca, 0x6d, 0x2d, 0xd6, 0xa6, 0xe6, 0xed, 0x45, 0x7a, 0x1f, 0xb6, 0x33, 0x9c,
 | 
				
			||||||
	0x2d, 0x0e, 0x82, 0x19, 0x2c, 0x14, 0xc6, 0xc5, 0x9e, 0x94, 0x98, 0x93, 0x98, 0x97, 0x9c, 0x2a,
 | 
						0xe3, 0x94, 0x1b, 0x57, 0xce, 0x40, 0xef, 0xe8, 0xe2, 0x6e, 0xb3, 0x7c, 0x54, 0x33, 0x4a, 0xad,
 | 
				
			||||||
	0xc1, 0xa4, 0xc0, 0xa8, 0xc1, 0xe9, 0x64, 0x03, 0x72, 0xd6, 0xad, 0x7b, 0xf2, 0x6a, 0x44, 0xd8,
 | 
						0x14, 0xfd, 0xd6, 0xc7, 0x2f, 0xa6, 0xd6, 0xfd, 0x0e, 0x60, 0x47, 0x75, 0xd7, 0x7d, 0xd8, 0xc1,
 | 
				
			||||||
	0xe3, 0x99, 0x57, 0x72, 0x69, 0x8b, 0x2e, 0x17, 0xd4, 0x02, 0xcf, 0xbc, 0x92, 0x20, 0x98, 0x61,
 | 
						0x61, 0x98, 0x13, 0x5e, 0xb9, 0x01, 0xbd, 0x63, 0xf7, 0xc5, 0x9f, 0xb5, 0x69, 0x45, 0xb1, 0x78,
 | 
				
			||||||
	0x56, 0x1c, 0x20, 0xdf, 0xbc, 0x58, 0x20, 0xcf, 0xe0, 0xe4, 0x7c, 0xe2, 0x91, 0x1c, 0xe3, 0x85,
 | 
						0x3b, 0xf5, 0xed, 0x80, 0xa5, 0x2a, 0xb9, 0xfa, 0xb1, 0x78, 0x38, 0x71, 0xc4, 0x2c, 0x23, 0xbc,
 | 
				
			||||||
	0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3,
 | 
						0xb2, 0x37, 0x90, 0xc2, 0xd5, 0xdc, 0xba, 0xa9, 0xf6, 0xa3, 0x2a, 0xee, 0x4c, 0x10, 0xee, 0xed,
 | 
				
			||||||
	0x8d, 0xc7, 0x72, 0x0c, 0x51, 0x9a, 0x48, 0x56, 0x80, 0x82, 0x4a, 0x37, 0x27, 0x31, 0xa9, 0x18,
 | 
						0x1a, 0xeb, 0xaf, 0x61, 0xc7, 0xc7, 0x09, 0xa6, 0x01, 0xa9, 0x2d, 0x5f, 0x77, 0x9f, 0x54, 0xa6,
 | 
				
			||||||
	0xcc, 0xd2, 0xaf, 0x80, 0x47, 0x22, 0xd8, 0xa6, 0x24, 0x36, 0x70, 0xa0, 0x1b, 0x03, 0x02, 0x00,
 | 
						0x7e, 0xae, 0xcd, 0x07, 0x97, 0x98, 0x33, 0xa4, 0x62, 0x35, 0xb7, 0xa0, 0x1a, 0x30, 0xa4, 0xc2,
 | 
				
			||||||
	0x00, 0xff, 0xff, 0x21, 0x8b, 0xca, 0xd4, 0xe1, 0x01, 0x00, 0x00,
 | 
						0xdb, 0x35, 0x53, 0x69, 0x3e, 0x00, 0xd8, 0x96, 0x61, 0xf5, 0x77, 0xd0, 0x20, 0x14, 0xfb, 0x09,
 | 
				
			||||||
 | 
						0x09, 0xc7, 0x07, 0x5f, 0x83, 0x1b, 0xad, 0x7a, 0xd7, 0xf7, 0x9b, 0x97, 0xf5, 0x6c, 0x4f, 0x8f,
 | 
				
			||||||
 | 
						0x70, 0x9c, 0xbb, 0xb7, 0x2b, 0x7f, 0xdf, 0x7e, 0x99, 0x37, 0xfe, 0xaf, 0x73, 0xef, 0x96, 0x6a,
 | 
				
			||||||
 | 
						0x7f, 0x50, 0x77, 0x5f, 0x6e, 0x7e, 0x23, 0xf0, 0xb5, 0x44, 0x60, 0x51, 0x22, 0xb0, 0x2c, 0x11,
 | 
				
			||||||
 | 
						0xd8, 0x94, 0x08, 0x7c, 0xda, 0x22, 0x6d, 0xb9, 0x45, 0xda, 0x8f, 0x2d, 0xd2, 0xde, 0x3c, 0xfc,
 | 
				
			||||||
 | 
						0x27, 0x6a, 0x65, 0xc1, 0x4a, 0xb0, 0xcf, 0xeb, 0x93, 0xf3, 0x7e, 0xff, 0x94, 0xea, 0xc4, 0x7e,
 | 
				
			||||||
 | 
						0xbb, 0x7e, 0x39, 0x8f, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xd6, 0x08, 0x73, 0x42, 0xd2, 0x02,
 | 
				
			||||||
 | 
						0x00, 0x00,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *GenesisState) VerboseEqual(that interface{}) error {
 | 
				
			||||||
 | 
						if that == nil {
 | 
				
			||||||
 | 
							if this == nil {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return fmt.Errorf("that == nil && this != nil")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						that1, ok := that.(*GenesisState)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							that2, ok := that.(GenesisState)
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								that1 = &that2
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return fmt.Errorf("that is not of type *GenesisState")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if that1 == nil {
 | 
				
			||||||
 | 
							if this == nil {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return fmt.Errorf("that is type *GenesisState but is nil && this != nil")
 | 
				
			||||||
 | 
						} else if this == nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("that is type *GenesisState but is not nil && this == nil")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(this.Accounts) != len(that1.Accounts) {
 | 
				
			||||||
 | 
							return fmt.Errorf("Accounts this(%v) Not Equal that(%v)", len(this.Accounts), len(that1.Accounts))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for i := range this.Accounts {
 | 
				
			||||||
 | 
							if !this.Accounts[i].Equal(&that1.Accounts[i]) {
 | 
				
			||||||
 | 
								return fmt.Errorf("Accounts this[%v](%v) Not Equal that[%v](%v)", i, this.Accounts[i], i, that1.Accounts[i])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !this.Params.Equal(&that1.Params) {
 | 
				
			||||||
 | 
							return fmt.Errorf("Params this(%v) Not Equal that(%v)", this.Params, that1.Params)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (this *GenesisState) Equal(that interface{}) bool {
 | 
				
			||||||
 | 
						if that == nil {
 | 
				
			||||||
 | 
							return this == nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						that1, ok := that.(*GenesisState)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							that2, ok := that.(GenesisState)
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								that1 = &that2
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if that1 == nil {
 | 
				
			||||||
 | 
							return this == nil
 | 
				
			||||||
 | 
						} else if this == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(this.Accounts) != len(that1.Accounts) {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for i := range this.Accounts {
 | 
				
			||||||
 | 
							if !this.Accounts[i].Equal(&that1.Accounts[i]) {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !this.Params.Equal(&that1.Params) {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (this *Account) VerboseEqual(that interface{}) error {
 | 
				
			||||||
 | 
						if that == nil {
 | 
				
			||||||
 | 
							if this == nil {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return fmt.Errorf("that == nil && this != nil")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						that1, ok := that.(*Account)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							that2, ok := that.(Account)
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								that1 = &that2
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return fmt.Errorf("that is not of type *Account")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if that1 == nil {
 | 
				
			||||||
 | 
							if this == nil {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return fmt.Errorf("that is type *Account but is nil && this != nil")
 | 
				
			||||||
 | 
						} else if this == nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("that is type *Account but is not nil && this == nil")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !bytes.Equal(this.Address, that1.Address) {
 | 
				
			||||||
 | 
							return fmt.Errorf("Address this(%v) Not Equal that(%v)", this.Address, that1.Address)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !this.Balance.Equal(that1.Balance) {
 | 
				
			||||||
 | 
							return fmt.Errorf("Balance this(%v) Not Equal that(%v)", this.Balance, that1.Balance)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (this *Account) Equal(that interface{}) bool {
 | 
				
			||||||
 | 
						if that == nil {
 | 
				
			||||||
 | 
							return this == nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						that1, ok := that.(*Account)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							that2, ok := that.(Account)
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								that1 = &that2
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if that1 == nil {
 | 
				
			||||||
 | 
							return this == nil
 | 
				
			||||||
 | 
						} else if this == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !bytes.Equal(this.Address, that1.Address) {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !this.Balance.Equal(that1.Balance) {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (this *Params) VerboseEqual(that interface{}) error {
 | 
				
			||||||
 | 
						if that == nil {
 | 
				
			||||||
 | 
							if this == nil {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return fmt.Errorf("that == nil && this != nil")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						that1, ok := that.(*Params)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							that2, ok := that.(Params)
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								that1 = &that2
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return fmt.Errorf("that is not of type *Params")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if that1 == nil {
 | 
				
			||||||
 | 
							if this == nil {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return fmt.Errorf("that is type *Params but is nil && this != nil")
 | 
				
			||||||
 | 
						} else if this == nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("that is type *Params but is not nil && this == nil")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(this.EnabledConversionPairs) != len(that1.EnabledConversionPairs) {
 | 
				
			||||||
 | 
							return fmt.Errorf("EnabledConversionPairs this(%v) Not Equal that(%v)", len(this.EnabledConversionPairs), len(that1.EnabledConversionPairs))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for i := range this.EnabledConversionPairs {
 | 
				
			||||||
 | 
							if !this.EnabledConversionPairs[i].Equal(&that1.EnabledConversionPairs[i]) {
 | 
				
			||||||
 | 
								return fmt.Errorf("EnabledConversionPairs this[%v](%v) Not Equal that[%v](%v)", i, this.EnabledConversionPairs[i], i, that1.EnabledConversionPairs[i])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (this *Params) Equal(that interface{}) bool {
 | 
				
			||||||
 | 
						if that == nil {
 | 
				
			||||||
 | 
							return this == nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						that1, ok := that.(*Params)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							that2, ok := that.(Params)
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								that1 = &that2
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if that1 == nil {
 | 
				
			||||||
 | 
							return this == nil
 | 
				
			||||||
 | 
						} else if this == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(this.EnabledConversionPairs) != len(that1.EnabledConversionPairs) {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for i := range this.EnabledConversionPairs {
 | 
				
			||||||
 | 
							if !this.EnabledConversionPairs[i].Equal(&that1.EnabledConversionPairs[i]) {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
func (m *GenesisState) Marshal() (dAtA []byte, err error) {
 | 
					func (m *GenesisState) Marshal() (dAtA []byte, err error) {
 | 
				
			||||||
	size := m.Size()
 | 
						size := m.Size()
 | 
				
			||||||
	dAtA = make([]byte, size)
 | 
						dAtA = make([]byte, size)
 | 
				
			||||||
@ -157,6 +409,16 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 | 
				
			|||||||
	_ = i
 | 
						_ = i
 | 
				
			||||||
	var l int
 | 
						var l int
 | 
				
			||||||
	_ = l
 | 
						_ = l
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							size, err := m.Params.MarshalToSizedBuffer(dAtA[:i])
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return 0, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							i -= size
 | 
				
			||||||
 | 
							i = encodeVarintGenesis(dAtA, i, uint64(size))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						i--
 | 
				
			||||||
 | 
						dAtA[i] = 0x12
 | 
				
			||||||
	if len(m.Accounts) > 0 {
 | 
						if len(m.Accounts) > 0 {
 | 
				
			||||||
		for iNdEx := len(m.Accounts) - 1; iNdEx >= 0; iNdEx-- {
 | 
							for iNdEx := len(m.Accounts) - 1; iNdEx >= 0; iNdEx-- {
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
@ -214,6 +476,43 @@ func (m *Account) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 | 
				
			|||||||
	return len(dAtA) - i, nil
 | 
						return len(dAtA) - i, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Params) Marshal() (dAtA []byte, err error) {
 | 
				
			||||||
 | 
						size := m.Size()
 | 
				
			||||||
 | 
						dAtA = make([]byte, size)
 | 
				
			||||||
 | 
						n, err := m.MarshalToSizedBuffer(dAtA[:size])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return dAtA[:n], nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Params) MarshalTo(dAtA []byte) (int, error) {
 | 
				
			||||||
 | 
						size := m.Size()
 | 
				
			||||||
 | 
						return m.MarshalToSizedBuffer(dAtA[:size])
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 | 
				
			||||||
 | 
						i := len(dAtA)
 | 
				
			||||||
 | 
						_ = i
 | 
				
			||||||
 | 
						var l int
 | 
				
			||||||
 | 
						_ = l
 | 
				
			||||||
 | 
						if len(m.EnabledConversionPairs) > 0 {
 | 
				
			||||||
 | 
							for iNdEx := len(m.EnabledConversionPairs) - 1; iNdEx >= 0; iNdEx-- {
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									size, err := m.EnabledConversionPairs[iNdEx].MarshalToSizedBuffer(dAtA[:i])
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										return 0, err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									i -= size
 | 
				
			||||||
 | 
									i = encodeVarintGenesis(dAtA, i, uint64(size))
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								i--
 | 
				
			||||||
 | 
								dAtA[i] = 0x22
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return len(dAtA) - i, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int {
 | 
					func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int {
 | 
				
			||||||
	offset -= sovGenesis(v)
 | 
						offset -= sovGenesis(v)
 | 
				
			||||||
	base := offset
 | 
						base := offset
 | 
				
			||||||
@ -237,6 +536,8 @@ func (m *GenesisState) Size() (n int) {
 | 
				
			|||||||
			n += 1 + l + sovGenesis(uint64(l))
 | 
								n += 1 + l + sovGenesis(uint64(l))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						l = m.Params.Size()
 | 
				
			||||||
 | 
						n += 1 + l + sovGenesis(uint64(l))
 | 
				
			||||||
	return n
 | 
						return n
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -255,6 +556,21 @@ func (m *Account) Size() (n int) {
 | 
				
			|||||||
	return n
 | 
						return n
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Params) Size() (n int) {
 | 
				
			||||||
 | 
						if m == nil {
 | 
				
			||||||
 | 
							return 0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var l int
 | 
				
			||||||
 | 
						_ = l
 | 
				
			||||||
 | 
						if len(m.EnabledConversionPairs) > 0 {
 | 
				
			||||||
 | 
							for _, e := range m.EnabledConversionPairs {
 | 
				
			||||||
 | 
								l = e.Size()
 | 
				
			||||||
 | 
								n += 1 + l + sovGenesis(uint64(l))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return n
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func sovGenesis(x uint64) (n int) {
 | 
					func sovGenesis(x uint64) (n int) {
 | 
				
			||||||
	return (math_bits.Len64(x|1) + 6) / 7
 | 
						return (math_bits.Len64(x|1) + 6) / 7
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -324,6 +640,39 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error {
 | 
				
			|||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			iNdEx = postIndex
 | 
								iNdEx = postIndex
 | 
				
			||||||
 | 
							case 2:
 | 
				
			||||||
 | 
								if wireType != 2 {
 | 
				
			||||||
 | 
									return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var msglen int
 | 
				
			||||||
 | 
								for shift := uint(0); ; shift += 7 {
 | 
				
			||||||
 | 
									if shift >= 64 {
 | 
				
			||||||
 | 
										return ErrIntOverflowGenesis
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if iNdEx >= l {
 | 
				
			||||||
 | 
										return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									b := dAtA[iNdEx]
 | 
				
			||||||
 | 
									iNdEx++
 | 
				
			||||||
 | 
									msglen |= int(b&0x7F) << shift
 | 
				
			||||||
 | 
									if b < 0x80 {
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if msglen < 0 {
 | 
				
			||||||
 | 
									return ErrInvalidLengthGenesis
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								postIndex := iNdEx + msglen
 | 
				
			||||||
 | 
								if postIndex < 0 {
 | 
				
			||||||
 | 
									return ErrInvalidLengthGenesis
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if postIndex > l {
 | 
				
			||||||
 | 
									return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								iNdEx = postIndex
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			iNdEx = preIndex
 | 
								iNdEx = preIndex
 | 
				
			||||||
			skippy, err := skipGenesis(dAtA[iNdEx:])
 | 
								skippy, err := skipGenesis(dAtA[iNdEx:])
 | 
				
			||||||
@ -463,6 +812,90 @@ func (m *Account) Unmarshal(dAtA []byte) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					func (m *Params) Unmarshal(dAtA []byte) error {
 | 
				
			||||||
 | 
						l := len(dAtA)
 | 
				
			||||||
 | 
						iNdEx := 0
 | 
				
			||||||
 | 
						for iNdEx < l {
 | 
				
			||||||
 | 
							preIndex := iNdEx
 | 
				
			||||||
 | 
							var wire uint64
 | 
				
			||||||
 | 
							for shift := uint(0); ; shift += 7 {
 | 
				
			||||||
 | 
								if shift >= 64 {
 | 
				
			||||||
 | 
									return ErrIntOverflowGenesis
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if iNdEx >= l {
 | 
				
			||||||
 | 
									return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								b := dAtA[iNdEx]
 | 
				
			||||||
 | 
								iNdEx++
 | 
				
			||||||
 | 
								wire |= uint64(b&0x7F) << shift
 | 
				
			||||||
 | 
								if b < 0x80 {
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							fieldNum := int32(wire >> 3)
 | 
				
			||||||
 | 
							wireType := int(wire & 0x7)
 | 
				
			||||||
 | 
							if wireType == 4 {
 | 
				
			||||||
 | 
								return fmt.Errorf("proto: Params: wiretype end group for non-group")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if fieldNum <= 0 {
 | 
				
			||||||
 | 
								return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							switch fieldNum {
 | 
				
			||||||
 | 
							case 4:
 | 
				
			||||||
 | 
								if wireType != 2 {
 | 
				
			||||||
 | 
									return fmt.Errorf("proto: wrong wireType = %d for field EnabledConversionPairs", wireType)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var msglen int
 | 
				
			||||||
 | 
								for shift := uint(0); ; shift += 7 {
 | 
				
			||||||
 | 
									if shift >= 64 {
 | 
				
			||||||
 | 
										return ErrIntOverflowGenesis
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if iNdEx >= l {
 | 
				
			||||||
 | 
										return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									b := dAtA[iNdEx]
 | 
				
			||||||
 | 
									iNdEx++
 | 
				
			||||||
 | 
									msglen |= int(b&0x7F) << shift
 | 
				
			||||||
 | 
									if b < 0x80 {
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if msglen < 0 {
 | 
				
			||||||
 | 
									return ErrInvalidLengthGenesis
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								postIndex := iNdEx + msglen
 | 
				
			||||||
 | 
								if postIndex < 0 {
 | 
				
			||||||
 | 
									return ErrInvalidLengthGenesis
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if postIndex > l {
 | 
				
			||||||
 | 
									return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								m.EnabledConversionPairs = append(m.EnabledConversionPairs, ConversionPair{})
 | 
				
			||||||
 | 
								if err := m.EnabledConversionPairs[len(m.EnabledConversionPairs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								iNdEx = postIndex
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								iNdEx = preIndex
 | 
				
			||||||
 | 
								skippy, err := skipGenesis(dAtA[iNdEx:])
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (skippy < 0) || (iNdEx+skippy) < 0 {
 | 
				
			||||||
 | 
									return ErrInvalidLengthGenesis
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (iNdEx + skippy) > l {
 | 
				
			||||||
 | 
									return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								iNdEx += skippy
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if iNdEx > l {
 | 
				
			||||||
 | 
							return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
func skipGenesis(dAtA []byte) (n int, err error) {
 | 
					func skipGenesis(dAtA []byte) (n int, err error) {
 | 
				
			||||||
	l := len(dAtA)
 | 
						l := len(dAtA)
 | 
				
			||||||
	iNdEx := 0
 | 
						iNdEx := 0
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,7 @@ import (
 | 
				
			|||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
	"github.com/stretchr/testify/require"
 | 
						"github.com/stretchr/testify/require"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/kava-labs/kava/app"
 | 
						"github.com/kava-labs/kava/app"
 | 
				
			||||||
@ -16,41 +17,53 @@ func TestGenesisState_Validate(t *testing.T) {
 | 
				
			|||||||
		name     string
 | 
							name     string
 | 
				
			||||||
		accounts []types.Account
 | 
							accounts []types.Account
 | 
				
			||||||
		success  bool
 | 
							success  bool
 | 
				
			||||||
 | 
							params   types.Params
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"dup addresses",
 | 
								name: "dup addresses",
 | 
				
			||||||
			[]types.Account{
 | 
								accounts: []types.Account{
 | 
				
			||||||
				{Address: addrs[0], Balance: sdk.NewInt(100)},
 | 
									{Address: addrs[0], Balance: sdk.NewInt(100)},
 | 
				
			||||||
				{Address: addrs[0], Balance: sdk.NewInt(150)},
 | 
									{Address: addrs[0], Balance: sdk.NewInt(150)},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			false,
 | 
								success: false,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"empty account address",
 | 
								name: "empty account address",
 | 
				
			||||||
			[]types.Account{
 | 
								accounts: []types.Account{
 | 
				
			||||||
				{Balance: sdk.NewInt(100)},
 | 
									{Balance: sdk.NewInt(100)},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			false,
 | 
								success: false,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"negative account balance",
 | 
								name: "negative account balance",
 | 
				
			||||||
			[]types.Account{
 | 
								accounts: []types.Account{
 | 
				
			||||||
				{Address: addrs[0], Balance: sdk.NewInt(-100)},
 | 
									{Address: addrs[0], Balance: sdk.NewInt(-100)},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			false,
 | 
								success: false,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"valid state",
 | 
								name: "invalid params",
 | 
				
			||||||
			[]types.Account{
 | 
								accounts: []types.Account{
 | 
				
			||||||
				{Address: addrs[0], Balance: sdk.NewInt(100)},
 | 
									{Address: addrs[0], Balance: sdk.NewInt(100)},
 | 
				
			||||||
				{Address: addrs[1], Balance: sdk.NewInt(150)},
 | 
									{Address: addrs[1], Balance: sdk.NewInt(150)},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			true,
 | 
								params: types.NewParams(types.NewConversionPairs(
 | 
				
			||||||
 | 
									types.NewConversionPair(types.NewInternalEVMAddress(common.HexToAddress("0xinvalidaddress")), "weth"),
 | 
				
			||||||
 | 
								)),
 | 
				
			||||||
 | 
								success: false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "valid state",
 | 
				
			||||||
 | 
								accounts: []types.Account{
 | 
				
			||||||
 | 
									{Address: addrs[0], Balance: sdk.NewInt(100)},
 | 
				
			||||||
 | 
									{Address: addrs[1], Balance: sdk.NewInt(150)},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								success: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, tt := range tests {
 | 
						for _, tt := range tests {
 | 
				
			||||||
		t.Run(tt.name, func(t *testing.T) {
 | 
							t.Run(tt.name, func(t *testing.T) {
 | 
				
			||||||
			gs := types.NewGenesisState(tt.accounts)
 | 
								gs := types.NewGenesisState(tt.accounts, tt.params)
 | 
				
			||||||
			err := gs.Validate()
 | 
								err := gs.Validate()
 | 
				
			||||||
			if tt.success {
 | 
								if tt.success {
 | 
				
			||||||
				require.NoError(t, err)
 | 
									require.NoError(t, err)
 | 
				
			||||||
 | 
				
			|||||||
@ -3,13 +3,18 @@ package types
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
	"github.com/cosmos/cosmos-sdk/types/address"
 | 
						"github.com/cosmos/cosmos-sdk/types/address"
 | 
				
			||||||
 | 
						authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	// ModuleName name that will be used throughout the module
 | 
						// ModuleName name that will be used throughout the module
 | 
				
			||||||
	ModuleName = "evmutil"
 | 
						ModuleName = "evmutil"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	StoreKey = "utilevm" // cannot be emvutil due to collision with x/evm
 | 
						StoreKey = "utilevm" // note: cannot be emvutil due to collision with x/evm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// RouterKey Top level router key
 | 
				
			||||||
 | 
						RouterKey = ModuleName
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var AccountStoreKeyPrefix = []byte{0x00} // prefix for keys that store accounts
 | 
					var AccountStoreKeyPrefix = []byte{0x00} // prefix for keys that store accounts
 | 
				
			||||||
@ -18,3 +23,10 @@ var AccountStoreKeyPrefix = []byte{0x00} // prefix for keys that store accounts
 | 
				
			|||||||
func AccountStoreKey(addr sdk.AccAddress) []byte {
 | 
					func AccountStoreKey(addr sdk.AccAddress) []byte {
 | 
				
			||||||
	return append(AccountStoreKeyPrefix, address.MustLengthPrefix(addr)...)
 | 
						return append(AccountStoreKeyPrefix, address.MustLengthPrefix(addr)...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ModuleAddress is the native module address for EVM
 | 
				
			||||||
 | 
					var ModuleEVMAddress common.Address
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						ModuleEVMAddress = common.BytesToAddress(authtypes.NewModuleAddress(ModuleName).Bytes())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										146
									
								
								x/evmutil/types/msg.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								x/evmutil/types/msg.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,146 @@
 | 
				
			|||||||
 | 
					package types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
 | 
				
			||||||
 | 
						"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ensure Msg interface compliance at compile time
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						_ sdk.Msg            = &MsgConvertCoinToERC20{}
 | 
				
			||||||
 | 
						_ sdk.Msg            = &MsgConvertERC20ToCoin{}
 | 
				
			||||||
 | 
						_ legacytx.LegacyMsg = &MsgConvertCoinToERC20{}
 | 
				
			||||||
 | 
						_ legacytx.LegacyMsg = &MsgConvertERC20ToCoin{}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// legacy message types
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						TypeMsgConvertCoinToERC20 = "evmutil_convert_coin_to_erc20"
 | 
				
			||||||
 | 
						TypeMsgConvertERC20ToCoin = "evmutil_convert_erc20_to_coin"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewMsgConvertCoinToERC20 returns a new MsgConvertCoinToERC20
 | 
				
			||||||
 | 
					func NewMsgConvertCoinToERC20(
 | 
				
			||||||
 | 
						initiator string,
 | 
				
			||||||
 | 
						receiver string,
 | 
				
			||||||
 | 
						amount sdk.Coin,
 | 
				
			||||||
 | 
					) MsgConvertCoinToERC20 {
 | 
				
			||||||
 | 
						return MsgConvertCoinToERC20{
 | 
				
			||||||
 | 
							Initiator: initiator,
 | 
				
			||||||
 | 
							Receiver:  receiver,
 | 
				
			||||||
 | 
							Amount:    &amount,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetSigners returns the addresses of signers that must sign.
 | 
				
			||||||
 | 
					func (msg MsgConvertCoinToERC20) GetSigners() []sdk.AccAddress {
 | 
				
			||||||
 | 
						sender, err := sdk.AccAddressFromBech32(msg.Initiator)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return []sdk.AccAddress{sender}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateBasic does a simple validation check that doesn't require access to any other information.
 | 
				
			||||||
 | 
					func (msg MsgConvertCoinToERC20) ValidateBasic() error {
 | 
				
			||||||
 | 
						_, err := sdk.AccAddressFromBech32(msg.Initiator)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !common.IsHexAddress(msg.Receiver) {
 | 
				
			||||||
 | 
							return sdkerrors.Wrap(
 | 
				
			||||||
 | 
								sdkerrors.ErrInvalidAddress,
 | 
				
			||||||
 | 
								"Receiver is not a valid hex address",
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if msg.Amount.IsZero() {
 | 
				
			||||||
 | 
							return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "amount cannot be zero")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Checks for negative
 | 
				
			||||||
 | 
						return msg.Amount.Validate()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetSignBytes implements the LegacyMsg.GetSignBytes method.
 | 
				
			||||||
 | 
					func (msg MsgConvertCoinToERC20) GetSignBytes() []byte {
 | 
				
			||||||
 | 
						return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Route implements the LegacyMsg.Route method.
 | 
				
			||||||
 | 
					func (msg MsgConvertCoinToERC20) Route() string {
 | 
				
			||||||
 | 
						return RouterKey
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Type implements the LegacyMsg.Type method.
 | 
				
			||||||
 | 
					func (msg MsgConvertCoinToERC20) Type() string {
 | 
				
			||||||
 | 
						return TypeMsgConvertCoinToERC20
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewMsgConvertERC20ToCoin returns a new MsgConvertERC20ToCoin
 | 
				
			||||||
 | 
					func NewMsgConvertERC20ToCoin(
 | 
				
			||||||
 | 
						initiator InternalEVMAddress,
 | 
				
			||||||
 | 
						receiver sdk.AccAddress,
 | 
				
			||||||
 | 
						contractAddr InternalEVMAddress,
 | 
				
			||||||
 | 
						amount sdk.Int,
 | 
				
			||||||
 | 
					) MsgConvertERC20ToCoin {
 | 
				
			||||||
 | 
						return MsgConvertERC20ToCoin{
 | 
				
			||||||
 | 
							Initiator:        initiator.String(),
 | 
				
			||||||
 | 
							Receiver:         receiver.String(),
 | 
				
			||||||
 | 
							KavaERC20Address: contractAddr.String(),
 | 
				
			||||||
 | 
							Amount:           amount,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetSigners returns the addresses of signers that must sign.
 | 
				
			||||||
 | 
					func (msg MsgConvertERC20ToCoin) GetSigners() []sdk.AccAddress {
 | 
				
			||||||
 | 
						addr := common.HexToAddress(msg.Initiator)
 | 
				
			||||||
 | 
						sender := sdk.AccAddress(addr.Bytes())
 | 
				
			||||||
 | 
						return []sdk.AccAddress{sender}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateBasic does a simple validation check that doesn't require access to any other information.
 | 
				
			||||||
 | 
					func (msg MsgConvertERC20ToCoin) ValidateBasic() error {
 | 
				
			||||||
 | 
						if !common.IsHexAddress(msg.Initiator) {
 | 
				
			||||||
 | 
							return sdkerrors.Wrap(
 | 
				
			||||||
 | 
								sdkerrors.ErrInvalidAddress,
 | 
				
			||||||
 | 
								"initiator is not a valid hex address",
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !common.IsHexAddress(msg.KavaERC20Address) {
 | 
				
			||||||
 | 
							return sdkerrors.Wrap(
 | 
				
			||||||
 | 
								sdkerrors.ErrInvalidAddress,
 | 
				
			||||||
 | 
								"erc20 contract address is not a valid hex address",
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := sdk.AccAddressFromBech32(msg.Receiver)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "receiver is not a valid bech32 address")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if msg.Amount.IsNil() || msg.Amount.LTE(sdk.ZeroInt()) {
 | 
				
			||||||
 | 
							return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "amount cannot be zero or less")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetSignBytes implements the LegacyMsg.GetSignBytes method.
 | 
				
			||||||
 | 
					func (msg MsgConvertERC20ToCoin) GetSignBytes() []byte {
 | 
				
			||||||
 | 
						return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Route implements the LegacyMsg.Route method.
 | 
				
			||||||
 | 
					func (msg MsgConvertERC20ToCoin) Route() string {
 | 
				
			||||||
 | 
						return RouterKey
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Type implements the LegacyMsg.Type method.
 | 
				
			||||||
 | 
					func (msg MsgConvertERC20ToCoin) Type() string {
 | 
				
			||||||
 | 
						return TypeMsgConvertERC20ToCoin
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										199
									
								
								x/evmutil/types/msg_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								x/evmutil/types/msg_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,199 @@
 | 
				
			|||||||
 | 
					package types_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/app"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/require"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestMsgConvertCoinToERC20(t *testing.T) {
 | 
				
			||||||
 | 
						app.SetSDKConfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						type errArgs struct {
 | 
				
			||||||
 | 
							expectPass bool
 | 
				
			||||||
 | 
							contains   string
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							name          string
 | 
				
			||||||
 | 
							giveInitiator string
 | 
				
			||||||
 | 
							giveReceiver  string
 | 
				
			||||||
 | 
							giveAmount    sdk.Coin
 | 
				
			||||||
 | 
							errArgs       errArgs
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"valid",
 | 
				
			||||||
 | 
								"kava123fxg0l602etulhhcdm0vt7l57qya5wjcrwhzz",
 | 
				
			||||||
 | 
								"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
 | 
				
			||||||
 | 
								sdk.NewCoin("erc20/weth", sdk.NewInt(1234)),
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - odd length hex address",
 | 
				
			||||||
 | 
								"kava123fxg0l602etulhhcdm0vt7l57qya5wjcrwhzz",
 | 
				
			||||||
 | 
								"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc",
 | 
				
			||||||
 | 
								sdk.NewCoin("erc20/weth", sdk.NewInt(1234)),
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "Receiver is not a valid hex address: invalid address",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - zero amount",
 | 
				
			||||||
 | 
								"kava123fxg0l602etulhhcdm0vt7l57qya5wjcrwhzz",
 | 
				
			||||||
 | 
								"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
 | 
				
			||||||
 | 
								sdk.NewCoin("erc20/weth", sdk.NewInt(0)),
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "amount cannot be zero",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - negative amount",
 | 
				
			||||||
 | 
								"kava123fxg0l602etulhhcdm0vt7l57qya5wjcrwhzz",
 | 
				
			||||||
 | 
								"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
 | 
				
			||||||
 | 
								// Create manually so there is no validation
 | 
				
			||||||
 | 
								sdk.Coin{Denom: "erc20/weth", Amount: sdk.NewInt(-1234)},
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "negative coin amount",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - empty denom",
 | 
				
			||||||
 | 
								"kava123fxg0l602etulhhcdm0vt7l57qya5wjcrwhzz",
 | 
				
			||||||
 | 
								"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
 | 
				
			||||||
 | 
								sdk.Coin{Denom: "", Amount: sdk.NewInt(-1234)},
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "invalid denom",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - invalid denom",
 | 
				
			||||||
 | 
								"kava123fxg0l602etulhhcdm0vt7l57qya5wjcrwhzz",
 | 
				
			||||||
 | 
								"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
 | 
				
			||||||
 | 
								sdk.Coin{Denom: "h", Amount: sdk.NewInt(-1234)},
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "invalid denom",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range tests {
 | 
				
			||||||
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
 | 
								msg := types.NewMsgConvertCoinToERC20(
 | 
				
			||||||
 | 
									tc.giveInitiator,
 | 
				
			||||||
 | 
									tc.giveReceiver,
 | 
				
			||||||
 | 
									tc.giveAmount,
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
								err := msg.ValidateBasic()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if tc.errArgs.expectPass {
 | 
				
			||||||
 | 
									require.NoError(t, err)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									require.Error(t, err)
 | 
				
			||||||
 | 
									require.Contains(t, err.Error(), tc.errArgs.contains)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestMsgConvertERC20ToCoin(t *testing.T) {
 | 
				
			||||||
 | 
						app.SetSDKConfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						type errArgs struct {
 | 
				
			||||||
 | 
							expectPass bool
 | 
				
			||||||
 | 
							contains   string
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							name         string
 | 
				
			||||||
 | 
							receiver     string
 | 
				
			||||||
 | 
							initiator    string
 | 
				
			||||||
 | 
							contractAddr string
 | 
				
			||||||
 | 
							amount       sdk.Int
 | 
				
			||||||
 | 
							errArgs      errArgs
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"valid",
 | 
				
			||||||
 | 
								"kava123fxg0l602etulhhcdm0vt7l57qya5wjcrwhzz",
 | 
				
			||||||
 | 
								"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
 | 
				
			||||||
 | 
								"0x404F9466d758eA33eA84CeBE9E444b06533b369e",
 | 
				
			||||||
 | 
								sdk.NewInt(1234),
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - odd length hex address",
 | 
				
			||||||
 | 
								"kava123fxg0l602etulhhcdm0vt7l57qya5wjcrwhzz",
 | 
				
			||||||
 | 
								"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc",
 | 
				
			||||||
 | 
								"0x404F9466d758eA33eA84CeBE9E444b06533b369e",
 | 
				
			||||||
 | 
								sdk.NewInt(1234),
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "initiator is not a valid hex address",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - zero amount",
 | 
				
			||||||
 | 
								"kava123fxg0l602etulhhcdm0vt7l57qya5wjcrwhzz",
 | 
				
			||||||
 | 
								"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
 | 
				
			||||||
 | 
								"0x404F9466d758eA33eA84CeBE9E444b06533b369e",
 | 
				
			||||||
 | 
								sdk.NewInt(0),
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "amount cannot be zero",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - negative amount",
 | 
				
			||||||
 | 
								"kava123fxg0l602etulhhcdm0vt7l57qya5wjcrwhzz",
 | 
				
			||||||
 | 
								"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
 | 
				
			||||||
 | 
								"0x404F9466d758eA33eA84CeBE9E444b06533b369e",
 | 
				
			||||||
 | 
								sdk.NewInt(-1234),
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "amount cannot be zero or less",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"invalid - invalid contract address",
 | 
				
			||||||
 | 
								"kava123fxg0l602etulhhcdm0vt7l57qya5wjcrwhzz",
 | 
				
			||||||
 | 
								"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
 | 
				
			||||||
 | 
								"0x404F9466d758eA33eA84CeBE9E444b06533b369",
 | 
				
			||||||
 | 
								sdk.NewInt(1234),
 | 
				
			||||||
 | 
								errArgs{
 | 
				
			||||||
 | 
									expectPass: false,
 | 
				
			||||||
 | 
									contains:   "erc20 contract address is not a valid hex address",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range tests {
 | 
				
			||||||
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
 | 
								msg := types.MsgConvertERC20ToCoin{
 | 
				
			||||||
 | 
									Initiator:        tc.initiator,
 | 
				
			||||||
 | 
									Receiver:         tc.receiver,
 | 
				
			||||||
 | 
									KavaERC20Address: tc.contractAddr,
 | 
				
			||||||
 | 
									Amount:           tc.amount,
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								err := msg.ValidateBasic()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if tc.errArgs.expectPass {
 | 
				
			||||||
 | 
									require.NoError(t, err)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									require.Error(t, err)
 | 
				
			||||||
 | 
									require.Contains(t, err.Error(), tc.errArgs.contains)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										48
									
								
								x/evmutil/types/params.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								x/evmutil/types/params.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					package types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Parameter keys and default values
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						KeyEnabledConversionPairs = []byte("EnabledConversionPairs")
 | 
				
			||||||
 | 
						DefaultConversionPairs    = ConversionPairs{}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ParamKeyTable for evmutil module.
 | 
				
			||||||
 | 
					func ParamKeyTable() paramtypes.KeyTable {
 | 
				
			||||||
 | 
						return paramtypes.NewKeyTable().RegisterParamSet(&Params{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ParamSetPairs implements the ParamSet interface and returns all the key/value
 | 
				
			||||||
 | 
					// pairs pairs of the evmutil module's parameters.
 | 
				
			||||||
 | 
					func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
 | 
				
			||||||
 | 
						return paramtypes.ParamSetPairs{
 | 
				
			||||||
 | 
							paramtypes.NewParamSetPair(KeyEnabledConversionPairs, &p.EnabledConversionPairs, validateConversionPairs),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewParams returns new evmutil module Params.
 | 
				
			||||||
 | 
					func NewParams(
 | 
				
			||||||
 | 
						conversionPairs ConversionPairs,
 | 
				
			||||||
 | 
					) Params {
 | 
				
			||||||
 | 
						return Params{
 | 
				
			||||||
 | 
							EnabledConversionPairs: conversionPairs,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DefaultParams returns the default parameters for evmutil.
 | 
				
			||||||
 | 
					func DefaultParams() Params {
 | 
				
			||||||
 | 
						return NewParams(
 | 
				
			||||||
 | 
							DefaultConversionPairs,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Validate returns an error if the Parmas is invalid.
 | 
				
			||||||
 | 
					func (p *Params) Validate() error {
 | 
				
			||||||
 | 
						if err := p.EnabledConversionPairs.Validate(); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										75
									
								
								x/evmutil/types/params_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								x/evmutil/types/params_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,75 @@
 | 
				
			|||||||
 | 
					package types_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						bytes "bytes"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/suite"
 | 
				
			||||||
 | 
						"sigs.k8s.io/yaml"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						paramstypes "github.com/cosmos/cosmos-sdk/x/params/types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/app"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/testutil"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/evmutil/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ParamsTestSuite struct {
 | 
				
			||||||
 | 
						suite.Suite
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ParamsTestSuite) SetupTest() {
 | 
				
			||||||
 | 
						app.SetSDKConfig()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ParamsTestSuite) TestDefault() {
 | 
				
			||||||
 | 
						defaultParams := types.DefaultParams()
 | 
				
			||||||
 | 
						suite.Require().NoError(defaultParams.Validate())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ParamsTestSuite) TestMarshalYAML() {
 | 
				
			||||||
 | 
						conversionPairs := types.NewConversionPairs(
 | 
				
			||||||
 | 
							types.NewConversionPair(
 | 
				
			||||||
 | 
								testutil.MustNewInternalEVMAddressFromString("0x0000000000000000000000000000000000000001"),
 | 
				
			||||||
 | 
								"usdc",
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p := types.NewParams(
 | 
				
			||||||
 | 
							conversionPairs,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data, err := yaml.Marshal(p)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var params map[string]interface{}
 | 
				
			||||||
 | 
						err = yaml.Unmarshal(data, ¶ms)
 | 
				
			||||||
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
						_, ok := params["enabled_conversion_pairs"]
 | 
				
			||||||
 | 
						suite.Require().True(ok, "enabled_conversion_pairs should exist in yaml")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *ParamsTestSuite) TestParamSetPairs_EnabledConversionPairs() {
 | 
				
			||||||
 | 
						suite.Require().Equal([]byte("EnabledConversionPairs"), types.KeyEnabledConversionPairs)
 | 
				
			||||||
 | 
						defaultParams := types.DefaultParams()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var paramSetPair *paramstypes.ParamSetPair
 | 
				
			||||||
 | 
						for _, pair := range defaultParams.ParamSetPairs() {
 | 
				
			||||||
 | 
							if bytes.Equal(pair.Key, types.KeyEnabledConversionPairs) {
 | 
				
			||||||
 | 
								paramSetPair = &pair
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						suite.Require().NotNil(paramSetPair)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pairs, ok := paramSetPair.Value.(*types.ConversionPairs)
 | 
				
			||||||
 | 
						suite.Require().True(ok)
 | 
				
			||||||
 | 
						suite.Require().Equal(pairs, &defaultParams.EnabledConversionPairs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						suite.Require().Nil(paramSetPair.ValidatorFn(*pairs))
 | 
				
			||||||
 | 
						suite.Require().EqualError(paramSetPair.ValidatorFn(struct{}{}), "invalid parameter type: struct {}")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestParamsTestSuite(t *testing.T) {
 | 
				
			||||||
 | 
						suite.Run(t, new(ParamsTestSuite))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										638
									
								
								x/evmutil/types/query.pb.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										638
									
								
								x/evmutil/types/query.pb.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,638 @@
 | 
				
			|||||||
 | 
					// Code generated by protoc-gen-gogo. DO NOT EDIT.
 | 
				
			||||||
 | 
					// source: kava/evmutil/v1beta1/query.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						context "context"
 | 
				
			||||||
 | 
						fmt "fmt"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						grpc1 "github.com/gogo/protobuf/grpc"
 | 
				
			||||||
 | 
						proto "github.com/gogo/protobuf/proto"
 | 
				
			||||||
 | 
						_ "google.golang.org/genproto/googleapis/api/annotations"
 | 
				
			||||||
 | 
						grpc "google.golang.org/grpc"
 | 
				
			||||||
 | 
						codes "google.golang.org/grpc/codes"
 | 
				
			||||||
 | 
						status "google.golang.org/grpc/status"
 | 
				
			||||||
 | 
						io "io"
 | 
				
			||||||
 | 
						math "math"
 | 
				
			||||||
 | 
						math_bits "math/bits"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Reference imports to suppress errors if they are not otherwise used.
 | 
				
			||||||
 | 
					var _ = proto.Marshal
 | 
				
			||||||
 | 
					var _ = fmt.Errorf
 | 
				
			||||||
 | 
					var _ = math.Inf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is a compile-time assertion to ensure that this generated file
 | 
				
			||||||
 | 
					// is compatible with the proto package it is being compiled against.
 | 
				
			||||||
 | 
					// A compilation error at this line likely means your copy of the
 | 
				
			||||||
 | 
					// proto package needs to be updated.
 | 
				
			||||||
 | 
					const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// QueryParamsRequest defines the request type for querying x/evmutil parameters.
 | 
				
			||||||
 | 
					type QueryParamsRequest struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *QueryParamsRequest) Reset()         { *m = QueryParamsRequest{} }
 | 
				
			||||||
 | 
					func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) }
 | 
				
			||||||
 | 
					func (*QueryParamsRequest) ProtoMessage()    {}
 | 
				
			||||||
 | 
					func (*QueryParamsRequest) Descriptor() ([]byte, []int) {
 | 
				
			||||||
 | 
						return fileDescriptor_4a8d0512331709e7, []int{0}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error {
 | 
				
			||||||
 | 
						return m.Unmarshal(b)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *QueryParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 | 
				
			||||||
 | 
						if deterministic {
 | 
				
			||||||
 | 
							return xxx_messageInfo_QueryParamsRequest.Marshal(b, m, deterministic)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							b = b[:cap(b)]
 | 
				
			||||||
 | 
							n, err := m.MarshalToSizedBuffer(b)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return b[:n], nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *QueryParamsRequest) XXX_Merge(src proto.Message) {
 | 
				
			||||||
 | 
						xxx_messageInfo_QueryParamsRequest.Merge(m, src)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *QueryParamsRequest) XXX_Size() int {
 | 
				
			||||||
 | 
						return m.Size()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *QueryParamsRequest) XXX_DiscardUnknown() {
 | 
				
			||||||
 | 
						xxx_messageInfo_QueryParamsRequest.DiscardUnknown(m)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var xxx_messageInfo_QueryParamsRequest proto.InternalMessageInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// QueryParamsResponse defines the response type for querying x/evmutil parameters.
 | 
				
			||||||
 | 
					type QueryParamsResponse struct {
 | 
				
			||||||
 | 
						Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *QueryParamsResponse) Reset()         { *m = QueryParamsResponse{} }
 | 
				
			||||||
 | 
					func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) }
 | 
				
			||||||
 | 
					func (*QueryParamsResponse) ProtoMessage()    {}
 | 
				
			||||||
 | 
					func (*QueryParamsResponse) Descriptor() ([]byte, []int) {
 | 
				
			||||||
 | 
						return fileDescriptor_4a8d0512331709e7, []int{1}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error {
 | 
				
			||||||
 | 
						return m.Unmarshal(b)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *QueryParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 | 
				
			||||||
 | 
						if deterministic {
 | 
				
			||||||
 | 
							return xxx_messageInfo_QueryParamsResponse.Marshal(b, m, deterministic)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							b = b[:cap(b)]
 | 
				
			||||||
 | 
							n, err := m.MarshalToSizedBuffer(b)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return b[:n], nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *QueryParamsResponse) XXX_Merge(src proto.Message) {
 | 
				
			||||||
 | 
						xxx_messageInfo_QueryParamsResponse.Merge(m, src)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *QueryParamsResponse) XXX_Size() int {
 | 
				
			||||||
 | 
						return m.Size()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *QueryParamsResponse) XXX_DiscardUnknown() {
 | 
				
			||||||
 | 
						xxx_messageInfo_QueryParamsResponse.DiscardUnknown(m)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var xxx_messageInfo_QueryParamsResponse proto.InternalMessageInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *QueryParamsResponse) GetParams() Params {
 | 
				
			||||||
 | 
						if m != nil {
 | 
				
			||||||
 | 
							return m.Params
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return Params{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						proto.RegisterType((*QueryParamsRequest)(nil), "kava.evmutil.v1beta1.QueryParamsRequest")
 | 
				
			||||||
 | 
						proto.RegisterType((*QueryParamsResponse)(nil), "kava.evmutil.v1beta1.QueryParamsResponse")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() { proto.RegisterFile("kava/evmutil/v1beta1/query.proto", fileDescriptor_4a8d0512331709e7) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var fileDescriptor_4a8d0512331709e7 = []byte{
 | 
				
			||||||
 | 
						// 294 bytes of a gzipped FileDescriptorProto
 | 
				
			||||||
 | 
						0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x90, 0x31, 0x4b, 0xc4, 0x30,
 | 
				
			||||||
 | 
						0x18, 0x86, 0x1b, 0xd1, 0x0e, 0x71, 0x8b, 0x1d, 0xa4, 0x94, 0x78, 0x14, 0x87, 0xbb, 0xc1, 0x84,
 | 
				
			||||||
 | 
						0x3b, 0x37, 0xc7, 0x5b, 0x5d, 0xbc, 0x1b, 0xdd, 0x52, 0x09, 0xb1, 0xd8, 0xf6, 0xeb, 0x35, 0x69,
 | 
				
			||||||
 | 
						0xf1, 0x56, 0x9d, 0x05, 0xc1, 0x3f, 0xe1, 0x4f, 0xb9, 0xf1, 0xc0, 0xc5, 0x49, 0xce, 0xd6, 0x1f,
 | 
				
			||||||
 | 
						0x22, 0x6d, 0x8a, 0x20, 0x76, 0x70, 0x0b, 0x5f, 0x9e, 0xef, 0x79, 0xdf, 0x04, 0x8f, 0xee, 0x44,
 | 
				
			||||||
 | 
						0x25, 0xb8, 0xac, 0xd2, 0xd2, 0xc4, 0x09, 0xaf, 0xa6, 0x91, 0x34, 0x62, 0xca, 0x57, 0xa5, 0x2c,
 | 
				
			||||||
 | 
						0xd6, 0x2c, 0x2f, 0xc0, 0x00, 0xf1, 0x5a, 0x82, 0xf5, 0x04, 0xeb, 0x09, 0xdf, 0x53, 0xa0, 0xa0,
 | 
				
			||||||
 | 
						0x03, 0x78, 0x7b, 0xb2, 0xac, 0x1f, 0x28, 0x00, 0x95, 0x48, 0x2e, 0xf2, 0x98, 0x8b, 0x2c, 0x03,
 | 
				
			||||||
 | 
						0x23, 0x4c, 0x0c, 0x99, 0xee, 0x6f, 0xc3, 0xc1, 0x2c, 0x25, 0x33, 0xa9, 0xe3, 0x9e, 0x09, 0x3d,
 | 
				
			||||||
 | 
						0x4c, 0x16, 0x6d, 0xf8, 0x95, 0x28, 0x44, 0xaa, 0x97, 0x72, 0x55, 0x4a, 0x6d, 0xc2, 0x05, 0x3e,
 | 
				
			||||||
 | 
						0xfa, 0x35, 0xd5, 0x39, 0x64, 0x5a, 0x92, 0x0b, 0xec, 0xe6, 0xdd, 0xe4, 0x18, 0x8d, 0xd0, 0xf8,
 | 
				
			||||||
 | 
						0x70, 0x16, 0xb0, 0xa1, 0xae, 0xcc, 0x6e, 0xcd, 0xf7, 0x37, 0x1f, 0x27, 0xce, 0xb2, 0xdf, 0x98,
 | 
				
			||||||
 | 
						0x3d, 0x21, 0x7c, 0xd0, 0x39, 0xc9, 0x23, 0xc2, 0xae, 0x45, 0xc8, 0x78, 0x58, 0xf0, 0xb7, 0x91,
 | 
				
			||||||
 | 
						0x3f, 0xf9, 0x07, 0x69, 0x5b, 0x86, 0xa7, 0x0f, 0x6f, 0x5f, 0x2f, 0x7b, 0x94, 0x04, 0x7c, 0xf0,
 | 
				
			||||||
 | 
						0xfd, 0xb6, 0xcf, 0xfc, 0x72, 0xf7, 0x49, 0xd1, 0x6b, 0x4d, 0xd1, 0xa6, 0xa6, 0x68, 0x5b, 0x53,
 | 
				
			||||||
 | 
						0xb4, 0xab, 0x29, 0x7a, 0x6e, 0xa8, 0xb3, 0x6d, 0xa8, 0xf3, 0xde, 0x50, 0xe7, 0x7a, 0xa2, 0x62,
 | 
				
			||||||
 | 
						0x73, 0x5b, 0x46, 0xec, 0x06, 0xd2, 0xce, 0x74, 0x96, 0x88, 0x48, 0x5b, 0xe7, 0xfd, 0x8f, 0xd5,
 | 
				
			||||||
 | 
						0xac, 0x73, 0xa9, 0x23, 0xb7, 0xfb, 0xcc, 0xf3, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0xeb, 0xa2,
 | 
				
			||||||
 | 
						0x8d, 0x8c, 0xde, 0x01, 0x00, 0x00,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *QueryParamsRequest) VerboseEqual(that interface{}) error {
 | 
				
			||||||
 | 
						if that == nil {
 | 
				
			||||||
 | 
							if this == nil {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return fmt.Errorf("that == nil && this != nil")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						that1, ok := that.(*QueryParamsRequest)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							that2, ok := that.(QueryParamsRequest)
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								that1 = &that2
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return fmt.Errorf("that is not of type *QueryParamsRequest")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if that1 == nil {
 | 
				
			||||||
 | 
							if this == nil {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return fmt.Errorf("that is type *QueryParamsRequest but is nil && this != nil")
 | 
				
			||||||
 | 
						} else if this == nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("that is type *QueryParamsRequest but is not nil && this == nil")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (this *QueryParamsRequest) Equal(that interface{}) bool {
 | 
				
			||||||
 | 
						if that == nil {
 | 
				
			||||||
 | 
							return this == nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						that1, ok := that.(*QueryParamsRequest)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							that2, ok := that.(QueryParamsRequest)
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								that1 = &that2
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if that1 == nil {
 | 
				
			||||||
 | 
							return this == nil
 | 
				
			||||||
 | 
						} else if this == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (this *QueryParamsResponse) VerboseEqual(that interface{}) error {
 | 
				
			||||||
 | 
						if that == nil {
 | 
				
			||||||
 | 
							if this == nil {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return fmt.Errorf("that == nil && this != nil")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						that1, ok := that.(*QueryParamsResponse)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							that2, ok := that.(QueryParamsResponse)
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								that1 = &that2
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return fmt.Errorf("that is not of type *QueryParamsResponse")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if that1 == nil {
 | 
				
			||||||
 | 
							if this == nil {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return fmt.Errorf("that is type *QueryParamsResponse but is nil && this != nil")
 | 
				
			||||||
 | 
						} else if this == nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("that is type *QueryParamsResponse but is not nil && this == nil")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !this.Params.Equal(&that1.Params) {
 | 
				
			||||||
 | 
							return fmt.Errorf("Params this(%v) Not Equal that(%v)", this.Params, that1.Params)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (this *QueryParamsResponse) Equal(that interface{}) bool {
 | 
				
			||||||
 | 
						if that == nil {
 | 
				
			||||||
 | 
							return this == nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						that1, ok := that.(*QueryParamsResponse)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							that2, ok := that.(QueryParamsResponse)
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								that1 = &that2
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if that1 == nil {
 | 
				
			||||||
 | 
							return this == nil
 | 
				
			||||||
 | 
						} else if this == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !this.Params.Equal(&that1.Params) {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Reference imports to suppress errors if they are not otherwise used.
 | 
				
			||||||
 | 
					var _ context.Context
 | 
				
			||||||
 | 
					var _ grpc.ClientConn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is a compile-time assertion to ensure that this generated file
 | 
				
			||||||
 | 
					// is compatible with the grpc package it is being compiled against.
 | 
				
			||||||
 | 
					const _ = grpc.SupportPackageIsVersion4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// QueryClient is the client API for Query service.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
 | 
				
			||||||
 | 
					type QueryClient interface {
 | 
				
			||||||
 | 
						// Params queries all parameters of the evmutil module.
 | 
				
			||||||
 | 
						Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type queryClient struct {
 | 
				
			||||||
 | 
						cc grpc1.ClientConn
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewQueryClient(cc grpc1.ClientConn) QueryClient {
 | 
				
			||||||
 | 
						return &queryClient{cc}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) {
 | 
				
			||||||
 | 
						out := new(QueryParamsResponse)
 | 
				
			||||||
 | 
						err := c.cc.Invoke(ctx, "/kava.evmutil.v1beta1.Query/Params", in, out, opts...)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return out, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// QueryServer is the server API for Query service.
 | 
				
			||||||
 | 
					type QueryServer interface {
 | 
				
			||||||
 | 
						// Params queries all parameters of the evmutil module.
 | 
				
			||||||
 | 
						Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UnimplementedQueryServer can be embedded to have forward compatible implementations.
 | 
				
			||||||
 | 
					type UnimplementedQueryServer struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) {
 | 
				
			||||||
 | 
						return nil, status.Errorf(codes.Unimplemented, "method Params not implemented")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func RegisterQueryServer(s grpc1.Server, srv QueryServer) {
 | 
				
			||||||
 | 
						s.RegisterService(&_Query_serviceDesc, srv)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
 | 
				
			||||||
 | 
						in := new(QueryParamsRequest)
 | 
				
			||||||
 | 
						if err := dec(in); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if interceptor == nil {
 | 
				
			||||||
 | 
							return srv.(QueryServer).Params(ctx, in)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						info := &grpc.UnaryServerInfo{
 | 
				
			||||||
 | 
							Server:     srv,
 | 
				
			||||||
 | 
							FullMethod: "/kava.evmutil.v1beta1.Query/Params",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 | 
				
			||||||
 | 
							return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return interceptor(ctx, in, info, handler)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _Query_serviceDesc = grpc.ServiceDesc{
 | 
				
			||||||
 | 
						ServiceName: "kava.evmutil.v1beta1.Query",
 | 
				
			||||||
 | 
						HandlerType: (*QueryServer)(nil),
 | 
				
			||||||
 | 
						Methods: []grpc.MethodDesc{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								MethodName: "Params",
 | 
				
			||||||
 | 
								Handler:    _Query_Params_Handler,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						Streams:  []grpc.StreamDesc{},
 | 
				
			||||||
 | 
						Metadata: "kava/evmutil/v1beta1/query.proto",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *QueryParamsRequest) Marshal() (dAtA []byte, err error) {
 | 
				
			||||||
 | 
						size := m.Size()
 | 
				
			||||||
 | 
						dAtA = make([]byte, size)
 | 
				
			||||||
 | 
						n, err := m.MarshalToSizedBuffer(dAtA[:size])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return dAtA[:n], nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) {
 | 
				
			||||||
 | 
						size := m.Size()
 | 
				
			||||||
 | 
						return m.MarshalToSizedBuffer(dAtA[:size])
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 | 
				
			||||||
 | 
						i := len(dAtA)
 | 
				
			||||||
 | 
						_ = i
 | 
				
			||||||
 | 
						var l int
 | 
				
			||||||
 | 
						_ = l
 | 
				
			||||||
 | 
						return len(dAtA) - i, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *QueryParamsResponse) Marshal() (dAtA []byte, err error) {
 | 
				
			||||||
 | 
						size := m.Size()
 | 
				
			||||||
 | 
						dAtA = make([]byte, size)
 | 
				
			||||||
 | 
						n, err := m.MarshalToSizedBuffer(dAtA[:size])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return dAtA[:n], nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) {
 | 
				
			||||||
 | 
						size := m.Size()
 | 
				
			||||||
 | 
						return m.MarshalToSizedBuffer(dAtA[:size])
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 | 
				
			||||||
 | 
						i := len(dAtA)
 | 
				
			||||||
 | 
						_ = i
 | 
				
			||||||
 | 
						var l int
 | 
				
			||||||
 | 
						_ = l
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							size, err := m.Params.MarshalToSizedBuffer(dAtA[:i])
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return 0, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							i -= size
 | 
				
			||||||
 | 
							i = encodeVarintQuery(dAtA, i, uint64(size))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						i--
 | 
				
			||||||
 | 
						dAtA[i] = 0xa
 | 
				
			||||||
 | 
						return len(dAtA) - i, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func encodeVarintQuery(dAtA []byte, offset int, v uint64) int {
 | 
				
			||||||
 | 
						offset -= sovQuery(v)
 | 
				
			||||||
 | 
						base := offset
 | 
				
			||||||
 | 
						for v >= 1<<7 {
 | 
				
			||||||
 | 
							dAtA[offset] = uint8(v&0x7f | 0x80)
 | 
				
			||||||
 | 
							v >>= 7
 | 
				
			||||||
 | 
							offset++
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						dAtA[offset] = uint8(v)
 | 
				
			||||||
 | 
						return base
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *QueryParamsRequest) Size() (n int) {
 | 
				
			||||||
 | 
						if m == nil {
 | 
				
			||||||
 | 
							return 0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var l int
 | 
				
			||||||
 | 
						_ = l
 | 
				
			||||||
 | 
						return n
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *QueryParamsResponse) Size() (n int) {
 | 
				
			||||||
 | 
						if m == nil {
 | 
				
			||||||
 | 
							return 0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var l int
 | 
				
			||||||
 | 
						_ = l
 | 
				
			||||||
 | 
						l = m.Params.Size()
 | 
				
			||||||
 | 
						n += 1 + l + sovQuery(uint64(l))
 | 
				
			||||||
 | 
						return n
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func sovQuery(x uint64) (n int) {
 | 
				
			||||||
 | 
						return (math_bits.Len64(x|1) + 6) / 7
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func sozQuery(x uint64) (n int) {
 | 
				
			||||||
 | 
						return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63))))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error {
 | 
				
			||||||
 | 
						l := len(dAtA)
 | 
				
			||||||
 | 
						iNdEx := 0
 | 
				
			||||||
 | 
						for iNdEx < l {
 | 
				
			||||||
 | 
							preIndex := iNdEx
 | 
				
			||||||
 | 
							var wire uint64
 | 
				
			||||||
 | 
							for shift := uint(0); ; shift += 7 {
 | 
				
			||||||
 | 
								if shift >= 64 {
 | 
				
			||||||
 | 
									return ErrIntOverflowQuery
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if iNdEx >= l {
 | 
				
			||||||
 | 
									return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								b := dAtA[iNdEx]
 | 
				
			||||||
 | 
								iNdEx++
 | 
				
			||||||
 | 
								wire |= uint64(b&0x7F) << shift
 | 
				
			||||||
 | 
								if b < 0x80 {
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							fieldNum := int32(wire >> 3)
 | 
				
			||||||
 | 
							wireType := int(wire & 0x7)
 | 
				
			||||||
 | 
							if wireType == 4 {
 | 
				
			||||||
 | 
								return fmt.Errorf("proto: QueryParamsRequest: wiretype end group for non-group")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if fieldNum <= 0 {
 | 
				
			||||||
 | 
								return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							switch fieldNum {
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								iNdEx = preIndex
 | 
				
			||||||
 | 
								skippy, err := skipQuery(dAtA[iNdEx:])
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (skippy < 0) || (iNdEx+skippy) < 0 {
 | 
				
			||||||
 | 
									return ErrInvalidLengthQuery
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (iNdEx + skippy) > l {
 | 
				
			||||||
 | 
									return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								iNdEx += skippy
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if iNdEx > l {
 | 
				
			||||||
 | 
							return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error {
 | 
				
			||||||
 | 
						l := len(dAtA)
 | 
				
			||||||
 | 
						iNdEx := 0
 | 
				
			||||||
 | 
						for iNdEx < l {
 | 
				
			||||||
 | 
							preIndex := iNdEx
 | 
				
			||||||
 | 
							var wire uint64
 | 
				
			||||||
 | 
							for shift := uint(0); ; shift += 7 {
 | 
				
			||||||
 | 
								if shift >= 64 {
 | 
				
			||||||
 | 
									return ErrIntOverflowQuery
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if iNdEx >= l {
 | 
				
			||||||
 | 
									return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								b := dAtA[iNdEx]
 | 
				
			||||||
 | 
								iNdEx++
 | 
				
			||||||
 | 
								wire |= uint64(b&0x7F) << shift
 | 
				
			||||||
 | 
								if b < 0x80 {
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							fieldNum := int32(wire >> 3)
 | 
				
			||||||
 | 
							wireType := int(wire & 0x7)
 | 
				
			||||||
 | 
							if wireType == 4 {
 | 
				
			||||||
 | 
								return fmt.Errorf("proto: QueryParamsResponse: wiretype end group for non-group")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if fieldNum <= 0 {
 | 
				
			||||||
 | 
								return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							switch fieldNum {
 | 
				
			||||||
 | 
							case 1:
 | 
				
			||||||
 | 
								if wireType != 2 {
 | 
				
			||||||
 | 
									return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var msglen int
 | 
				
			||||||
 | 
								for shift := uint(0); ; shift += 7 {
 | 
				
			||||||
 | 
									if shift >= 64 {
 | 
				
			||||||
 | 
										return ErrIntOverflowQuery
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if iNdEx >= l {
 | 
				
			||||||
 | 
										return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									b := dAtA[iNdEx]
 | 
				
			||||||
 | 
									iNdEx++
 | 
				
			||||||
 | 
									msglen |= int(b&0x7F) << shift
 | 
				
			||||||
 | 
									if b < 0x80 {
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if msglen < 0 {
 | 
				
			||||||
 | 
									return ErrInvalidLengthQuery
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								postIndex := iNdEx + msglen
 | 
				
			||||||
 | 
								if postIndex < 0 {
 | 
				
			||||||
 | 
									return ErrInvalidLengthQuery
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if postIndex > l {
 | 
				
			||||||
 | 
									return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								iNdEx = postIndex
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								iNdEx = preIndex
 | 
				
			||||||
 | 
								skippy, err := skipQuery(dAtA[iNdEx:])
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (skippy < 0) || (iNdEx+skippy) < 0 {
 | 
				
			||||||
 | 
									return ErrInvalidLengthQuery
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (iNdEx + skippy) > l {
 | 
				
			||||||
 | 
									return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								iNdEx += skippy
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if iNdEx > l {
 | 
				
			||||||
 | 
							return io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func skipQuery(dAtA []byte) (n int, err error) {
 | 
				
			||||||
 | 
						l := len(dAtA)
 | 
				
			||||||
 | 
						iNdEx := 0
 | 
				
			||||||
 | 
						depth := 0
 | 
				
			||||||
 | 
						for iNdEx < l {
 | 
				
			||||||
 | 
							var wire uint64
 | 
				
			||||||
 | 
							for shift := uint(0); ; shift += 7 {
 | 
				
			||||||
 | 
								if shift >= 64 {
 | 
				
			||||||
 | 
									return 0, ErrIntOverflowQuery
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if iNdEx >= l {
 | 
				
			||||||
 | 
									return 0, io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								b := dAtA[iNdEx]
 | 
				
			||||||
 | 
								iNdEx++
 | 
				
			||||||
 | 
								wire |= (uint64(b) & 0x7F) << shift
 | 
				
			||||||
 | 
								if b < 0x80 {
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							wireType := int(wire & 0x7)
 | 
				
			||||||
 | 
							switch wireType {
 | 
				
			||||||
 | 
							case 0:
 | 
				
			||||||
 | 
								for shift := uint(0); ; shift += 7 {
 | 
				
			||||||
 | 
									if shift >= 64 {
 | 
				
			||||||
 | 
										return 0, ErrIntOverflowQuery
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if iNdEx >= l {
 | 
				
			||||||
 | 
										return 0, io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									iNdEx++
 | 
				
			||||||
 | 
									if dAtA[iNdEx-1] < 0x80 {
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							case 1:
 | 
				
			||||||
 | 
								iNdEx += 8
 | 
				
			||||||
 | 
							case 2:
 | 
				
			||||||
 | 
								var length int
 | 
				
			||||||
 | 
								for shift := uint(0); ; shift += 7 {
 | 
				
			||||||
 | 
									if shift >= 64 {
 | 
				
			||||||
 | 
										return 0, ErrIntOverflowQuery
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if iNdEx >= l {
 | 
				
			||||||
 | 
										return 0, io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									b := dAtA[iNdEx]
 | 
				
			||||||
 | 
									iNdEx++
 | 
				
			||||||
 | 
									length |= (int(b) & 0x7F) << shift
 | 
				
			||||||
 | 
									if b < 0x80 {
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if length < 0 {
 | 
				
			||||||
 | 
									return 0, ErrInvalidLengthQuery
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								iNdEx += length
 | 
				
			||||||
 | 
							case 3:
 | 
				
			||||||
 | 
								depth++
 | 
				
			||||||
 | 
							case 4:
 | 
				
			||||||
 | 
								if depth == 0 {
 | 
				
			||||||
 | 
									return 0, ErrUnexpectedEndOfGroupQuery
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								depth--
 | 
				
			||||||
 | 
							case 5:
 | 
				
			||||||
 | 
								iNdEx += 4
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if iNdEx < 0 {
 | 
				
			||||||
 | 
								return 0, ErrInvalidLengthQuery
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if depth == 0 {
 | 
				
			||||||
 | 
								return iNdEx, nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0, io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						ErrInvalidLengthQuery        = fmt.Errorf("proto: negative length found during unmarshaling")
 | 
				
			||||||
 | 
						ErrIntOverflowQuery          = fmt.Errorf("proto: integer overflow")
 | 
				
			||||||
 | 
						ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										148
									
								
								x/evmutil/types/query.pb.gw.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								x/evmutil/types/query.pb.gw.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,148 @@
 | 
				
			|||||||
 | 
					// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
 | 
				
			||||||
 | 
					// source: kava/evmutil/v1beta1/query.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Package types is a reverse proxy.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It translates gRPC into RESTful JSON APIs.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/golang/protobuf/descriptor"
 | 
				
			||||||
 | 
						"github.com/golang/protobuf/proto"
 | 
				
			||||||
 | 
						"github.com/grpc-ecosystem/grpc-gateway/runtime"
 | 
				
			||||||
 | 
						"github.com/grpc-ecosystem/grpc-gateway/utilities"
 | 
				
			||||||
 | 
						"google.golang.org/grpc"
 | 
				
			||||||
 | 
						"google.golang.org/grpc/codes"
 | 
				
			||||||
 | 
						"google.golang.org/grpc/grpclog"
 | 
				
			||||||
 | 
						"google.golang.org/grpc/status"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Suppress "imported and not used" errors
 | 
				
			||||||
 | 
					var _ codes.Code
 | 
				
			||||||
 | 
					var _ io.Reader
 | 
				
			||||||
 | 
					var _ status.Status
 | 
				
			||||||
 | 
					var _ = runtime.String
 | 
				
			||||||
 | 
					var _ = utilities.NewDoubleArray
 | 
				
			||||||
 | 
					var _ = descriptor.ForMessage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
 | 
				
			||||||
 | 
						var protoReq QueryParamsRequest
 | 
				
			||||||
 | 
						var metadata runtime.ServerMetadata
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 | 
				
			||||||
 | 
						return msg, metadata, err
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
 | 
				
			||||||
 | 
						var protoReq QueryParamsRequest
 | 
				
			||||||
 | 
						var metadata runtime.ServerMetadata
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msg, err := server.Params(ctx, &protoReq)
 | 
				
			||||||
 | 
						return msg, metadata, err
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
 | 
				
			||||||
 | 
					// UnaryRPC     :call QueryServer directly.
 | 
				
			||||||
 | 
					// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
 | 
				
			||||||
 | 
					// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
 | 
				
			||||||
 | 
					func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 | 
				
			||||||
 | 
							ctx, cancel := context.WithCancel(req.Context())
 | 
				
			||||||
 | 
							defer cancel()
 | 
				
			||||||
 | 
							inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
 | 
				
			||||||
 | 
							rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams)
 | 
				
			||||||
 | 
							ctx = runtime.NewServerMetadataContext(ctx, md)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but
 | 
				
			||||||
 | 
					// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
 | 
				
			||||||
 | 
					func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
 | 
				
			||||||
 | 
						conn, err := grpc.Dial(endpoint, opts...)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								if cerr := conn.Close(); cerr != nil {
 | 
				
			||||||
 | 
									grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							go func() {
 | 
				
			||||||
 | 
								<-ctx.Done()
 | 
				
			||||||
 | 
								if cerr := conn.Close(); cerr != nil {
 | 
				
			||||||
 | 
									grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}()
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return RegisterQueryHandler(ctx, mux, conn)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RegisterQueryHandler registers the http handlers for service Query to "mux".
 | 
				
			||||||
 | 
					// The handlers forward requests to the grpc endpoint over "conn".
 | 
				
			||||||
 | 
					func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
 | 
				
			||||||
 | 
						return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RegisterQueryHandlerClient registers the http handlers for service Query
 | 
				
			||||||
 | 
					// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient".
 | 
				
			||||||
 | 
					// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient"
 | 
				
			||||||
 | 
					// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
 | 
				
			||||||
 | 
					// "QueryClient" to call the correct interceptors.
 | 
				
			||||||
 | 
					func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 | 
				
			||||||
 | 
							ctx, cancel := context.WithCancel(req.Context())
 | 
				
			||||||
 | 
							defer cancel()
 | 
				
			||||||
 | 
							inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
 | 
				
			||||||
 | 
							rctx, err := runtime.AnnotateContext(ctx, mux, req)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							resp, md, err := request_Query_Params_0(rctx, inboundMarshaler, client, req, pathParams)
 | 
				
			||||||
 | 
							ctx = runtime.NewServerMetadataContext(ctx, md)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"kava", "evmutil", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false)))
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						forward_Query_Params_0 = runtime.ForwardResponseMessage
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										1378
									
								
								x/evmutil/types/tx.pb.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1378
									
								
								x/evmutil/types/tx.pb.go
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
		Reference in New Issue
	
	Block a user