Skip to main content
Glama

getERC20Allowance

Check how many ERC20 tokens a spender can use on behalf of an owner. Verify approval amounts for token spending permissions in Ethereum wallets.

Instructions

Get the amount of tokens that a spender is approved to spend on behalf of a token owner. Used to check ERC20 approval amounts.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
contractAddressYesThe address of the ERC20 token contract
tokenAddressNoDEPRECATED: Use contractAddress instead. The address of the ERC20 token contract
ownerAddressYesThe Ethereum address that owns the tokens
spenderAddressYesThe Ethereum address that is approved to spend tokens
providerNoOptional. Either a network name or custom RPC URL. Use getAllNetworks to see available networks and their details, or getNetwork to get info about a specific network. You can use any network name returned by these tools as a provider value.
chainIdNoOptional. The chain ID to use. If provided with a named network and they don't match, the RPC's chain ID will be used.

Implementation Reference

  • Primary MCP tool handler implementation for getERC20Allowance. Handles parameter mapping, calls the ethers service for allowance and token info, formats response.
    async (params) => {
      // Map deprecated parameters
      const mapped = mapParameters(params);
      
      try {
        const contractAddr = mapped.contractAddress || params.tokenAddress;
        if (!contractAddr) {
          throw new Error('Either contractAddress or tokenAddress must be provided');
        }
        const allowance = await ethersService.getERC20Allowance(
          contractAddr,
          mapped.ownerAddress,
          mapped.spenderAddress,
          mapped.provider,
          mapped.chainId
        );
        
        // Get token info to format the response
        const tokenInfo = await ethersService.getERC20TokenInfo(
          contractAddr,
          mapped.provider,
          mapped.chainId
        );
        
        return {
          content: [{ 
            type: "text", 
            text: `${mapped.spenderAddress} is approved to spend ${allowance} ${tokenInfo.symbol} from ${mapped.ownerAddress}`
          }]
        };
      } catch (error) {
        return {
          isError: true,
          content: [{ 
            type: "text", 
            text: `Error getting token allowance: ${error instanceof Error ? error.message : String(error)}`
          }]
        };
      }
    }
  • JSON schema definition for the getERC20Allowance tool inputs.
    name: "getERC20Allowance",
    description: "Get the amount of tokens approved for a spender to use from an owner's account",
    inputSchema: {
      type: "object",
      properties: {
        tokenAddress: {
          type: "string",
          description: "The address of the ERC20 token contract"
        },
        ownerAddress: {
          type: "string",
          description: "The Ethereum address that owns the tokens"
        },
        spenderAddress: {
          type: "string",
          description: "The Ethereum address that is approved to spend tokens"
        },
        provider: {
          type: "string",
          description: "Optional. Either a network name or custom RPC URL. Use getSupportedNetworks to get a list of supported networks."
        },
        chainId: {
          type: "number",
          description: "Optional. The chain ID to use. If provided with a named network and they don't match, the RPC's chain ID will be used."
        }
      },
      required: ["tokenAddress", "ownerAddress", "spenderAddress"]
    }
  • MCP server tool registration for getERC20Allowance, including inline Zod schema and handler reference.
      "getERC20Allowance",
      "Get the amount of tokens that a spender is approved to spend on behalf of a token owner. Used to check ERC20 approval amounts.",
      {
        contractAddress: contractAddressSchema,
        tokenAddress: tokenAddressSchema.optional(),  // Deprecated
        ownerAddress: z.string().describe(
          "The Ethereum address that owns the tokens"
        ),
        spenderAddress: z.string().describe(
          "The Ethereum address that is approved to spend tokens"
        ),
        provider: providerSchema,
        chainId: chainIdSchema
      },
      async (params) => {
        // Map deprecated parameters
        const mapped = mapParameters(params);
        
        try {
          const contractAddr = mapped.contractAddress || params.tokenAddress;
          if (!contractAddr) {
            throw new Error('Either contractAddress or tokenAddress must be provided');
          }
          const allowance = await ethersService.getERC20Allowance(
            contractAddr,
            mapped.ownerAddress,
            mapped.spenderAddress,
            mapped.provider,
            mapped.chainId
          );
          
          // Get token info to format the response
          const tokenInfo = await ethersService.getERC20TokenInfo(
            contractAddr,
            mapped.provider,
            mapped.chainId
          );
          
          return {
            content: [{ 
              type: "text", 
              text: `${mapped.spenderAddress} is approved to spend ${allowance} ${tokenInfo.symbol} from ${mapped.ownerAddress}`
            }]
          };
        } catch (error) {
          return {
            isError: true,
            content: [{ 
              type: "text", 
              text: `Error getting token allowance: ${error instanceof Error ? error.message : String(error)}`
            }]
          };
        }
      }
    );
  • Core helper function getAllowance that performs the actual ethers.Contract allowance call, caching, error handling, and formatting. Called by ethersService.getERC20Allowance.
    export async function getAllowance(
      ethersService: EthersService,
      tokenAddress: string,
      ownerAddress: string,
      spenderAddress: string,
      provider?: string,
      chainId?: number
    ): Promise<string> {
      metrics.incrementCounter('erc20.getAllowance');
      
      return timeAsync('erc20.getAllowance', async () => {
        try {
          // Create cache key
          const cacheKey = createTokenCacheKey(
            CACHE_KEYS.ERC20_ALLOWANCE,
            tokenAddress,
            ownerAddress,
            spenderAddress,
            chainId
          );
          
          // Check cache first
          const cachedAllowance = balanceCache.get(cacheKey);
          if (cachedAllowance) {
            return cachedAllowance;
          }
          
          // Get provider from ethers service
          const ethersProvider = ethersService['getProvider'](provider, chainId);
          
          // Create contract instance
          const contract = new ethers.Contract(tokenAddress, ERC20_ABI, ethersProvider);
          
          // Get allowance
          const allowance = await contract.allowance(ownerAddress, spenderAddress);
          
          // Get token decimals for formatting
          const tokenInfo = await getTokenInfo(ethersService, tokenAddress, provider, chainId);
          
          // Format the allowance based on decimals
          const formattedAllowance = ethers.formatUnits(allowance, tokenInfo.decimals);
          
          // Cache result for future use (30 second TTL)
          balanceCache.set(cacheKey, formattedAllowance, { ttl: 30000 });
          
          return formattedAllowance;
        } catch (error) {
          logger.debug('Error getting ERC20 allowance', { tokenAddress, ownerAddress, spenderAddress, error });
          throw handleTokenError(error, 'Failed to get token allowance');
        }
      });
    }
  • Alternative handler implementation using validation utils and friendly errors, possibly for different tool server setup.
    getERC20Allowance: async (args: unknown) => {
      const schema = z.object({
        contractAddress: contractAddressSchema.optional(),
        tokenAddress: tokenAddressSchema,  // Deprecated
        ownerAddress: CommonSchemas.ethereumAddress.describe('Token owner address'),
        spenderAddress: CommonSchemas.ethereumAddress.describe('Address authorized to spend tokens'),
        provider: providerSchema,
        chainId: chainIdSchema
      });
      
      try {
        // First validate with friendly errors
        const validatedParams = validateWithFriendlyErrors(
          schema,
          args,
          'Get ERC20 Allowance'
        );
        
        // Then map deprecated parameters for backward compatibility
        const mapped = mapParameters(validatedParams);
        
        // Ensure we have a contract address (from either new or old parameter name)
        const contractAddr = mapped.contractAddress || validatedParams.tokenAddress;
        if (!contractAddr) {
          throw new Error('Contract address is required. Please provide either contractAddress or tokenAddress.');
        }
        
        const allowance = await ethersService.getERC20Allowance(
          contractAddr, 
          validatedParams.ownerAddress, 
          validatedParams.spenderAddress, 
          mapped.provider, 
          mapped.chainId
        );
        
        // Get token info to format the response
        const tokenInfo = await ethersService.getERC20TokenInfo(contractAddr, mapped.provider, mapped.chainId);
        
        return {
          content: [{ 
            type: "text", 
            text: `${validatedParams.spenderAddress} is approved to spend ${allowance} ${tokenInfo.symbol} from ${validatedParams.ownerAddress}`
          }]
        };
      } catch (error) {
        return createErrorResponse(error, 'getting token allowance');
      }
    },

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/crazyrabbitLTC/mcp-ethers-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server