> ## Documentation Index
> Fetch the complete documentation index at: https://seilabs-docs-evm-cookbook.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Transactions

> Comprehensive guide on Transactions on Sei. Learn key concepts, commands, and best practices.

Sei supports EVM transactions, so it works with Ethereum-based tools and contracts. Transactions are signed messages from an externally owned account (EOA) that trigger state changes on the blockchain.

## Transaction lifecycle

| Stage | Description |
| - | - |
| 1. Creation | An EOA creates a transaction and specifies the recipient, value, gas parameters, and other fields. |
| 2. Signing | The sender's private key signs the transaction and creates a valid signature. |
| 3. Submission | The sender submits the signed transaction to the network through an RPC endpoint. |
| 4. Mempool | The transaction enters the mempool (transaction pool), where it waits for inclusion in a block. |
| 5. Execution | When a validator selects the transaction, the EVM executes it and updates the state. |
| 6. Validation | The consensus mechanism validates the transaction and its state changes. |
| 7. Confirmation | After validation, the transaction is included in a block and confirmed on-chain. |
| 8. Finality | On Sei, transactions reach immediate finality when they are included in a block. |

<Info>
  On other EVM chains, you need to wait for multiple confirmations. Sei's consensus mechanism gives immediate transaction finality. After a transaction is included in a block, it cannot be reversed.
</Info>

## Gas mechanics

Gas is a unit of computational work in the EVM. It helps prevent spam and allocate resources efficiently:

| Term | Description |
| - | - |
| Gas limit | The maximum amount of gas the transaction may consume. The sender sets it. |
| Base fee | The minimum gas price required for inclusion in a block. On Sei, the base fee is not burned. All fees go to validators. |
| Priority fee | An extra fee (tip) paid to validators for faster inclusion. |
| Gas price | In legacy transactions, the price per unit of gas the sender is willing to pay. |
| Effective gas price | The actual price paid per unit of gas (base fee + priority fee in EIP-1559). |

<Warning>
  **Gas requirements for common operations:**

  * Simple SEI transfer: 21,000 gas
  * ERC-20 transfer: approximately 45,000 gas
  * Contract deployment: Depends on contract size and complexity
  * Always estimate gas with `eth_estimateGas` before you send transactions
</Warning>

## Transaction structure

EVM transactions on Sei follow the Ethereum transaction format and its standard properties:

<Tabs>
  <Tab title="Transaction Properties">
    | Property | Description |
    | - | - |
    | `from` | The address of the sender that signs the transaction. This must be an externally owned account (EOA), because contract accounts cannot send transactions. |
    | `to` | The receiving address. If it is an EOA, the transaction transfers value. If it is a contract address, the transaction executes the contract code. If it is empty or null, the transaction creates a new contract. |
    | `signature` | The cryptographic signature generated when the sender's private key signs the transaction. It confirms that the sender authorized the transaction, and it includes the v, r, and s components. |
    | `nonce` | A sequentially incrementing counter that indicates the transaction number from the account. It prevents replay attacks and keeps transactions in order. |
    | `data` | The input data (also called 'input' or 'calldata') for contract execution. For simple transfers, this is usually empty. For contract interactions, this contains the function selector and encoded arguments. |
    | `value` | The amount of SEI to transfer from the sender to the recipient, in wei (1 SEI equals 1e+18 wei). |
    | `gasLimit` | The maximum number of gas units that the transaction can consume. Transaction objects often call it 'gas'. |
    | `maxPriorityFeePerGas` | The maximum tip per unit of consumed gas that goes to the validator, in wei. Used in EIP-1559 transactions. |
    | `maxFeePerGas` | The maximum fee per unit of gas that the sender is willing to pay for the transaction, including baseFeePerGas and maxPriorityFeePerGas. Used in EIP-1559 transactions. |
    | `gasPrice` | The price per unit of gas that the sender is willing to pay, in wei. Used in legacy transactions. |
    | `chainId` | The chain identifier number. It prevents transaction reuse across different chains. |
    | `accessList` | A list of addresses and storage keys that the transaction plans to access. EIP-2930 and EIP-1559 transactions use it to reduce the gas cost of access to those addresses and storage slots. |
    | `type` | The transaction type: 0 for legacy (pre-EIP-2718), 1 for EIP-2930 access list transactions, and 2 for EIP-1559 fee market transactions. |
    | `hash` | The transaction hash: a unique identifier for the transaction, generated after signing. |
  </Tab>

  <Tab title="Transaction Types">
    ### Legacy transactions (type 0)

    This format predates EIP-1559 and specifies a single gasPrice.

    ```json theme={null}
    {
      "from": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db",
      "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
      "gas": "0x55555",
      "gasPrice": "0x1234",
      "value": "0x1234",
      "data": "0xabcd",
      "nonce": "0x0"
    }
    ```

    ### Access list transactions (type 1, EIP-2930)

    These transactions can include an access list of addresses and storage keys to reduce gas costs.

    ```json theme={null}
    {
      "type": "0x1",
      "from": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db",
      "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
      "gas": "0x55555",
      "gasPrice": "0x1234",
      "value": "0x1234",
      "data": "0xabcd",
      "nonce": "0x0",
      "accessList": [
        {
          "address": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
          "storageKeys": [
            "0x0000000000000000000000000000000000000000000000000000000000000000"
          ]
        }
      ]
    }
    ```

    ### Fee market transactions (type 2, EIP-1559)

    This format supports dynamic base fees and a priority fee (tip) to validators.

    ```json theme={null}
    {
      "type": "0x2",
      "from": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db",
      "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
      "gas": "0x55555",
      "maxFeePerGas": "0x1234",
      "maxPriorityFeePerGas": "0x1234",
      "value": "0x1234",
      "data": "0xabcd",
      "nonce": "0x0",
      "accessList": []
    }
    ```
  </Tab>

  <Tab title="Example Request">
    ### Example request: sending an EIP-1559 transaction

    ```json theme={null}
    {
      "jsonrpc": "2.0",
      "method": "eth_sendTransaction",
      "params": [
        {
          "from": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db",
          "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
          "gas": "0x55555",
          "maxFeePerGas": "0x1234",
          "maxPriorityFeePerGas": "0x1234",
          "value": "0x1234",
          "data": "0xabcd",
          "nonce": "0x0"
        }
      ],
      "id": 2
    }
    ```

    ### JavaScript example with web3.js

    <Info>
      Public RPC endpoints such as `https://evm-rpc.sei-apis.com` do not manage or unlock accounts. On these endpoints, `eth_accounts` returns an empty list and `eth_sendTransaction` returns an error. Sign transactions locally with a private key and broadcast the raw transaction instead.
    </Info>

    ```javascript theme={null}
    // Example using web3.js v4 to sign and broadcast a transaction.
    // Public RPC endpoints do not manage accounts, so sign locally with a private key.
    const { Web3 } = require('web3');
    const web3 = new Web3('https://evm-rpc.sei-apis.com');

    // Load your account from a private key. Never hard-code keys — read from an env var.
    const account = web3.eth.accounts.privateKeyToAccount(process.env.PRIVATE_KEY);

    async function sendTransaction() {
      // Current nonce for the sender
      const nonce = await web3.eth.getTransactionCount(account.address);

      // Use the latest base fee to set EIP-1559 fees
      const block = await web3.eth.getBlock('latest');
      const maxPriorityFeePerGas = web3.utils.toWei('1', 'gwei');
      const maxFeePerGas = (BigInt(block.baseFeePerGas) + BigInt(maxPriorityFeePerGas)).toString();

      const tx = {
        from: account.address,
        to: '0x07a565b7ed7d7a678680a4c162885bedbb695fe0',
        value: web3.utils.toWei('0.1', 'ether'),
        gas: 21000, // Gas limit for a simple transfer
        maxFeePerGas,
        maxPriorityFeePerGas,
        nonce,
        chainId: 1329 // Sei Mainnet (use 1328 for Sei Testnet)
      };

      // Sign locally, then broadcast the raw transaction
      const signed = await web3.eth.accounts.signTransaction(tx, process.env.PRIVATE_KEY);
      const receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction);
      console.log('Transaction receipt:', receipt);
    }

    sendTransaction().catch(console.error);
    ```
  </Tab>

  <Tab title="Example Response">
    ### `eth_sendTransaction`

    ```json theme={null}
    {
      "jsonrpc": "2.0",
      "id": 2,
      "result": "0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e"
    }
    ```

    ### `eth_getTransactionByHash`

    ```json theme={null}
    {
      "jsonrpc": "2.0",
      "id": 3,
      "result": {
        "blockHash": "0x5d15649e25d8e7c60b5a1cb3612b6b45dceaa3c774f438d4d5b4e1e1b2db634a",
        "blockNumber": "0x92a",
        "from": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db",
        "gas": "0x55555",
        "gasPrice": "0x1234",
        "hash": "0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e",
        "input": "0xabcd",
        "nonce": "0x0",
        "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
        "transactionIndex": "0x1",
        "value": "0x1234",
        "type": "0x2",
        "accessList": [],
        "chainId": "0x531",
        "maxFeePerGas": "0x1234",
        "maxPriorityFeePerGas": "0x1234",
        "v": "0x0",
        "r": "0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e",
        "s": "0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663"
      }
    }
    ```

    ### Transaction receipt

    ```json theme={null}
    {
      "jsonrpc": "2.0",
      "id": 4,
      "result": {
        "transactionHash": "0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e",
        "transactionIndex": "0x1",
        "blockHash": "0x5d15649e25d8e7c60b5a1cb3612b6b45dceaa3c774f438d4d5b4e1e1b2db634a",
        "blockNumber": "0x92a",
        "from": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db",
        "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
        "cumulativeGasUsed": "0xd190",
        "gasUsed": "0x5208",
        "contractAddress": null,
        "logs": [],
        "status": "0x1",
        "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "effectiveGasPrice": "0x1234",
        "type": "0x2"
      }
    }
    ```
  </Tab>
</Tabs>

## Transaction guidelines

<Info>
  * Use network conditions to estimate appropriate values for `maxFeePerGas` and `maxPriorityFeePerGas`.
  * Track and increment nonces correctly to avoid transaction failures.
  * Prefer EIP-1559 transactions (type 2) for more predictable fees.
  * Handle possible transaction failures and revert reasons in your code.
  * Always double-check destination addresses, because transactions cannot be reversed.
</Info>

| Common issue | Cause | Solution |
| - | - | - |
| Transaction Underpriced | Gas price or priority fee too low | Increase `maxFeePerGas` and `maxPriorityFeePerGas` |
| Nonce Too Low | The nonce was already used | Query the current nonce with `getTransactionCount` |
| Out of Gas | Gas limit too low for the operation | Use `eth_estimateGas` to set an appropriate limit |
| Contract Execution Failed | Contract function reverted | Test with `eth_call` before you send the transaction |

## Transaction validation

Before Sei accepts an EVM transaction, it performs strict semantic validation of the transaction fields. Sei enforces this validation from v6.5.0 onward. If you construct and sign transactions manually, make sure they are well formed to avoid rejection.

* [Transaction types](/evm/evm-parity/transaction-types#access-list-and-auth-list-entry-validation) is the canonical field-level reference. It covers signature-value byte caps and zero-padding rules, access-list entries, and EIP-7702 authorization lists.
* [Differences with Ethereum](/evm/differences-with-ethereum#evm-transaction-envelope-restrictions) covers envelope-level restrictions: no Cosmos wrapper fields, canonical protobuf encoding, and whole-block rejection on decode failure.

### Receipts for nonce-bumping failed transactions

Some EVM transactions pass basic validation and bump the sender's nonce, but still fail during state transition. One example is a transaction whose gas limit clears the intrinsic-gas check but falls short of the EIP-7623 floor-data-gas requirement. This can occur in normal operation after Pectra. Because these transactions bump the nonce, they are considered to have happened and therefore produce a receipt.

For such failures, Sei writes a synthetic `status=0` (failed) receipt at the end of the block. The receipt reports a `gasUsed` of 0 and an `effectiveGasPrice` of 0. It also carries a `VmError` that describes the state-transition reason. `eth_getTransactionReceipt` returns this failed-transaction receipt instead of `null`. Sei stores the `VmError` on its internal receipt record, not in the `eth_getTransactionReceipt` JSON response. To get it, use the non-standard `eth_getVMError` method.

<Info>
  Previously, a nonce-bumping transaction that failed during state transition could return `null` from `eth_getTransactionReceipt` indefinitely. Clients that polled for a receipt could then hang. Clients should now expect a `status=0` receipt for these transactions and treat it as a normal failed-transaction result.
</Info>

## Additional resources

<CardGroup cols={3}>
  <Card horizontal title="RPC reference" icon="circle-info" href="/evm/reference">
    Sei's EVM RPC endpoints for creating and monitoring transactions
  </Card>

  <Card horizontal title="Gas and fees" icon="coins" href="/learn/dev-gas">
    Learn more about gas calculation, fee estimation, and cost optimization on Sei
  </Card>

  <Card horizontal title="Accounts" icon="user" href="/learn/accounts">
    Externally owned accounts and contract accounts on Sei
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.