Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
979b7d5
WIP created eth_tacSimulate rpc method
AkKoks Feb 5, 2026
0bbf572
created proto-gen github actions workflow
AkKoks Feb 5, 2026
44a9428
Merge commit 'c51e74f244dcd42dda5ef2161381fa983fee8686' into tac-simu…
AkKoks Feb 5, 2026
4997eb2
chore: regenerate protobuf files
AkKoks Feb 5, 2026
5231538
Merge commit '4997eb23377c5f7f067e49c4f319465daa5b892a' into tac-simu…
AkKoks Feb 5, 2026
13da91a
added state override to stateDB and state transition to ApplyMessageW…
AkKoks Feb 5, 2026
c205d28
finish grpc query server
AkKoks Feb 5, 2026
048d4b6
fix proto-gen github action
AkKoks Feb 5, 2026
9e8bcd5
little refactor
AkKoks Feb 5, 2026
e0d2cf1
fix TestParams with new ed25519 precompile
AkKoks Feb 5, 2026
afff503
add test for TacSimulate for grpc_query server
AkKoks Feb 5, 2026
096e5db
Merge commit '99e4891dd9a488faaee80ec1a308bca263dc033c' into tac-simu…
AkKoks Feb 6, 2026
cb40e7b
fix precompile override
AkKoks Feb 6, 2026
c88d28a
Merge commit '8e01bec6500c12869a516df899f2e2c670265587' into tac-simu…
AkKoks Feb 9, 2026
95c645f
little fix naming
AkKoks Feb 9, 2026
0319c80
fix returned log types
AkKoks Feb 9, 2026
2c357dd
fix stateoverride type from map ptr to just map
AkKoks Feb 9, 2026
9890068
fix state override with clean full state obj storage
AkKoks Feb 11, 2026
607c986
state transition tests
AkKoks Feb 12, 2026
a097b38
gen new proto type TacSimulateResponse
AkKoks Feb 17, 2026
d235109
- fix TacSimulate grpc to return estimatedGas value in response.
AkKoks Feb 17, 2026
505d78b
- eth_tacSimulate moved to "tac" namespace and renamed tac_simulate
AkKoks Feb 17, 2026
a3949a4
fix comments
AkKoks Feb 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,275 changes: 1,965 additions & 310 deletions api/cosmos/evm/vm/v1/query.pulsar.go

Large diffs are not rendered by default.

40 changes: 40 additions & 0 deletions api/cosmos/evm/vm/v1/query_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 39 additions & 0 deletions proto/cosmos/evm/vm/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ service Query {
option (google.api.http).get = "/cosmos/evm/vm/v1/eth_call";
}

// TacSimulate implements the custom `tac_simulate` rpc api which supports state override
rpc TacSimulate(TacSimulateRequest) returns (TacSimulateResponse) {
option (google.api.http).get = "/cosmos/evm/vm/v1/tac_simulate";
}

// EstimateGas implements the `eth_estimateGas` rpc api
rpc EstimateGas(EthCallRequest) returns (EstimateGasResponse) {
option (google.api.http).get = "/cosmos/evm/vm/v1/estimate_gas";
Expand Down Expand Up @@ -260,6 +265,40 @@ message EthCallRequest {
int64 chain_id = 4;
}

// TacSimulateRequest defines TacSimulate request
message TacSimulateRequest {
// args uses the same json format as the json rpc api.
bytes args = 1;
// state_override defines the state override for the call, it uses the same json format as the json rpc api.
bytes state_override = 2;
// gas_cap defines the default gas cap to be used
uint64 gas_cap = 3;
// proposer_address of the requested block in hex format
bytes proposer_address = 4
[ (gogoproto.casttype) =
"github.com/cosmos/cosmos-sdk/types.ConsAddress" ];
// chain_id is the eip155 chain id parsed from the requested block header
int64 chain_id = 5;
}

// TacSimulateResponse defines TacSimulate response
message TacSimulateResponse {
// hash of the ethereum transaction in hex format
string hash = 1;
// logs contains the proto-compatible ethereum logs
repeated Log logs = 2;
// ret is the returned data from evm function (result or data supplied with
// revert opcode)
bytes ret = 3;
// vm_error is the error returned by vm execution
string vm_error = 4;
// gas_used specifies how much gas was consumed by the EVM execution
uint64 gas_used = 5;
// gas_estimated is the estimated minimum gas limit needed to execute
// the transaction successfully (result of binary search, like eth_estimateGas)
uint64 gas_estimated = 6;
}

// EstimateGasResponse defines EstimateGas response
message EstimateGasResponse {
// gas returns the estimated gas
Expand Down
18 changes: 18 additions & 0 deletions rpc/apis.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/cosmos/evm/rpc/namespaces/ethereum/miner"
"github.com/cosmos/evm/rpc/namespaces/ethereum/net"
"github.com/cosmos/evm/rpc/namespaces/ethereum/personal"
"github.com/cosmos/evm/rpc/namespaces/ethereum/tac"
"github.com/cosmos/evm/rpc/namespaces/ethereum/txpool"
"github.com/cosmos/evm/rpc/namespaces/ethereum/web3"
"github.com/cosmos/evm/types"
Expand All @@ -37,6 +38,7 @@ const (
TxPoolNamespace = "txpool"
DebugNamespace = "debug"
MinerNamespace = "miner"
TacNamespace = "tac"

apiVersion = "1.0"
)
Expand Down Expand Up @@ -155,6 +157,22 @@ func init() {
},
}
},
TacNamespace: func(ctx *server.Context,
clientCtx client.Context,
_ *rpcclient.WSClient,
allowUnprotectedTxs bool,
indexer types.EVMTxIndexer,
) []rpc.API {
evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer)
return []rpc.API{
{
Namespace: TacNamespace,
Version: apiVersion,
Service: tac.NewTacAPI(ctx.Logger, evmBackend),
Public: true,
},
}
},
}
}

Expand Down
1 change: 1 addition & 0 deletions rpc/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ type EVMBackend interface {
SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.TransactionArgs, error)
EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *rpctypes.BlockNumber) (hexutil.Uint64, error)
DoCall(args evmtypes.TransactionArgs, blockNr rpctypes.BlockNumber) (*evmtypes.MsgEthereumTxResponse, error)
DoTacSimulate(args evmtypes.TransactionArgs, blockNr rpctypes.BlockNumber, stateOverride evmtypes.StateOverride) (*evmtypes.TacSimulateResponse, error)
GasPrice() (*hexutil.Big, error)

// Filter API
Expand Down
60 changes: 60 additions & 0 deletions rpc/backend/call_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,66 @@ func (b *Backend) DoCall(
return res, nil
}

func (b *Backend) DoTacSimulate(
args evmtypes.TransactionArgs,
blockNr rpctypes.BlockNumber,
stateOverride evmtypes.StateOverride,
) (*evmtypes.TacSimulateResponse, error) {
bz, err := json.Marshal(&args)
if err != nil {
return nil, err
}

header, err := b.TendermintBlockByNumber(blockNr)
if err != nil {
// the error message imitates geth behavior
return nil, errors.New("header not found")
}

overrideBz, err := json.Marshal(stateOverride)
if err != nil {
return nil, err
}

req := evmtypes.TacSimulateRequest{
Args: bz,
GasCap: b.RPCGasCap(),
ProposerAddress: sdk.ConsAddress(header.Block.ProposerAddress),
ChainId: b.chainID.Int64(),
StateOverride: overrideBz,
}

// From ContextWithHeight: if the provided height is 0,
// it will return an empty context and the gRPC query will use
// the latest block height for querying.
ctx := rpctypes.ContextWithHeight(blockNr.Int64())
timeout := b.RPCEVMTimeout()

// Setup context so it may be canceled the call has completed
// or, in case of unmetered gas, setup a context with a timeout.
var cancel context.CancelFunc
if timeout > 0 {
ctx, cancel = context.WithTimeout(ctx, timeout)
} else {
ctx, cancel = context.WithCancel(ctx)
}

// Make sure the context is canceled when the call has completed
// this makes sure resources are cleaned up.
defer cancel()

res, err := b.queryClient.TacSimulate(ctx, &req)
if err != nil {
return nil, err
}

if err = handleRevertError(res.VmError, res.Ret); err != nil {
return nil, err
}

return res, nil
}

// GasPrice returns the current gas price based on Cosmos EVM' gas price oracle.
func (b *Backend) GasPrice() (*hexutil.Big, error) {
var (
Expand Down
Loading
Loading