Skip to main content
Glama

approve_token_spending

Authorize smart contracts to spend your ERC20 tokens for DeFi interactions like DEX trades or lending protocols. Set spending limits or revoke permissions as needed.

Instructions

Approve a spender (contract) to spend tokens on your behalf. Required before interacting with DEXes, lending protocols, etc.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
tokenAddressYesThe ERC20 token contract address
spenderAddressYesThe address that will be allowed to spend tokens (usually a contract)
amountYesAmount to approve (in token units). Use '0' to revoke approval.
networkNoNetwork name or chain ID. Defaults to Ethereum mainnet.

Implementation Reference

  • MCP server.tool registration, input schema with Zod, and handler function for the 'approve_token_spending' tool. The handler performs ENS resolution if needed, fetches token decimals/symbol, parses amount, signs and sends the approve transaction via viem wallet client, and returns formatted results.
    // Approve ERC20 token spending server.tool( 'approve_token_spending', 'Approve another address (like a DeFi protocol or exchange) to spend your ERC20 tokens. This is often required before interacting with DeFi protocols.', { privateKey: z .string() .describe( '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.' ), tokenAddress: z .string() .describe( "The contract address of the ERC20 token to approve for spending (e.g., '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' for USDC on Ethereum)" ), spenderAddress: z .string() .describe( 'The contract address being approved to spend your tokens (e.g., a DEX or lending protocol)' ), amount: z .string() .describe( "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." ), network: z .string() .optional() .describe( "Network name (e.g., 'ethereum', 'optimism', 'arbitrum', 'base', 'polygon') or chain ID. Defaults to Ethereum mainnet." ) }, async ({ privateKey, tokenAddress, spenderAddress, amount, network = 'ethereum' }) => { try { // Get the formattedKey with 0x prefix const formattedKey = privateKey.startsWith('0x') ? (privateKey as `0x${string}`) : (`0x${privateKey}` as `0x${string}`); const result = await services.approveERC20( tokenAddress as Address, spenderAddress as Address, amount, formattedKey, network ); return { content: [ { type: 'text', text: JSON.stringify( { success: true, txHash: result.txHash, network, tokenAddress, spender: spenderAddress, amount: result.amount.formatted, symbol: result.token.symbol }, null, 2 ) } ] }; } catch (error) { return { content: [ { type: 'text', text: `Error approving token spending: ${error instanceof Error ? error.message : String(error)}` } ], isError: true }; } } );
  • Core helper function approveERC20 that resolves addresses (supports ENS), fetches token metadata, parses amount using decimals, creates wallet client from private key, calls approve function on ERC20 contract, and returns transaction hash with details.
    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 } }; }
  • ERC20 ABI fragment defining the approve, transfer, decimals, and symbol functions used by the approveERC20 helper.
    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;
  • Calls registerEVMTools to register all EVM tools including approve_token_spending.
    registerEVMTools(server);

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

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