> ## 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.

# Bank

> An ERC20 interface to native Cosmos SDK tokens for balance queries and supply information

## Overview

The Bank precompile provides ERC20-style access to native Cosmos SDK tokens, enabling smart contracts to query balances and token supplies through standardized interfaces. It serves as a Solidity wrapper around the Cosmos SDK `x/bank` module.

**Address**: `0x0000000000000000000000000000000000000804`

**Related Module**: [x/bank](/sdk/v0.53/build/modules/bank)

## Gas Costs

* **balances**: 2,851 + (2,851 × (n-1)) where n = number of tokens returned
* **totalSupply**: 2,477 + (2,477 × (n-1)) where n = number of tokens returned
* **supplyOf**: 2,477

## Primary Methods

### balances

**Signature**: `balances(address account) → Balance[] memory`

**Description**: Queries all native token balances for a specific account address and returns an array of `Balance` (ERC-20 contract address & amount) structures.

<CodeGroup>
  ```solidity Solidity expandable lines theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
  // SPDX-License-Identifier: MIT
  pragma solidity ^0.8.0;

  contract BankExample {
      address constant BANK_PRECOMPILE = 0x0000000000000000000000000000000000000804;
      
      struct Balance {
          address contractAddress;
          uint256 amount;
      }
      
      function getAccountBalances(address account) external view returns (Balance[] memory balances) {
          (bool success, bytes memory result) = BANK_PRECOMPILE.staticcall(
              abi.encodeWithSignature("balances(address)", account)
          );
          
          require(success, "Balance query failed");
          balances = abi.decode(result, (Balance[]));
          return balances;
      }
      
      // Convenience function to get caller's balances
      function getMyBalances() external view returns (Balance[] memory balances) {
          return this.getAccountBalances(msg.sender);
      }
  }
  ```

  ```javascript Ethers.js expandable lines theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
  import { ethers } from "ethers";

  // Connect to the network
  const provider = new ethers.JsonRpcProvider("<RPC_URL>");

  // Precompile address and ABI
  const precompileAddress = "0x0000000000000000000000000000000000000804";
  const precompileAbi = [
    "function balances(address account) view returns (tuple(address contractAddress, uint256 amount)[])"
  ];

  // Create a contract instance
  const contract = new ethers.Contract(precompileAddress, precompileAbi, provider);

  // Address to query
  const accountAddress = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"; // Placeholder

  async function getBalances() {
    try {
      const balances = await contract.balances(accountAddress);
      console.log("Balances:", balances);
    } catch (error) {
      console.error("Error fetching balances:", error);
    }
  }

  getBalances();
  ```

  ```bash cURL expandable lines theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
  # Replace <RPC_URL> and the account address with your actual data.
  # Data is ABI-encoded: function selector + padded address
  curl -X POST --data '{
      "jsonrpc": "2.0",
      "method": "eth_call",
      "params": [
          {
              "to": "0x0000000000000000000000000000000000000804",
              "data": "0x27e235e3000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045"
          },
          "latest"
      ],
      "id": 1
  }' -H "Content-Type: application/json" <RPC_URL>
  ```
</CodeGroup>

**Parameters**:

* `account` (address): The account address to query balances for

**Returns**: Array of Balance structures with contractAddress and amount fields

### totalSupply

**Signature**: `totalSupply() → Balance[] memory`

**Description**: Queries the total supply of all native tokens in the system. Returns comprehensive supply information for every token registered in the system.

<CodeGroup>
  ```solidity Solidity expandable lines theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
  // SPDX-License-Identifier: MIT
  pragma solidity ^0.8.0;

  contract BankExample {
      address constant BANK_PRECOMPILE = 0x0000000000000000000000000000000000000804;
      
      struct Balance {
          address contractAddress;
          uint256 amount;
      }
      
      function getTotalSupply() external view returns (Balance[] memory totalSupply) {
          (bool success, bytes memory result) = BANK_PRECOMPILE.staticcall(
              abi.encodeWithSignature("totalSupply()")
          );
          
          require(success, "Total supply query failed");
          totalSupply = abi.decode(result, (Balance[]));
          return totalSupply;
      }
  }
  ```

  ```javascript Ethers.js expandable lines theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
  import { ethers } from "ethers";

  // Connect to the network
  const provider = new ethers.JsonRpcProvider("<RPC_URL>");

  // Precompile address and ABI
  const precompileAddress = "0x0000000000000000000000000000000000000804";
  const precompileAbi = [
    "function totalSupply() view returns (tuple(address contractAddress, uint256 amount)[])"
  ];

  // Create a contract instance
  const contract = new ethers.Contract(precompileAddress, precompileAbi, provider);

  async function getTotalSupply() {
    try {
      const supply = await contract.totalSupply();
      console.log("Total Supply:", supply);
    } catch (error) {
      console.error("Error fetching total supply:", error);
    }
  }

  getTotalSupply();
  ```

  ```bash cURL expandable lines theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
  # Replace <RPC_URL> with your actual RPC endpoint.
  # Data is the function selector for totalSupply()
  curl -X POST --data '{
      "jsonrpc": "2.0",
      "method": "eth_call",
      "params": [
          {
              "to": "0x0000000000000000000000000000000000000804",
              "data": "0x18160ddd"
          },
          "latest"
      ],
      "id": 1
  }' -H "Content-Type: application/json" <RPC_URL>
  ```
</CodeGroup>

**Parameters**: None

**Returns**: Array of Balance structures showing total supply for each token

### supplyOf

**Signature**: `supplyOf(address erc20Address) → uint256`

**Description**: Queries the total supply of a specific token by providing its ERC20 contract address. More efficient when you need supply information for a single token.

<CodeGroup>
  ```solidity Solidity expandable lines theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
  // SPDX-License-Identifier: MIT
  pragma solidity ^0.8.0;

  contract BankExample {
      address constant BANK_PRECOMPILE = 0x0000000000000000000000000000000000000804;
      
      function getTokenSupply(address erc20Address) external view returns (uint256 supply) {
          (bool success, bytes memory result) = BANK_PRECOMPILE.staticcall(
              abi.encodeWithSignature("supplyOf(address)", erc20Address)
          );
          
          require(success, "Token supply query failed");
          supply = abi.decode(result, (uint256));
          return supply;
      }
      
      // Helper function to check if token exists (has supply > 0)
      function tokenExists(address erc20Address) external view returns (bool) {
          uint256 supply = this.getTokenSupply(erc20Address);
          return supply > 0;
      }
  }
  ```

  ```javascript Ethers.js expandable lines theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
  import { ethers } from "ethers";

  // Connect to the network
  const provider = new ethers.JsonRpcProvider("<RPC_URL>");

  // Precompile address and ABI
  const precompileAddress = "0x0000000000000000000000000000000000000804";
  const precompileAbi = [
    "function supplyOf(address erc20Address) view returns (uint256)"
  ];

  // Create a contract instance
  const contract = new ethers.Contract(precompileAddress, precompileAbi, provider);

  // ERC20 address to query
  const erc20Address = "0xdAC17F958D2ee523a2206206994597C13D831ec7"; // Placeholder for a token contract

  async function getSupplyOf() {
    try {
      const supply = await contract.supplyOf(erc20Address);
      console.log("Supply of", erc20Address, ":", supply.toString());
    } catch (error) {
      console.error("Error fetching supply:", error);
    }
  }

  getSupplyOf();
  ```

  ```bash cURL expandable lines theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
  # Replace <RPC_URL> and the token address with your actual data.
  # Data is ABI-encoded: function selector + padded address
  curl -X POST --data '{
      "jsonrpc": "2.0",
      "method": "eth_call",
      "params": [
          {
              "to": "0x0000000000000000000000000000000000000804",
              "data": "0x62400e4c000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7"
          },
          "latest"
      ],
      "id": 1
  }' -H "Content-Type: application/json" <RPC_URL>
  ```
</CodeGroup>

**Parameters**:

* `erc20Address` (address): The ERC20 contract address of the token

**Returns**: Total supply of the specified token as uint256

## Data Structures ->

### Balance

The Balance struct represents a token balance with its associated ERC20 contract address:

* `contractAddress` (address): The ERC20 contract address representing the native token
* `amount` (uint256): Token amount in the smallest denomination

## Full Interface & ABI

```solidity title="Bank Solidity Interface" lines expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.18;

/// @dev The IBank contract's address.
address constant IBANK_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000804;

/// @dev The IBank contract's instance.
IBank constant IBANK_CONTRACT = IBank(IBANK_PRECOMPILE_ADDRESS);

/// @dev Balance specifies the ERC20 contract address and the amount of tokens.
struct Balance {
    /// contractAddress defines the ERC20 contract address.
    address contractAddress;
    /// amount of tokens
    uint256 amount;
}

/**
 * @author Evmos Team
 * @title Bank Interface
 * @dev Interface for querying balances and supply from the Bank module.
 */
interface IBank {
    /// @dev balances defines a method for retrieving all the native token balances
    /// for a given account.
    /// @param account the address of the account to query balances for.
    /// @return balances the array of native token balances.
    function balances(
        address account
    ) external view returns (Balance[] memory balances);

    /// @dev totalSupply defines a method for retrieving the total supply of all
    /// native tokens.
    /// @return totalSupply the supply as an array of native token balances
    function totalSupply() external view returns (Balance[] memory totalSupply);

    /// @dev supplyOf defines a method for retrieving the total supply of a particular native coin.
    /// @return totalSupply the supply as a uint256
    function supplyOf(
        address erc20Address
    ) external view returns (uint256 totalSupply);
}
```

```json title="Bank ABI" lines expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
{
  "_format": "hh-sol-artifact-1",
  "contractName": "IBank",
  "sourceName": "solidity/precompiles/bank/IBank.sol",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "balances",
      "outputs": [
        {
          "components": [
            {
              "internalType": "address",
              "name": "contractAddress",
              "type": "address"
            },
            {
              "internalType": "uint256",
              "name": "amount",
              "type": "uint256"
            }
          ],
          "internalType": "struct Balance[]",
          "name": "balances",
          "type": "tuple[]"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "erc20Address",
          "type": "address"
        }
      ],
      "name": "supplyOf",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "totalSupply",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "totalSupply",
      "outputs": [
        {
          "components": [
            {
              "internalType": "address",
              "name": "contractAddress",
              "type": "address"
            },
            {
              "internalType": "uint256",
              "name": "amount",
              "type": "uint256"
            }
          ],
          "internalType": "struct Balance[]",
          "name": "totalSupply",
          "type": "tuple[]"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    }
  ],
  "bytecode": "0x",
  "deployedBytecode": "0x",
  "linkReferences": {},
  "deployedLinkReferences": {}
}
```

## Implementation Details

### Token Resolution

The precompile resolves native Cosmos SDK denominations to their corresponding ERC-20 contract addresses through the `x/erc20` module's token pair registry. Only tokens with registered token pairs are returned in query results.

### Decimal Precision

All amounts returned preserve the original decimal precision stored in the `x/bank` module. No decimal conversion is performed by the precompile.

### Gas Metering

The precompile implements efficient gas metering by:

* Charging base gas for the first result
* Incrementally charging for each additional result in batch queries
* Consuming gas before returning results to prevent DoS vectors

### Error Handling

* Invalid token addresses in `supplyOf` return 0 rather than reverting
* Queries for accounts with no balances return empty arrays
* All methods are read-only and cannot modify state
