x/vm
module provides this EVM familiarity on a scalable, high-throughput Proof-of-Stake blockchain. It is built as a Cosmos SDK module which allows for the deployment of smart contracts, interaction with the EVM state machine (state transitions), and the use of EVM tooling. It can be used on Cosmos application-specific blockchains, which alleviate the aforementioned concerns through high transaction throughput via CometBFT, fast transaction finality, and horizontal scalability via IBC.
The x/vm
module is part of the Cosmos EVM library.
NOTE:: If you’re not familiar with the overall module structure from the SDK modules, please check this document as prerequisite reading.
x/vm
module implements the EVM as a Cosmos SDK module. It allows users to interact with the EVM by submitting Ethereum txs and executing their containing messages on the given state to evoke a state transition.
ADD = 3gas
and SSTORE = 100gas
). To calculate the gas consumption of a tx, the gas cost is multiplied by the gas price, which can change depending on the demand of the network at the time. If the network is under heavy load, you might have to pay a higher gas price to get your tx executed. If the gas limit is hit (out of gas exception) no changes to the Ethereum state are applied, except that the sender’s nonce increments and their balance goes down to pay for wasting the EVM’s time.
Smart contracts can also call other smart contracts. Each call to a new contract creates a new instance of the EVM (including a new stack and memory). Each call passes the sandbox state to the next EVM. If the gas runs out, all state changes are discarded. Otherwise, they are kept.
For further reading, please refer to:
eth_call
eth_call
allows you to execute messages against contracts. Usually, you need to send a transaction to a Geth node to include it in the mempool, then nodes gossip between each other and eventually the transaction is included in a block and gets executed. eth_call
however lets you send data to a contract and see what happens without committing a transaction.
In the Geth implementation, calling the endpoint roughly goes through the following steps:
eth_call
request is transformed to call the func (s *PublicBlockchainAPI) Call()
function using the eth
namespaceCall()
is given the transaction arguments, the block to call against and optional arguments that modify the state to call against. It then calls DoCall()
.DoCall()
transforms the arguments into a ethtypes.message
, instantiates an EVM and applies the message with core.ApplyMessage
ApplyMessage()
calls the state transition TransitionDb()
TransitionDb()
either Create()
s a new contract or Call()
s a contractevm.Call()
runs the interpreter evm.interpreter.Run()
to execute the message. If the execution fails, the state is reverted to a snapshot taken before the execution and gas is consumed.Run()
performs a loop to execute the opcodes.eth_call
request is transformed to call the func (e *PublicAPI) Call
function using the eth
namespaceCall()
calls doCall()
doCall()
transforms the arguments into a EthCallRequest
and calls EthCall()
using the query client of the evm module.EthCall()
transforms the arguments into a ethtypes.message
and calls `ApplyMessageWithConfig()ApplyMessageWithConfig()
instantiates an EVM and either Create()
s a new contract or Call()
s a contract using the Geth implementation.StateDB
interface from go-ethereum represents an EVM database for full state querying. EVM state transitions are enabled by this interface, which in the x/vm
module is implemented by the Keeper
. The implementation of this interface is what makes the Cosmos EVM compatible.
x/vm
module interacts with the CometBFT Consensus Engine over an Application Blockchain Interface (ABCI). Together, the application and CometBFT form the programs that run a complete blockchain and combine business logic with decentralized data storage.
Ethereum transactions which are submitted to the x/vm
module take part in this consensus process before being executed and changing the application state. We encourage to understand the basics of the CometBFT consensus engine in order to understand state transitions in detail.
x/vm
transaction, the result contains the Ethereum Log
s from the state machine execution that are used by the JSON-RPC Web3 server for filter querying and for processing the EVM Hooks.
The tx logs are stored in the transient store during tx execution and then emitted through cosmos events after the transaction has been processed. They can be queried via gRPC and JSON-RPC.
EndBlock
processing. They can be queried via gRPC and JSON-RPC.
x/vm
module state, functionalities that are derived from the go-ethereum StateDB
interface, and its implementation through the Keeper as well as the state implementation at genesis.
x/vm
module keeps the following objects in state:
Description | Key | Value | Store | |
---|---|---|---|---|
Code | Smart contract bytecode | []byte{1} + []byte(address) | []byte{code} | KV |
Storage | Smart contract storage | []byte{2} + [32]byte{key} | [32]byte(value) | KV |
Block Bloom | Block bloom filter, used to accumulate the bloom filter of current block, emitted to events at end blocker. | []byte{1} + []byte(tx.Hash) | protobuf([]Log) | Transient |
Tx Index | Index of current transaction in current block. | []byte{2} | BigEndian(uint64) | Transient |
Log Size | Number of the logs emitted so far in current block. Used to decide the log index of following logs. | []byte{3} | BigEndian(uint64) | Transient |
Gas Used | Amount of gas used by ethereum messages of current cosmos-sdk tx, it’s necessary when cosmos-sdk tx contains multiple ethereum messages. | []byte{4} | BigEndian(uint64) | Transient |
StateDB
interface is implemented by the StateDB
in the x/vm/statedb
module to represent an EVM database for full state querying of both contracts and accounts. Within the Ethereum protocol, StateDB
s are used to store anything within the IAVL tree and take care of caching and storing nested states.
StateDB
in the x/vm
provides the following functionalities:
EthAccount
instances from the provided address and set the value to store on the AccountKeeper
with createAccount()
. If an account with the given address already exists, this function also resets any preexisting code and storage associated with that address.
An account’s coin balance can be is managed through the BankKeeper
and can be read with GetBalance()
and updated with AddBalance()
and SubBalance()
.
GetBalance()
returns the EVM denomination balance of the provided address. The denomination is obtained from the module parameters.AddBalance()
adds the given amount to the address balance coin by minting new coins and transferring them to the address. The coin denomination is obtained from the module parameters.SubBalance()
subtracts the given amount from the address balance by transferring the coins to an escrow account and then burning them. The coin denomination is obtained from the module parameters. This function performs a no-op if the amount is negative or the user doesn’t have enough funds for the transfer.Sequence
via the auth module AccountKeeper
.
GetNonce()
retrieves the account with the given address and returns the tx sequence (i.e nonce). The function performs a no-op if the account is not found.SetNonce()
sets the given nonce as the sequence of the address’ account. If the account doesn’t exist, a new one will be created from the address.EVMKeeper
and it can be queried with GetCodeHash()
,GetCode()
& GetCodeSize()
and updated with SetCode()
.
GetCodeHash()
fetches the account from the store and returns its code hash. If the account doesn’t exist or is not an EthAccount type, it returns the empty code hash value.GetCode()
returns the code byte array associated with the given address. If the code hash from the account is empty, this function returns nil.SetCode()
stores the code byte array to the application KVStore and sets the code hash to the given account. The code is deleted from the store if it is empty.GetCodeSize()
returns the size of the contract code associated with this object, or zero if none.AddRefund()
adds the given amount of gas to the in-memory refund value.SubRefund()
subtracts the given amount of gas from the in-memory refund value. This function will panic if gas amount is greater than the current refund.GetRefund()
returns the amount of gas available for return after the tx execution finalizes. This value is reset to 0 on every transaction.EVMKeeper
. It can be queried with GetCommittedState()
, GetState()
and updated with SetState()
.
GetCommittedState()
returns the value set in store for the given key hash. If the key is not registered this function returns the empty hash.GetState()
returns the in-memory dirty state for the given key hash, if not exist load the committed value from KVStore.SetState()
sets the given hashes (key, value) to the state. If the value hash is empty, this function deletes the key from the state, the new value is kept in dirty state at first, and will be committed to KVStore in the end.Suicide()
marks the given account as suicided and clears the account balance of the EVM tokens.HasSuicided()
queries the in-memory flag to check if the account has been marked as suicided in the current transaction. Accounts that are suicided will be returned as non-nil during queries and “cleared” after the block has been committed.Exist()
and Empty()
.
Exist()
returns true if the given account exists in store or if it has been marked as suicided.
Empty()
returns true if the address meets the following conditions:
PrepareAccessList()
handles the preparatory steps for executing a state transition in regard to both EIP-2929 and EIP-2930. This method should only be called if Yolov3/Berlin/2929+2930 is applicable at the current number.
AddressInAccessList()
returns true if the address is registered.
SlotInAccessList()
checks if the address and the slots are registered.
AddAddressToAccessList()
adds the given address to the access list. If the address is already in the access list, this function performs a no-op.
AddSlotToAccessList()
adds the given (address, slot) to the access list. If the address and slot are already in the access list, this function performs a no-op.
Snapshot()
to identify the current state with a revision and revert the state to a given revision with RevertToSnapshot()
to support this feature.
Snapshot()
creates a new snapshot and returns the identifier.RevertToSnapshot(rev)
undo all the modifications up to the snapshot identified as rev
.AddLog()
you can append the given Ethereum Log
to the list of logs associated with the transaction hash kept in the current state. This function also fills in the tx hash, block hash, tx index and log index fields before setting the log to store.
Keeper
grants access to the EVM module state and implements statedb.Keeper
interface to support the StateDB
implementation. The Keeper contains a store key that allows the DB to write to a concrete subtree of the multistore that is only accessible by the EVM module. Instead of using a trie and database for querying and persistence (the StateDB
implementation), Cosmos EVM uses the Cosmos KVStore
(key-value store) and Cosmos SDK Keeper
to facilitate state transitions.
To support the interface functionality, it imports 4 module Keepers:
auth
: CRUD accountsbank
: accounting (supply) and CRUD of balancesstaking
: query historical headersfee market
: EIP-1559 base fee for processing DynamicFeeTx
after the London
hard fork has been activated on the ChainConfig
parametersx/vm
module GenesisState
defines the state necessary for initializing the chain from a previous exported height. It contains the GenesisAccounts
and the module parameters
GenesisAccount
type corresponds to an adaptation of the Ethereum GenesisAccount
type. It defines an account to be initialized in the genesis state.
Its main difference is that the one on the Cosmos EVM uses a custom Storage
type that uses a slice instead of maps for the evm State
(due to non-determinism), and that it doesn’t contain the private key field.
It is also important to note that since the auth
module on the Cosmos SDK manages the account state, the Address
field must correspond to an existing EthAccount
that is stored in the auth
’s module Keeper
(i.e AccountKeeper
). Addresses use the EIP55 hex format on genesis.json
.
x/vm
module allows for users to submit Ethereum transactions (Tx
) and execute their containing messages to evoke state transitions on the given state.
Users submit transactions client-side to broadcast it to the network. When the transaction is included in a block during consensus, it is executed server-side. We highly recommend to understand the basics of the CometBFT consensus engine to understand the State Transitions in detail.
eth_sendTransaction
JSON-RPCeth_sendTransaction
eth_sendRawTransaction
b. personal (private) namespace:personal_sendTransaction
MsgEthereumTx
is created after populating the RPC transaction using SetTxDefaults
to fill missing tx arguments with default values
Tx
fields are validated (stateless) using ValidateBasic()
Tx
is signed using the key associated with the sender address and the latest ethereum hard fork (London
, Berlin
, etc) from the ChainConfig
Tx
is built from the msg fields using the Cosmos Config builder
Tx
is broadcast in sync mode to ensure to wait for a CheckTx
execution response. Transactions are validated by the application using CheckTx()
, before being added to the mempool of the consensus engine.
RLP
hash of the transaction fields. This hash is different from the default hash used by SDK Transactions that calculates the sha256
hash of the transaction bytes.
Tx
) has been committed during consensus, it is applied to the application in a series of ABCI msgs server-side.
Each Tx
is handled by the application by calling RunTx
. After a stateless validation on each sdk.Msg
in the Tx
, the AnteHandler
confirms whether the Tx
is an Ethereum or SDK transaction. As an Ethereum transaction it’s containing msgs are then handled by the x/vm
module to update the application’s state.
anteHandler
is run for every transaction. It checks if the Tx
is an Ethereum transaction and routes it to an internal ante handler. Here, Tx
s are handled using EthereumTx extension options to process them differently than normal Cosmos SDK transactions. The antehandler
runs through a series of options and their AnteHandle
functions for each Tx
:
EthSetUpContextDecorator()
is adapted from SetUpContextDecorator from cosmos-sdk, it ignores gas consumption by setting the gas meter to infinite
EthValidateBasicDecorator(evmKeeper)
validates the fields of an Ethereum type Cosmos Tx
msg
EthSigVerificationDecorator(evmKeeper)
validates that the registered chain id is the same as the one on the message, and that the signer address matches the one defined on the message. It’s not skipped for RecheckTx, because it set From
address which is critical from other ante handler to work. Failure in RecheckTx will prevent tx to be included into block, especially when CheckTx succeed, in which case user won’t see the error message.
EthAccountVerificationDecorator(ak, bankKeeper, evmKeeper)
will verify, that the sender balance is greater than the total transaction cost. The account will be set to store if it doesn’t exist, i.e cannot be found on store. This AnteHandler decorator will fail if:
EthNonceVerificationDecorator(ak)
validates that the transaction nonces are valid and equivalent to the sender account’s current nonce.
EthGasConsumeDecorator(evmKeeper)
validates that the Ethereum tx message has enough to cover intrinsic gas (during CheckTx only) and that the sender has enough balance to pay for the gas cost. Intrinsic gas for a transaction is the amount of gas that the transaction uses before the transaction is executed. The gas is a constant value plus any cost incurred by additional bytes of data supplied with the transaction. This AnteHandler decorator will fail if:
CanTransferDecorator(evmKeeper, feeMarketKeeper)
creates an EVM from the message and calls the BlockContext CanTransfer function to see if the address can execute the transaction.
EthIncrementSenderSequenceDecorator(ak)
handles incrementing the sequence of the signer (i.e sender). If the transaction is a contract creation, the nonce will be incremented during the transaction execution and not within this AnteHandler decorator.
authante.NewMempoolFeeDecorator()
, authante.NewTxTimeoutHeightDecorator()
and authante.NewValidateMemoDecorator(ak)
are the same as for a Cosmos Tx
. Click here for more on the anteHandler
.
antehandler
, each sdk.Msg
(in this case MsgEthereumTx
) in the Tx
is delivered to the Msg Handler in the x/vm
module and runs through the following the steps:
Msg
to an ethereum Tx
type
Tx
with EVMConfig
and attempt to perform a state transition, that will only be persisted (committed) to the underlying KVStore if the transaction does not fail:
EVMConfig
is createdEVMConfig
EnableCreate
) and contract execution (EnableCall
) are enabledTo
address is nil
, create new contract using code as deployment code. Else call contract at given address with the given input as parametersTx
applied successfully
Tx
postprocessing hooks. If hooks return error, revert the whole Tx
sdk.Msg
concrete types that result in the state transitions defined on the previous section.
MsgEthereumTx
MsgEthereumTx
. This message encapsulates an Ethereum transaction data (TxData
) as a sdk.Msg
. It contains the necessary transaction data fields. Note, that the MsgEthereumTx
implements both the sdk.Msg
and sdk.Tx
interfaces. Normally, SDK messages only implement the former, while the latter is a group of messages bundled together.
From
field is defined and the address is invalidTxData
stateless validation failsAnteHandler
Ethereum decorators checks fail:
Data.AccountNonce
evm.Create
) fails, or evm.Call
fails
MsgEthreumTx
can be converted to the go-ethereum Transaction
and Message
types in order to create and call evm contracts.
TxData
must contain the v | r | s
values from the Signer
. Sign calculates a secp256k1 ECDSA signature and signs the transaction. It takes a keyring signer and the chainID to sign an Ethereum transaction according to EIP-155 standard. This method mutates the transaction as it populates the V, R, S fields of the Transaction’s Signature. The function will fail if the sender address is not defined for the msg or if the sender is not registered on the keyring.
MsgEthereumTx
supports the 3 valid Ethereum transaction data types from go-ethereum: LegacyTx
, AccessListTx
and DynamicFeeTx
. These types are defined as protobuf messages and packed into a proto.Any
interface type in the MsgEthereumTx
field.
LegacyTx
: EIP-155 transaction typeDynamicFeeTx
: EIP-1559 transaction type. Enabled by London hard fork blockAccessListTx
: EIP-2930 transaction type. Enabled by Berlin hard fork blockLegacyTx
GasPrice
is invalid (nil
, negative or out of int256 bound)Fee
(gasprice * gaslimit) is invalidAmount
is invalid (negative or out of int256 bound)To
address is invalid (non valid ethereum hex address)DynamicFeeTx
GasTipCap
is invalid (nil
, negative or overflows int256)GasFeeCap
is invalid (nil
, negative or overflows int256)GasFeeCap
is less than GasTipCap
Fee
(gas price * gas limit) is invalid (overflows int256)Amount
is invalid (negative or overflows int256)To
address is invalid (non-valid ethereum hex address)ChainID
is nil
AccessListTx
GasPrice
is invalid (nil
, negative or overflows int256)Fee
(gas price * gas limit) is invalid (overflows int256)Amount
is invalid (negative or overflows int256)To
address is invalid (non-valid ethereum hex address)ChainID
is nil
x/vm
is the Consensus connection at Commit. This connection is responsible for block execution and calls the functions InitChain
(containing InitGenesis
), BeginBlock
, DeliverTx
, EndBlock
, Commit
. InitChain
is only called the first time a new blockchain is started and DeliverTx
is called for each transaction in the block.
InitGenesis
initializes the EVM module genesis state by setting the GenesisState
fields to the store. In particular, it sets the parameters and genesis accounts (state and code).
ExportGenesis
ABCI function exports the genesis state of the EVM module. In particular, it retrieves all the accounts with their bytecode, balance and storage, the transaction logs, and the EVM parameters and chain configuration.
BeginBlock
logic is executed prior to handling the state transitions from the transactions. The main objective of this function is to:
Keeper
once one of the StateDB
functions are called during EVM state transitions.ChainID
number (obtained from the full chain-id), in case it hasn’t been set before during InitChain
EndBlock
logic occurs after executing all the state transitions from the transactions. The main objective of this function is to:
x/vm
module implements an EvmHooks
interface that extend and customize the Tx
processing logic externally.
This supports EVM contracts to call native cosmos modules by
PostTxProcessing
hook that registers custom Tx
hooks in the EvmKeeper
. These Tx
hooks are processed after the EVM state transition is finalized and doesn’t fail. Note that there are no default hooks implemented in the EVM module.
PostTxProcessing
PostTxProcessing
is only called after an EVM transaction finished successfully and delegates the call to underlying hooks. If no hook has been registered, this function returns with a nil
error.
nil
instead.
The error returned by the hooks is translated to a VM error failed to process native logs
, the detailed error message is stored in the return value. The message is sent to native modules asynchronously, there’s no way for the caller to catch and recover the error.
EVMHooks
supports a contract calling a native module to convert ERC-20 Tokens into Cosmos native Coins. Following the steps from above.
You can define and emit a Transfer
log signature in the smart contract like this:
BankSendHook
to the EvmKeeper
. It recognizes the ethereum tx Log
and converts it to a call to the bank module’s SendCoinsFromAccountToAccount
method:
app.go
:
x/vm
module emits the Cosmos SDK events after a state execution. The EVM module emits events of the relevant transaction fields, as well as the transaction logs (ethereum events).
Type | Attribute Key | Attribute Value |
---|---|---|
ethereum_tx | "amount" | {amount} |
ethereum_tx | "recipient" | {hex_address} |
ethereum_tx | "contract" | {hex_address} |
ethereum_tx | "txHash" | {hex_hash} |
ethereum_tx | "ethereumTxHash" | {hex_hash} |
ethereum_tx | "txIndex" | {tx_index} |
ethereum_tx | "txGasUsed" | {gas_used} |
tx_log | "txLog" | {tx_log} |
message | "sender" | {eth_address} |
message | "action" | "ethereum" |
message | "module" | "evm" |
EndBlock
for the filter query block bloom.
Type | Attribute Key | Attribute Value |
---|---|---|
block_bloom | "bloom" | string(bloomBytes) |
Key | Type | Default Value |
---|---|---|
EVMDenom | string | "astake" |
EnableCreate | bool | true |
EnableCall | bool | true |
ExtraEIPs | []int | TBD |
ChainConfig | ChainConfig | See ChainConfig |
AllowUnprotectedTxs | bool | false |
ActivePrecompiles | []string | [] |
AccessControl | AccessControl | Permissionless EVM |
evm_denom
would be ETH
. In the case of Cosmos EVM, the default denomination is the atto stake. In terms of precision, STAKE
and ETH
share the same value, i.e. 1 STAKE = 10^18 atto stake
and 1 ETH = 10^18 wei
.
evm_denom
(i.e not "astake"
).vm.Create
function. When the parameter is disabled, it will prevent all contract creation functionality.
vm.Call
function. When the parameter is disabled, it will prevent transfers between accounts and executing a smart contract call.
Config
that apply custom jump tables.
ChainConfig
is a protobuf wrapper type that contains the same fields as the go-ethereum ChainConfig
parameters, but using *sdk.Int
types instead of *big.Int
.
By default, all block configuration fields but ConstantinopleBlock
, are enabled at genesis (height 0).
Name | Default Value |
---|---|
HomesteadBlock | 0 |
DAOForkBlock | 0 |
DAOForkSupport | true |
EIP150Block | 0 |
EIP150Hash | 0x0000000000000000000000000000000000000000000000000000000000000000 |
EIP155Block | 0 |
EIP158Block | 0 |
ByzantiumBlock | 0 |
ConstantinopleBlock | 0 |
PetersburgBlock | 0 |
IstanbulBlock | 0 |
MuirGlacierBlock | 0 |
BerlinBlock | 0 |
LondonBlock | 0 |
ArrowGlacierBlock | 0 |
GrayGlacierBlock | 0 |
MergeNetsplitBlock | 0 |
ShanghaiBlock | 0 |
CancunBlock. | 0 |
enable_create
and enable_call
have been extended to give exact control of who can access these features.
By default, the EVM is permissionless, meaning that everyone can deploy smart contracts and send EVM transaction unless they have specifically been blacklisted. The blacklisted addresses can be defined in the corresponding AccessControlList
.
By setting the individual AccessControlType
for either the create or call functionality as restricted, the EVM does not accept further interactions with the specific functionality.
When defining the control type as being permissioned, the given list of addresses is interpreted as a collection of whitelisted addresses, which are the only ones capable of deploying contracts or calling the EVM respectively.
evm
module using the CLI, JSON-RPC, gRPC or REST.
appd
commands added with the x/vm
module. You can obtain the full list by using the appd -h
command.
query
commands allow users to query evm
state.
code
Allows users to query the smart contract code at a given address.
storage
Allows users to query storage for an account with a given key and height.
tx
commands allow users to interact with the evm
module.
raw
Allows users to build cosmos transactions from raw ethereum transaction.
Verb | Method | Description |
---|---|---|
gRPC | ethermint.evm.v1.Query/Account | Get an Ethereum account |
gRPC | ethermint.evm.v1.Query/CosmosAccount | Get an Ethereum account’s Cosmos Address |
gRPC | ethermint.evm.v1.Query/ValidatorAccount | Get an Ethereum account’s from a validator consensus Address |
gRPC | ethermint.evm.v1.Query/Balance | Get the balance of a the EVM denomination for a single EthAccount. |
gRPC | ethermint.evm.v1.Query/Storage | Get the balance of all coins for a single account |
gRPC | ethermint.evm.v1.Query/Code | Get the balance of all coins for a single account |
gRPC | ethermint.evm.v1.Query/Params | Get the parameters of x/vm module |
gRPC | ethermint.evm.v1.Query/EthCall | Implements the eth_call rpc api |
gRPC | ethermint.evm.v1.Query/EstimateGas | Implements the eth_estimateGas rpc api |
gRPC | ethermint.evm.v1.Query/TraceTx | Implements the debug_traceTransaction rpc api |
gRPC | ethermint.evm.v1.Query/TraceBlock | Implements the debug_traceBlockByNumber and debug_traceBlockByHash rpc api |
GET | /ethermint/evm/v1/account/{address} | Get an Ethereum account |
GET | /ethermint/evm/v1/cosmos_account/{address} | Get an Ethereum account’s Cosmos Address |
GET | /ethermint/evm/v1/validator_account/{cons_address} | Get an Ethereum account’s from a validator consensus Address |
GET | /ethermint/evm/v1/balances/{address} | Get the balance of a the EVM denomination for a single EthAccount. |
GET | /ethermint/evm/v1/storage/{address}/{key} | Get the balance of all coins for a single account |
GET | /ethermint/evm/v1/codes/{address} | Get the balance of all coins for a single account |
GET | /ethermint/evm/v1/params | Get the parameters of x/vm module |
GET | /ethermint/evm/v1/eth_call | Implements the eth_call rpc api |
GET | /ethermint/evm/v1/estimate_gas | Implements the eth_estimateGas rpc api |
GET | /ethermint/evm/v1/trace_tx | Implements the debug_traceTransaction rpc api |
GET | /ethermint/evm/v1/trace_block | Implements the debug_traceBlockByNumber and debug_traceBlockByHash rpc api |
Verb | Method | Description |
---|---|---|
gRPC | ethermint.evm.v1.Msg/EthereumTx | Submit an Ethereum transactions |
POST | /ethermint/evm/v1/ethereum_tx | Submit an Ethereum transactions |