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

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.
// 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);
    }
}
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.
// 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;
    }
}
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.
// 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;
    }
}
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

Bank Solidity Interface
// 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);
}
Bank ABI
{
  "_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