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
| Name | Required | Description | Default |
|---|---|---|---|
| contractAddress | Yes | The address of the ERC20 token contract | |
| tokenAddress | No | DEPRECATED: Use contractAddress instead. The address of the ERC20 token contract | |
| ownerAddress | Yes | The Ethereum address that owns the tokens | |
| spenderAddress | Yes | The Ethereum address that is approved to spend tokens | |
| provider | No | Optional. 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. | |
| chainId | No | 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. |
Implementation Reference
- src/tools/erc20.ts:280-319 (handler)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)}` }] }; } }
- src/tools/definitions/erc20.ts:58-85 (schema)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"] }
- src/tools/erc20.ts:266-320 (registration)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)}` }] }; } } );
- src/services/erc/erc20.ts:206-257 (helper)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'); } }); }
- src/tools/handlers/erc20.ts:122-169 (handler)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'); } },