deploy_gasless_token
Deploy ERC-20 tokens on Base network with zero gas fees for users via CDP Paymaster, requiring only token name, symbol, and owner address.
Instructions
Deploy an ERC-20 token on Base using CDP Paymaster (zero gas for user). Falls back to normal gas if no paymaster configured. Requires DEPLOYER_PRIVATE_KEY.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Token name (e.g. 'My Token') | |
| symbol | Yes | Token symbol/ticker (e.g. 'MTK') | |
| supply | No | Total supply in human units (e.g. '1000000' for 1M tokens, 18 decimals) | 1000000 |
| owner_address | Yes | Address that receives all minted tokens and owns the token |
Implementation Reference
- src/index.ts:133-208 (handler)The MCP tool 'deploy_gasless_token' is registered and implemented directly within src/index.ts. It uses a Zod schema for input validation, constructs a transaction using ethers.js, and delegates the final transmission to a helper 'sendTransaction' which handles the paymaster logic.
server.tool( "deploy_gasless_token", "Deploy an ERC-20 token on Base using CDP Paymaster (zero gas for user). Falls back to normal gas if no paymaster configured. Requires DEPLOYER_PRIVATE_KEY.", { name: z.string().describe("Token name (e.g. 'My Token')"), symbol: z.string().describe("Token symbol/ticker (e.g. 'MTK')"), supply: z.string().default("1000000").describe("Total supply in human units (e.g. '1000000' for 1M tokens, 18 decimals)"), owner_address: z.string().describe("Address that receives all minted tokens and owns the token"), }, async ({ name, symbol, supply, owner_address }) => { try { const signer = getSigner(); const supplyWei = ethers.parseUnits(supply, 18); // Encode constructor args const factory = new ethers.ContractFactory(TOKEN_ABI, TOKEN_BYTECODE, signer); const deployTx = await factory.getDeployTransaction(name, symbol, supplyWei, owner_address); // Get gas estimate for savings calculation const provider = getProvider(); const gasEstimate = await provider.estimateGas({ ...deployTx, from: await signer.getAddress(), }); const feeData = await provider.getFeeData(); const gasPrice = feeData.gasPrice || 0n; const estimatedCostWei = gasEstimate * gasPrice; // Send through paymaster or normal const { receipt, usedPaymaster } = await sendTransaction(signer, deployTx); // Extract deployed contract address const tokenAddress = receipt.contractAddress; if (!tokenAddress) { return mcpError("Deploy succeeded but contract address not found in receipt"); } const actualGasCostWei = receipt.gasUsed * receipt.gasPrice; // Track deployment const record: DeployRecord = { tokenAddress, deployer: await signer.getAddress(), owner: owner_address, name, symbol, totalSupply: supply, txHash: receipt.hash, blockNumber: receipt.blockNumber, gasUsed: receipt.gasUsed.toString(), gasPrice: receipt.gasPrice.toString(), gasCostWei: actualGasCostWei.toString(), usedPaymaster, timestamp: Math.floor(Date.now() / 1000), }; deployments.push(record); return mcpResult({ success: true, token_address: tokenAddress, name, symbol, total_supply: supply, decimals: 18, owner: owner_address, gasless: usedPaymaster, gas_used: receipt.gasUsed.toString(), gas_cost_eth: usedPaymaster ? "0 (sponsored)" : ethers.formatEther(actualGasCostWei), estimated_cost_eth: ethers.formatEther(estimatedCostWei), gas_saved_eth: usedPaymaster ? ethers.formatEther(estimatedCostWei) : "0", tx_hash: receipt.hash, block_number: receipt.blockNumber, explorer: `https://basescan.org/token/${tokenAddress}`, paymaster_status: usedPaymaster ? "sponsored" : (isPaymasterEnabled() ? "failed_fallback" : "not_configured"), }); } catch (err: unknown) {