Skip to main content
Glama

approve_token_spending

Authorize a DeFi protocol or exchange to spend your ERC20 tokens by specifying the token address, spender address, and amount. Essential for enabling token interactions in decentralized applications.

Instructions

Approve another address (like a DeFi protocol or exchange) to spend your ERC20 tokens. This is often required before interacting with DeFi protocols.

Input Schema

NameRequiredDescriptionDefault
amountYesThe amount of tokens to approve in token units, not wei (e.g., '1000' to approve spending 1000 tokens). Use a very large number for unlimited approval.
networkNoNetwork name (e.g., 'ethereum', 'optimism', 'arbitrum', 'base', 'polygon') or chain ID. Defaults to Ethereum mainnet.
privateKeyYesPrivate key of the token owner account in hex format (with or without 0x prefix). SECURITY: This is used only for transaction signing and is not stored.
spenderAddressYesThe contract address being approved to spend your tokens (e.g., a DEX or lending protocol)
tokenAddressYesThe contract address of the ERC20 token to approve for spending (e.g., '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' for USDC on Ethereum)

Input Schema (JSON Schema)

{ "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "amount": { "description": "The amount of tokens to approve in token units, not wei (e.g., '1000' to approve spending 1000 tokens). Use a very large number for unlimited approval.", "type": "string" }, "network": { "description": "Network name (e.g., 'ethereum', 'optimism', 'arbitrum', 'base', 'polygon') or chain ID. Defaults to Ethereum mainnet.", "type": "string" }, "privateKey": { "description": "Private key of the token owner account in hex format (with or without 0x prefix). SECURITY: This is used only for transaction signing and is not stored.", "type": "string" }, "spenderAddress": { "description": "The contract address being approved to spend your tokens (e.g., a DEX or lending protocol)", "type": "string" }, "tokenAddress": { "description": "The contract address of the ERC20 token to approve for spending (e.g., '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' for USDC on Ethereum)", "type": "string" } }, "required": [ "privateKey", "tokenAddress", "spenderAddress", "amount" ], "type": "object" }

Implementation Reference

  • Registration of the 'approve_token_spending' MCP tool, including input schema, annotations, and handler function that delegates to services.approveERC20
    server.registerTool( "approve_token_spending", { description: "Approve a spender (contract) to spend tokens on your behalf. Required before interacting with DEXes, lending protocols, etc.", inputSchema: { tokenAddress: z.string().describe("The ERC20 token contract address"), spenderAddress: z.string().describe("The address that will be allowed to spend tokens (usually a contract)"), amount: z.string().describe("Amount to approve (in token units). Use '0' to revoke approval."), network: z.string().optional().describe("Network name or chain ID. Defaults to Ethereum mainnet.") }, annotations: { title: "Approve Token Spending", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true } }, async ({ tokenAddress, spenderAddress, amount, network = "ethereum" }) => { try { const privateKey = getConfiguredPrivateKey(); const senderAddress = getWalletAddressFromKey(); const txHash = await services.approveERC20(tokenAddress as Address, spenderAddress as Address, amount, privateKey, network); return { content: [{ type: "text", text: JSON.stringify({ network, tokenAddress, owner: senderAddress, spender: spenderAddress, approvalAmount: amount, txHash, message: "Approval transaction sent. Use get_transaction_receipt to check confirmation." }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error approving token spending: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } }
  • Core implementation of ERC20 approve logic: resolves addresses, fetches token decimals/symbol, parses amount, and sends approve transaction using viem walletClient.writeContract
    export async function approveERC20( tokenAddressOrEns: string, spenderAddressOrEns: string, amount: string, privateKey: string | `0x${string}`, network: string = 'ethereum' ): Promise<{ txHash: Hash; amount: { raw: bigint; formatted: string; }; token: { symbol: string; decimals: number; }; }> { // Resolve ENS names to addresses if needed const tokenAddress = await resolveAddress(tokenAddressOrEns, network) as Address; const spenderAddress = await resolveAddress(spenderAddressOrEns, network) as Address; // Ensure the private key has 0x prefix const formattedKey = typeof privateKey === 'string' && !privateKey.startsWith('0x') ? `0x${privateKey}` as `0x${string}` : privateKey as `0x${string}`; // Get token details const publicClient = getPublicClient(network); const contract = getContract({ address: tokenAddress, abi: erc20TransferAbi, client: publicClient, }); // Get token decimals and symbol const decimals = await contract.read.decimals(); const symbol = await contract.read.symbol(); // Parse the amount with the correct number of decimals const rawAmount = parseUnits(amount, decimals); // Create wallet client for sending the transaction const walletClient = getWalletClient(formattedKey, network); // Send the transaction const hash = await walletClient.writeContract({ address: tokenAddress, abi: erc20TransferAbi, functionName: 'approve', args: [spenderAddress, rawAmount], account: walletClient.account!, chain: walletClient.chain }); return { txHash: hash, amount: { raw: rawAmount, formatted: amount }, token: { symbol, decimals } }; }
  • Zod input schema for the approve_token_spending tool parameters
    tokenAddress: z.string().describe("The ERC20 token contract address"), spenderAddress: z.string().describe("The address that will be allowed to spend tokens (usually a contract)"), amount: z.string().describe("Amount to approve (in token units). Use '0' to revoke approval."), network: z.string().optional().describe("Network name or chain ID. Defaults to Ethereum mainnet.") },
  • ERC20 ABI snippet used for approve, decimals, and symbol reads/writes in the approveERC20 function
    const erc20TransferAbi = [ { inputs: [ { type: 'address', name: 'to' }, { type: 'uint256', name: 'amount' } ], name: 'transfer', outputs: [{ type: 'bool' }], stateMutability: 'nonpayable', type: 'function' }, { inputs: [ { type: 'address', name: 'spender' }, { type: 'uint256', name: 'amount' } ], name: 'approve', outputs: [{ type: 'bool' }], stateMutability: 'nonpayable', type: 'function' }, { inputs: [], name: 'decimals', outputs: [{ type: 'uint8' }], stateMutability: 'view', type: 'function' }, { inputs: [], name: 'symbol', outputs: [{ type: 'string' }], stateMutability: 'view', type: 'function' } ] as const;

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/mcpdotdirect/evm-mcp-server'

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