> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cosmos.network/llms.txt
> Use this file to discover all available pages before exploring further.

# Gas and Fees

<Note>
  **Synopsis**
  This document describes the default strategies to handle gas and fees within a Cosmos SDK application.
</Note>

<Note>
  ### Pre-requisite Readings

  * [Anatomy of a Cosmos SDK Application](/sdk/v0.47/learn/beginner/overview-app)
</Note>

## Introduction to `Gas` and `Fees`

In the Cosmos SDK, `gas` is a special unit that is used to track the consumption of resources during execution. `gas` is typically consumed whenever read and writes are made to the store, but it can also be consumed if expensive computation needs to be done. It serves two main purposes:

* Make sure blocks are not consuming too many resources and are finalized. This is implemented by default in the Cosmos SDK via the [block gas meter](#block-gas-meter).
* Prevent spam and abuse from end-user. To this end, `gas` consumed during [`message`](/sdk/v0.47/build/building-modules/messages-and-queries#messages) execution is typically priced, resulting in a `fee` (`fees = gas * gas-prices`). `fees` generally have to be paid by the sender of the `message`. Note that the Cosmos SDK does not enforce `gas` pricing by default, as there may be other ways to prevent spam (e.g. bandwidth schemes). Still, most applications implement `fee` mechanisms to prevent spam by using the [`AnteHandler`](#antehandler).

## Gas Meter

In the Cosmos SDK, `gas` is a simple alias for `uint64`, and is managed by an object called a *gas meter*. Gas meters implement the `GasMeter` interface

```go expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
package types

import (
    
	"fmt"
    "math"
)

// Gas consumption descriptors.
const (
	GasIterNextCostFlatDesc = "IterNextFlat"
	GasValuePerByteDesc     = "ValuePerByte"
	GasWritePerByteDesc     = "WritePerByte"
	GasReadPerByteDesc      = "ReadPerByte"
	GasWriteCostFlatDesc    = "WriteFlat"
	GasReadCostFlatDesc     = "ReadFlat"
	GasHasDesc              = "Has"
	GasDeleteDesc           = "Delete"
)

// Gas measured by the SDK
type Gas = uint64

// ErrorNegativeGasConsumed defines an error thrown when the amount of gas refunded results in a
// negative gas consumed amount.
type ErrorNegativeGasConsumed struct {
    Descriptor string
}

// ErrorOutOfGas defines an error thrown when an action results in out of gas.
type ErrorOutOfGas struct {
    Descriptor string
}

// ErrorGasOverflow defines an error thrown when an action results gas consumption
// unsigned integer overflow.
type ErrorGasOverflow struct {
    Descriptor string
}

// GasMeter interface to track gas consumption
type GasMeter interface {
    GasConsumed()

Gas
	GasConsumedToLimit()

Gas
	GasRemaining()

Gas
	Limit()

Gas
	ConsumeGas(amount Gas, descriptor string)

RefundGas(amount Gas, descriptor string)

IsPastLimit()

bool
	IsOutOfGas()

bool
	String()

string
}

type basicGasMeter struct {
    limit    Gas
	consumed Gas
}

// NewGasMeter returns a reference to a new basicGasMeter.
func NewGasMeter(limit Gas)

GasMeter {
    return &basicGasMeter{
    limit:    limit,
		consumed: 0,
}
}

// GasConsumed returns the gas consumed from the GasMeter.
func (g *basicGasMeter)

GasConsumed()

Gas {
    return g.consumed
}

// GasRemaining returns the gas left in the GasMeter.
func (g *basicGasMeter)

GasRemaining()

Gas {
    if g.IsPastLimit() {
    return 0
}

return g.limit - g.consumed
}

// Limit returns the gas limit of the GasMeter.
func (g *basicGasMeter)

Limit()

Gas {
    return g.limit
}

// GasConsumedToLimit returns the gas limit if gas consumed is past the limit,
// otherwise it returns the consumed gas.
// NOTE: This behaviour is only called when recovering from panic when
// BlockGasMeter consumes gas past the limit.
func (g *basicGasMeter)

GasConsumedToLimit()

Gas {
    if g.IsPastLimit() {
    return g.limit
}

return g.consumed
}

// addUint64Overflow performs the addition operation on two uint64 integers and
// returns a boolean on whether or not the result overflows.
func addUint64Overflow(a, b uint64) (uint64, bool) {
    if math.MaxUint64-a < b {
    return 0, true
}

return a + b, false
}

// ConsumeGas adds the given amount of gas to the gas consumed and panics if it overflows the limit or out of gas.
func (g *basicGasMeter)

ConsumeGas(amount Gas, descriptor string) {
    var overflow bool
	g.consumed, overflow = addUint64Overflow(g.consumed, amount)
    if overflow {
    g.consumed = math.MaxUint64
		panic(ErrorGasOverflow{
    descriptor
})
}
    if g.consumed > g.limit {
    panic(ErrorOutOfGas{
    descriptor
})
}
}

// RefundGas will deduct the given amount from the gas consumed. If the amount is greater than the
// gas consumed, the function will panic.
//
// Use case: This functionality enables refunding gas to the transaction or block gas pools so that
// EVM-compatible chains can fully support the go-ethereum StateDb interface.
// See https://github.com/cosmos/cosmos-sdk/pull/9403 for reference.
func (g *basicGasMeter)

RefundGas(amount Gas, descriptor string) {
    if g.consumed < amount {
    panic(ErrorNegativeGasConsumed{
    Descriptor: descriptor
})
}

g.consumed -= amount
}

// IsPastLimit returns true if gas consumed is past limit, otherwise it returns false.
func (g *basicGasMeter)

IsPastLimit()

bool {
    return g.consumed > g.limit
}

// IsOutOfGas returns true if gas consumed is greater than or equal to gas limit, otherwise it returns false.
func (g *basicGasMeter)

IsOutOfGas()

bool {
    return g.consumed >= g.limit
}

// String returns the BasicGasMeter's gas limit and gas consumed.
func (g *basicGasMeter)

String()

string {
    return fmt.Sprintf("BasicGasMeter:\n  limit: %d\n  consumed: %d", g.limit, g.consumed)
}

type infiniteGasMeter struct {
    consumed Gas
}

// NewInfiniteGasMeter returns a new gas meter without a limit.
func NewInfiniteGasMeter()

GasMeter {
    return &infiniteGasMeter{
    consumed: 0,
}
}

// GasConsumed returns the gas consumed from the GasMeter.
func (g *infiniteGasMeter)

GasConsumed()

Gas {
    return g.consumed
}

// GasConsumedToLimit returns the gas consumed from the GasMeter since the gas is not confined to a limit.
// NOTE: This behaviour is only called when recovering from panic when BlockGasMeter consumes gas past the limit.
func (g *infiniteGasMeter)

GasConsumedToLimit()

Gas {
    return g.consumed
}

// GasRemaining returns MaxUint64 since limit is not confined in infiniteGasMeter.
func (g *infiniteGasMeter)

GasRemaining()

Gas {
    return math.MaxUint64
}

// Limit returns MaxUint64 since limit is not confined in infiniteGasMeter.
func (g *infiniteGasMeter)

Limit()

Gas {
    return math.MaxUint64
}

// ConsumeGas adds the given amount of gas to the gas consumed and panics if it overflows the limit.
func (g *infiniteGasMeter)

ConsumeGas(amount Gas, descriptor string) {
    var overflow bool
	// TODO: Should we set the consumed field after overflow checking?
	g.consumed, overflow = addUint64Overflow(g.consumed, amount)
    if overflow {
    panic(ErrorGasOverflow{
    descriptor
})
}
}

// RefundGas will deduct the given amount from the gas consumed. If the amount is greater than the
// gas consumed, the function will panic.
//
// Use case: This functionality enables refunding gas to the trasaction or block gas pools so that
// EVM-compatible chains can fully support the go-ethereum StateDb interface.
// See https://github.com/cosmos/cosmos-sdk/pull/9403 for reference.
func (g *infiniteGasMeter)

RefundGas(amount Gas, descriptor string) {
    if g.consumed < amount {
    panic(ErrorNegativeGasConsumed{
    Descriptor: descriptor
})
}

g.consumed -= amount
}

// IsPastLimit returns false since the gas limit is not confined.
func (g *infiniteGasMeter)

IsPastLimit()

bool {
    return false
}

// IsOutOfGas returns false since the gas limit is not confined.
func (g *infiniteGasMeter)

IsOutOfGas()

bool {
    return false
}

// String returns the InfiniteGasMeter's gas consumed.
func (g *infiniteGasMeter)

String()

string {
    return fmt.Sprintf("InfiniteGasMeter:\n  consumed: %d", g.consumed)
}

// GasConfig defines gas cost for each operation on KVStores
type GasConfig struct {
    HasCost          Gas
	DeleteCost       Gas
	ReadCostFlat     Gas
	ReadCostPerByte  Gas
	WriteCostFlat    Gas
	WriteCostPerByte Gas
	IterNextCostFlat Gas
}

// KVGasConfig returns a default gas config for KVStores.
func KVGasConfig()

GasConfig {
    return GasConfig{
    HasCost:          1000,
    DeleteCost:       1000,
    ReadCostFlat:     1000,
    ReadCostPerByte:  3,
    WriteCostFlat:    2000,
    WriteCostPerByte: 30,
    IterNextCostFlat: 30,
}
}

// TransientGasConfig returns a default gas config for TransientStores.
func TransientGasConfig()

GasConfig {
    return GasConfig{
    HasCost:          100,
    DeleteCost:       100,
    ReadCostFlat:     100,
    ReadCostPerByte:  0,
    WriteCostFlat:    200,
    WriteCostPerByte: 3,
    IterNextCostFlat: 3,
}
}
```

where:

* `GasConsumed()` returns the amount of gas that was consumed by the gas meter instance.
* `GasConsumedToLimit()` returns the amount of gas that was consumed by gas meter instance, or the limit if it is reached.
* `GasRemaining()` returns the gas left in the GasMeter.
* `Limit()` returns the limit of the gas meter instance. `0` if the gas meter is infinite.
* `ConsumeGas(amount Gas, descriptor string)` consumes the amount of `gas` provided. If the `gas` overflows, it panics with the `descriptor` message. If the gas meter is not infinite, it panics if `gas` consumed goes above the limit.
* `RefundGas()` deducts the given amount from the gas consumed. This functionality enables refunding gas to the transaction or block gas pools so that EVM-compatible chains can fully support the go-ethereum StateDB interface.
* `IsPastLimit()` returns `true` if the amount of gas consumed by the gas meter instance is strictly above the limit, `false` otherwise.
* `IsOutOfGas()` returns `true` if the amount of gas consumed by the gas meter instance is above or equal to the limit, `false` otherwise.

The gas meter is generally held in [`ctx`](/sdk/v0.47/learn/advanced/context), and consuming gas is done with the following pattern:

```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
ctx.GasMeter().ConsumeGas(amount, "description")
```

By default, the Cosmos SDK makes use of two different gas meters, the [main gas meter](#main-gas-meter) and the [block gas meter](#block-gas-meter).

### Main Gas Meter

`ctx.GasMeter()` is the main gas meter of the application. The main gas meter is initialized in `BeginBlock` via `setDeliverState`, and then tracks gas consumption during execution sequences that lead to state-transitions, i.e. those originally triggered by [`BeginBlock`](/sdk/v0.47/learn/advanced/baseapp#beginblock), [`DeliverTx`](/sdk/v0.47/learn/advanced/baseapp#delivertx) and [`EndBlock`](/sdk/v0.47/learn/advanced/baseapp#endblock). At the beginning of each `DeliverTx`, the main gas meter **must be set to 0** in the [`AnteHandler`](#antehandler), so that it can track gas consumption per-transaction.

Gas consumption can be done manually, generally by the module developer in the [`BeginBlocker`, `EndBlocker`](/sdk/v0.47/build/building-modules/beginblock-endblock) or [`Msg` service](/sdk/v0.47/build/building-modules/msg-services), but most of the time it is done automatically whenever there is a read or write to the store. This automatic gas consumption logic is implemented in a special store called [`GasKv`](/sdk/v0.47/learn/advanced/store#gaskv-store).

### Block Gas Meter

`ctx.BlockGasMeter()` is the gas meter used to track gas consumption per block and make sure it does not go above a certain limit. A new instance of the `BlockGasMeter` is created each time [`BeginBlock`](/sdk/v0.47/learn/advanced/baseapp#beginblock) is called. The `BlockGasMeter` is finite, and the limit of gas per block is defined in the application's consensus parameters. By default, Cosmos SDK applications use the default consensus parameters provided by CometBFT:

```go expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
package types

import (
    
	"errors"
    "fmt"
    "time"
    "github.com/cometbft/cometbft/crypto/ed25519"
    "github.com/cometbft/cometbft/crypto/secp256k1"
    "github.com/cometbft/cometbft/crypto/tmhash"
	cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
)

const (
	// MaxBlockSizeBytes is the maximum permitted size of the blocks.
	MaxBlockSizeBytes = 104857600 // 100MB

	// BlockPartSizeBytes is the size of one block part.
	BlockPartSizeBytes uint32 = 65536 // 64kB

	// MaxBlockPartsCount is the maximum number of block parts.
	MaxBlockPartsCount = (MaxBlockSizeBytes / BlockPartSizeBytes) + 1

	ABCIPubKeyTypeEd25519   = ed25519.KeyType
	ABCIPubKeyTypeSecp256k1 = secp256k1.KeyType
)

var ABCIPubKeyTypesToNames = map[string]string{
    ABCIPubKeyTypeEd25519:   ed25519.PubKeyName,
	ABCIPubKeyTypeSecp256k1: secp256k1.PubKeyName,
}

// ConsensusParams contains consensus critical parameters that determine the
// validity of blocks.
type ConsensusParams struct {
    Block     BlockParams     `json:"block"`
	Evidence  EvidenceParams  `json:"evidence"`
	Validator ValidatorParams `json:"validator"`
	Version   VersionParams   `json:"version"`
}

// BlockParams define limits on the block size and gas plus minimum time
// between blocks.
type BlockParams struct {
    MaxBytes int64 `json:"max_bytes"`
	MaxGas   int64 `json:"max_gas"`
}

// EvidenceParams determine how we handle evidence of malfeasance.
type EvidenceParams struct {
    MaxAgeNumBlocks int64         `json:"max_age_num_blocks"` // only accept new evidence more recent than this
	MaxAgeDuration  time.Duration `json:"max_age_duration"`
	MaxBytes        int64         `json:"max_bytes"`
}

// ValidatorParams restrict the public key types validators can use.
// NOTE: uses ABCI pubkey naming, not Amino names.
type ValidatorParams struct {
    PubKeyTypes []string `json:"pub_key_types"`
}

type VersionParams struct {
    App uint64 `json:"app"`
}

// DefaultConsensusParams returns a default ConsensusParams.
func DefaultConsensusParams() *ConsensusParams {
    return &ConsensusParams{
    Block:     DefaultBlockParams(),
    Evidence:  DefaultEvidenceParams(),
    Validator: DefaultValidatorParams(),
    Version:   DefaultVersionParams(),
}
}

// DefaultBlockParams returns a default BlockParams.
func DefaultBlockParams()

BlockParams {
    return BlockParams{
    MaxBytes: 22020096, // 21MB
		MaxGas:   -1,
}
}

// DefaultEvidenceParams returns a default EvidenceParams.
func DefaultEvidenceParams()

EvidenceParams {
    return EvidenceParams{
    MaxAgeNumBlocks: 100000, // 27.8 hrs at 1block/s
		MaxAgeDuration:  48 * time.Hour,
    MaxBytes:        1048576, // 1MB
}
}

// DefaultValidatorParams returns a default ValidatorParams, which allows
// only ed25519 pubkeys.
func DefaultValidatorParams()

ValidatorParams {
    return ValidatorParams{
    PubKeyTypes: []string{
    ABCIPubKeyTypeEd25519
},
}
}

func DefaultVersionParams()

VersionParams {
    return VersionParams{
    App: 0,
}
}

func IsValidPubkeyType(params ValidatorParams, pubkeyType string)

bool {
    for i := 0; i < len(params.PubKeyTypes); i++ {
    if params.PubKeyTypes[i] == pubkeyType {
    return true
}
	
}

return false
}

// Validate validates the ConsensusParams to ensure all values are within their
// allowed limits, and returns an error if they are not.
func (params ConsensusParams)

ValidateBasic()

error {
    if params.Block.MaxBytes <= 0 {
    return fmt.Errorf("block.MaxBytes must be greater than 0. Got %d",
			params.Block.MaxBytes)
}
    if params.Block.MaxBytes > MaxBlockSizeBytes {
    return fmt.Errorf("block.MaxBytes is too big. %d > %d",
			params.Block.MaxBytes, MaxBlockSizeBytes)
}
    if params.Block.MaxGas < -1 {
    return fmt.Errorf("block.MaxGas must be greater or equal to -1. Got %d",
			params.Block.MaxGas)
}
    if params.Evidence.MaxAgeNumBlocks <= 0 {
    return fmt.Errorf("evidence.MaxAgeNumBlocks must be greater than 0. Got %d",
			params.Evidence.MaxAgeNumBlocks)
}
    if params.Evidence.MaxAgeDuration <= 0 {
    return fmt.Errorf("evidence.MaxAgeDuration must be grater than 0 if provided, Got %v",
			params.Evidence.MaxAgeDuration)
}
    if params.Evidence.MaxBytes > params.Block.MaxBytes {
    return fmt.Errorf("evidence.MaxBytesEvidence is greater than upper bound, %d > %d",
			params.Evidence.MaxBytes, params.Block.MaxBytes)
}
    if params.Evidence.MaxBytes < 0 {
    return fmt.Errorf("evidence.MaxBytes must be non negative. Got: %d",
			params.Evidence.MaxBytes)
}
    if len(params.Validator.PubKeyTypes) == 0 {
    return errors.New("len(Validator.PubKeyTypes)

must be greater than 0")
}

	// Check if keyType is a known ABCIPubKeyType
    for i := 0; i < len(params.Validator.PubKeyTypes); i++ {
    keyType := params.Validator.PubKeyTypes[i]
    if _, ok := ABCIPubKeyTypesToNames[keyType]; !ok {
    return fmt.Errorf("params.Validator.PubKeyTypes[%d], %s, is an unknown pubkey type",
				i, keyType)
}
	
}

return nil
}

// Hash returns a hash of a subset of the parameters to store in the block header.
// Only the Block.MaxBytes and Block.MaxGas are included in the hash.
// This allows the ConsensusParams to evolve more without breaking the block
// protocol. No need for a Merkle tree here, just a small struct to hash.
func (params ConsensusParams)

Hash() []byte {
    hasher := tmhash.New()
    hp := cmtproto.HashedParams{
    BlockMaxBytes: params.Block.MaxBytes,
    BlockMaxGas:   params.Block.MaxGas,
}

bz, err := hp.Marshal()
    if err != nil {
    panic(err)
}

	_, err = hasher.Write(bz)
    if err != nil {
    panic(err)
}

return hasher.Sum(nil)
}

// Update returns a copy of the params with updates from the non-zero fields of p2.
// NOTE: note: must not modify the original
func (params ConsensusParams)

Update(params2 *cmtproto.ConsensusParams)

ConsensusParams {
    res := params // explicit copy
    if params2 == nil {
    return res
}

	// we must defensively consider any structs may be nil
    if params2.Block != nil {
    res.Block.MaxBytes = params2.Block.MaxBytes
		res.Block.MaxGas = params2.Block.MaxGas
}
    if params2.Evidence != nil {
    res.Evidence.MaxAgeNumBlocks = params2.Evidence.MaxAgeNumBlocks
		res.Evidence.MaxAgeDuration = params2.Evidence.MaxAgeDuration
		res.Evidence.MaxBytes = params2.Evidence.MaxBytes
}
    if params2.Validator != nil {
		// Copy params2.Validator.PubkeyTypes, and set result's value to the copy.
		// This avoids having to initialize the slice to 0 values, and then write to it again.
		res.Validator.PubKeyTypes = append([]string{
}, params2.Validator.PubKeyTypes...)
}
    if params2.Version != nil {
    res.Version.App = params2.Version.App
}

return res
}

func (params *ConsensusParams)

ToProto()

cmtproto.ConsensusParams {
    return cmtproto.ConsensusParams{
    Block: &cmtproto.BlockParams{
    MaxBytes: params.Block.MaxBytes,
    MaxGas:   params.Block.MaxGas,
},
    Evidence: &cmtproto.EvidenceParams{
    MaxAgeNumBlocks: params.Evidence.MaxAgeNumBlocks,
    MaxAgeDuration:  params.Evidence.MaxAgeDuration,
    MaxBytes:        params.Evidence.MaxBytes,
},
    Validator: &cmtproto.ValidatorParams{
    PubKeyTypes: params.Validator.PubKeyTypes,
},
    Version: &cmtproto.VersionParams{
    App: params.Version.App,
},
}
}

func ConsensusParamsFromProto(pbParams cmtproto.ConsensusParams)

ConsensusParams {
    return ConsensusParams{
    Block: BlockParams{
    MaxBytes: pbParams.Block.MaxBytes,
    MaxGas:   pbParams.Block.MaxGas,
},
    Evidence: EvidenceParams{
    MaxAgeNumBlocks: pbParams.Evidence.MaxAgeNumBlocks,
    MaxAgeDuration:  pbParams.Evidence.MaxAgeDuration,
    MaxBytes:        pbParams.Evidence.MaxBytes,
},
    Validator: ValidatorParams{
    PubKeyTypes: pbParams.Validator.PubKeyTypes,
},
    Version: VersionParams{
    App: pbParams.Version.App,
},
}
}
```

When a new [transaction](/sdk/v0.47/learn/advanced/transactions) is being processed via `DeliverTx`, the current value of `BlockGasMeter` is checked to see if it is above the limit. If it is, `DeliverTx` returns immediately. This can happen even with the first transaction in a block, as `BeginBlock` itself can consume gas. If not, the transaction is processed normally. At the end of `DeliverTx`, the gas tracked by `ctx.BlockGasMeter()` is increased by the amount consumed to process the transaction:

```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
ctx.BlockGasMeter().ConsumeGas(
	ctx.GasMeter().GasConsumedToLimit(),
	"block gas meter",
)
```

## AnteHandler

The `AnteHandler` is run for every transaction during `CheckTx` and `DeliverTx`, before a Protobuf `Msg` service method for each `sdk.Msg` in the transaction.

The anteHandler is not implemented in the core Cosmos SDK but in a module. That said, most applications today use the default implementation defined in the [`auth` module](https://github.com/cosmos/cosmos-sdk/tree/main/x/auth). Here is what the `anteHandler` is intended to do in a normal Cosmos SDK application:

* Verify that the transactions are of the correct type. Transaction types are defined in the module that implements the `anteHandler`, and they follow the transaction interface:

```go expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
package types

import (
    
	"encoding/json"
	fmt "fmt"
    "github.com/cosmos/gogoproto/proto"
    "github.com/cosmos/cosmos-sdk/codec"
	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
)

type (
	// Msg defines the interface a transaction message must fulfill.
	Msg interface {
    proto.Message

		// ValidateBasic does a simple validation check that
		// doesn't require access to any other information.
		ValidateBasic()

error

		// GetSigners returns the addrs of signers that must sign.
		// CONTRACT: All signatures must be present to be valid.
		// CONTRACT: Returns addrs in some deterministic order.
		GetSigners() []AccAddress
}

	// Fee defines an interface for an application application-defined concrete
	// transaction type to be able to set and return the transaction fee.
	Fee interface {
    GetGas()

uint64
		GetAmount()

Coins
}

	// Signature defines an interface for an application application-defined
	// concrete transaction type to be able to set and return transaction signatures.
	Signature interface {
    GetPubKey()

cryptotypes.PubKey
		GetSignature() []byte
}

	// Tx defines the interface a transaction must fulfill.
	Tx interface {
		// GetMsgs gets the all the transaction's messages.
		GetMsgs() []Msg

		// ValidateBasic does a simple and lightweight validation check that doesn't
		// require access to any other information.
		ValidateBasic()

error
}

	// FeeTx defines the interface to be implemented by Tx to use the FeeDecorators
	FeeTx interface {
    Tx
		GetGas()

uint64
		GetFee()

Coins
		FeePayer()

AccAddress
		FeeGranter()

AccAddress
}

	// TxWithMemo must have GetMemo()

method to use ValidateMemoDecorator
	TxWithMemo interface {
    Tx
		GetMemo()

string
}

	// TxWithTimeoutHeight extends the Tx interface by allowing a transaction to
	// set a height timeout.
	TxWithTimeoutHeight interface {
    Tx

		GetTimeoutHeight()

uint64
}
)

// TxDecoder unmarshals transaction bytes
type TxDecoder func(txBytes []byte) (Tx, error)

// TxEncoder marshals transaction to bytes
type TxEncoder func(tx Tx) ([]byte, error)

// MsgTypeURL returns the TypeURL of a `sdk.Msg`.
func MsgTypeURL(msg Msg)

string {
    return "/" + proto.MessageName(msg)
}

// GetMsgFromTypeURL returns a `sdk.Msg` message type from a type URL
func GetMsgFromTypeURL(cdc codec.Codec, input string) (Msg, error) {
    var msg Msg
	bz, err := json.Marshal(struct {
    Type string `json:"@type"`
}{
    Type: input,
})
    if err != nil {
    return nil, err
}
    if err := cdc.UnmarshalInterfaceJSON(bz, &msg); err != nil {
    return nil, fmt.Errorf("failed to determine sdk.Msg for %s URL : %w", input, err)
}

return msg, nil
}
```

This enables developers to play with various types for the transaction of their application. In the default `auth` module, the default transaction type is `Tx`:

```protobuf theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
// Reference: https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/tx/v1beta1/tx.proto#L13-L26
```

* Verify signatures for each [`message`](/sdk/v0.47/build/building-modules/messages-and-queries#messages) contained in the transaction. Each `message` should be signed by one or multiple sender(s), and these signatures must be verified in the `anteHandler`.
* During `CheckTx`, verify that the gas prices provided with the transaction is greater than the local `min-gas-prices` (as a reminder, gas-prices can be deducted from the following equation: `fees = gas * gas-prices`). `min-gas-prices` is a parameter local to each full-node and used during `CheckTx` to discard transactions that do not provide a minimum amount of fees. This ensures that the mempool cannot be spammed with garbage transactions.
* Verify that the sender of the transaction has enough funds to cover for the `fees`. When the end-user generates a transaction, they must indicate 2 of the 3 following parameters (the third one being implicit): `fees`, `gas` and `gas-prices`. This signals how much they are willing to pay for nodes to execute their transaction. The provided `gas` value is stored in a parameter called `GasWanted` for later use.
* Set `newCtx.GasMeter` to 0, with a limit of `GasWanted`. **This step is crucial**, as it not only makes sure the transaction cannot consume infinite gas, but also that `ctx.GasMeter` is reset in-between each `DeliverTx` (`ctx` is set to `newCtx` after `anteHandler` is run, and the `anteHandler` is run each time `DeliverTx` is called).

As explained above, the `anteHandler` returns a maximum limit of `gas` the transaction can consume during execution called `GasWanted`. The actual amount consumed in the end is denominated `GasUsed`, and we must therefore have `GasUsed =< GasWanted`. Both `GasWanted` and `GasUsed` are relayed to the underlying consensus engine when [`DeliverTx`](/sdk/v0.47/learn/advanced/baseapp#delivertx) returns.
