<!--
order: 4
-->

# Transactions

This section defines the `sdk.Msg` concrete types that result in the state transitions defined on the previous section.

## `MsgEthereumTx`

An EVM state transition can be achieved by using the `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`](https://github.com/cosmos/cosmos-sdk/blob/v0.39.2/types/tx_msg.go#L7-L29) and [`sdk.Tx`](https://github.com/cosmos/cosmos-sdk/blob/v0.39.2/types/tx_msg.go#L33-L41) interfaces. Normally,  SDK messages only implement the former, while the latter is a group of messages bundled together.

```go
type MsgEthereumTx struct {
	// inner transaction data
	Data *types.Any `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
	// encoded storage size of the transaction
	Size_ float64 `protobuf:"fixed64,2,opt,name=size,proto3" json:"-"`
	// transaction hash in hex format
	Hash string `protobuf:"bytes,3,opt,name=hash,proto3" json:"hash,omitempty" rlp:"-"`
	// ethereum signer address in hex format. This address value is checked
	// against the address derived from the signature (V, R, S) using the
	// secp256k1 elliptic curve
	From string `protobuf:"bytes,4,opt,name=from,proto3" json:"from,omitempty"`
}
```

This message field validation is expected to fail if:

- `From` field is defined and the address is invalid
- `TxData` stateless validation fails

The transaction execution is expected to fail if:

- Any of the custom `AnteHandler` Ethereum decorators checks fail:
    - Minimum gas amount requirements for transaction
    - Tx sender account doesn't exist or hasn't enough balance for fees
    - Account sequence doesn't match the transaction `Data.AccountNonce`
    - Message signature verification fails
- EVM contract creation (i.e `evm.Create`) fails, or `evm.Call` fails

### Conversion

The `MsgEthreumTx` can be converted to the go-ethereum `Transaction` and `Message` types in order to create and call evm contracts.

```go
// AsTransaction creates an Ethereum Transaction type from the msg fields
func (msg MsgEthereumTx) AsTransaction() *ethtypes.Transaction {
	txData, err := UnpackTxData(msg.Data)
	if err != nil {
		return nil
	}

	return ethtypes.NewTx(txData.AsEthereumData())
}

// AsMessage returns the transaction as a core.Message.
func (tx *Transaction) AsMessage(s Signer, baseFee *big.Int) (Message, error) {
	msg := Message{
		nonce:      tx.Nonce(),
		gasLimit:   tx.Gas(),
		gasPrice:   new(big.Int).Set(tx.GasPrice()),
		gasFeeCap:  new(big.Int).Set(tx.GasFeeCap()),
		gasTipCap:  new(big.Int).Set(tx.GasTipCap()),
		to:         tx.To(),
		amount:     tx.Value(),
		data:       tx.Data(),
		accessList: tx.AccessList(),
		isFake:     false,
	}
	// If baseFee provided, set gasPrice to effectiveGasPrice.
	if baseFee != nil {
		msg.gasPrice = math.BigMin(msg.gasPrice.Add(msg.gasTipCap, baseFee), msg.gasFeeCap)
	}
	var err error
	msg.from, err = Sender(s, tx)
	return msg, err
}
```

### Signing

In order for the signature verification to be valid, the  `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 EIP155 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.

```go
// 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
// EIP155 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
func (msg *MsgEthereumTx) Sign(ethSigner ethtypes.Signer, keyringSigner keyring.Signer) error {
	from := msg.GetFrom()
	if from.Empty() {
		return fmt.Errorf("sender address not defined for message")
	}

	tx := msg.AsTransaction()
	txHash := ethSigner.Hash(tx)

	sig, _, err := keyringSigner.SignByAddress(from, txHash.Bytes())
	if err != nil {
		return err
	}

	tx, err = tx.WithSignature(ethSigner, sig)
	if err != nil {
		return err
	}

	msg.FromEthereumTx(tx)
	return nil
}
```

## TxData

The `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](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md) transaction type
- `DynamicFeeTx`: [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) transaction type. Enabled by London hard fork block
- `AccessListTx`: [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930) transaction type. Enabled by Berlin hard fork block

### `LegacyTx`

The transaction data of regular Ethereum transactions.

```go
type LegacyTx struct {
	// nonce corresponds to the account nonce (transaction sequence).
	Nonce uint64 `protobuf:"varint,1,opt,name=nonce,proto3" json:"nonce,omitempty"`
	// gas price defines the value for each gas unit
	GasPrice *github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,2,opt,name=gas_price,json=gasPrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"gas_price,omitempty"`
	// gas defines the gas limit defined for the transaction.
	GasLimit uint64 `protobuf:"varint,3,opt,name=gas,proto3" json:"gas,omitempty"`
	// hex formatted address of the recipient
	To string `protobuf:"bytes,4,opt,name=to,proto3" json:"to,omitempty"`
	// value defines the unsigned integer value of the transaction amount.
	Amount *github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,5,opt,name=value,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"value,omitempty"`
	// input defines the data payload bytes of the transaction.
	Data []byte `protobuf:"bytes,6,opt,name=data,proto3" json:"data,omitempty"`
	// v defines the signature value
	V []byte `protobuf:"bytes,7,opt,name=v,proto3" json:"v,omitempty"`
	// r defines the signature value
	R []byte `protobuf:"bytes,8,opt,name=r,proto3" json:"r,omitempty"`
	// s define the signature value
	S []byte `protobuf:"bytes,9,opt,name=s,proto3" json:"s,omitempty"`
}
```

This message field validation is expected to fail if:

- `GasPrice` is invalid (`nil` , negaitve or out of int256 bound)
- `Fee` (gasprice * gaslimit) is invalid
- `Amount` is invalid (negaitve or out of int256 bound)
- `To` address is invalid (non valid ethereum hex address)

### `DynamicFeeTx`

The transaction data of EIP-1559 dynamic fee transactions.

```go
type DynamicFeeTx struct {
	// destination EVM chain ID
	ChainID *github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"chainID"`
	// nonce corresponds to the account nonce (transaction sequence).
	Nonce uint64 `protobuf:"varint,2,opt,name=nonce,proto3" json:"nonce,omitempty"`
	// gas tip cap defines the max value for the gas tip
	GasTipCap *github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,3,opt,name=gas_tip_cap,json=gasTipCap,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"gas_tip_cap,omitempty"`
	// gas fee cap defines the max value for the gas fee
	GasFeeCap *github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,4,opt,name=gas_fee_cap,json=gasFeeCap,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"gas_fee_cap,omitempty"`
	// gas defines the gas limit defined for the transaction.
	GasLimit uint64 `protobuf:"varint,5,opt,name=gas,proto3" json:"gas,omitempty"`
	// hex formatted address of the recipient
	To string `protobuf:"bytes,6,opt,name=to,proto3" json:"to,omitempty"`
	// value defines the the transaction amount.
	Amount *github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,7,opt,name=value,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"value,omitempty"`
	// input defines the data payload bytes of the transaction.
	Data     []byte     `protobuf:"bytes,8,opt,name=data,proto3" json:"data,omitempty"`
	Accesses AccessList `protobuf:"bytes,9,rep,name=accesses,proto3,castrepeated=AccessList" json:"accessList"`
	// v defines the signature value
	V []byte `protobuf:"bytes,10,opt,name=v,proto3" json:"v,omitempty"`
	// r defines the signature value
	R []byte `protobuf:"bytes,11,opt,name=r,proto3" json:"r,omitempty"`
	// s define the signature value
	S []byte `protobuf:"bytes,12,opt,name=s,proto3" json:"s,omitempty"`
}
```

This message field validation is expected to fail if:

- `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`

The transaction data of EIP-2930 access list transactions.

```go
type AccessListTx struct {
	// destination EVM chain ID
	ChainID *github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"chainID"`
	// nonce corresponds to the account nonce (transaction sequence).
	Nonce uint64 `protobuf:"varint,2,opt,name=nonce,proto3" json:"nonce,omitempty"`
	// gas price defines the value for each gas unit
	GasPrice *github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,3,opt,name=gas_price,json=gasPrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"gas_price,omitempty"`
	// gas defines the gas limit defined for the transaction.
	GasLimit uint64 `protobuf:"varint,4,opt,name=gas,proto3" json:"gas,omitempty"`
	// hex formatted address of the recipient
	To string `protobuf:"bytes,5,opt,name=to,proto3" json:"to,omitempty"`
	// value defines the unsigned integer value of the transaction amount.
	Amount *github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,6,opt,name=value,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"value,omitempty"`
	// input defines the data payload bytes of the transaction.
	Data     []byte     `protobuf:"bytes,7,opt,name=data,proto3" json:"data,omitempty"`
	Accesses AccessList `protobuf:"bytes,8,rep,name=accesses,proto3,castrepeated=AccessList" json:"accessList"`
	// v defines the signature value
	V []byte `protobuf:"bytes,9,opt,name=v,proto3" json:"v,omitempty"`
	// r defines the signature value
	R []byte `protobuf:"bytes,10,opt,name=r,proto3" json:"r,omitempty"`
	// s define the signature value
	S []byte `protobuf:"bytes,11,opt,name=s,proto3" json:"s,omitempty"`
}
```

This message field validation is expected to fail if:

- `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`
