Skip to main content
Glama

auditContract

Analyze Ethereum smart contracts for security vulnerabilities and code quality issues. Enter a contract address to receive detailed audit results including potential risks and recommendations.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
addressYes
chainNoeth

Implementation Reference

  • The core asynchronous handler function for the 'auditContract' tool. It initializes Web3, analyzes the contract address using helper functions, formats the results into MCP content format, and handles errors.
    async ({ address, chain }) => { try { // Use the web3 instance from the environment variable or default public node console.error('Creating Web3 instance with URL:', process.env.ETH_RPC_URL); const web3 = new Web3(process.env.ETH_RPC_URL || 'https://eth.llamarpc.com'); // Perform the contract analysis console.error('Analyzing address:', address); const result = await analyzeAddress(web3, address); // Format the output for MCP response return { content: [{ type: "text", text: formatAnalysisResults(result) }] }; } catch (error) { console.error('Error in auditContract:', error); return { content: [{ type: "text", text: `Error analyzing contract: ${error.message}` }] }; } }
  • Zod-based input schema validating the 'address' parameter as a 42-character Ethereum address starting with 0x, and optional 'chain' parameter defaulting to 'eth'.
    { address: z.string().regex(/^0x[a-fA-F0-9]{40}$/, "Invalid Ethereum address"), chain: z.string().optional().default("eth") },
  • tools/audit.js:19-55 (registration)
    The registerAuditTool exported function that registers the 'auditContract' tool on the MCP server instance using server.tool, providing the schema and handler.
    export function registerAuditTool(server) { console.error('Registering audit tool...'); server.tool("auditContract", { address: z.string().regex(/^0x[a-fA-F0-9]{40}$/, "Invalid Ethereum address"), chain: z.string().optional().default("eth") }, async ({ address, chain }) => { try { // Use the web3 instance from the environment variable or default public node console.error('Creating Web3 instance with URL:', process.env.ETH_RPC_URL); const web3 = new Web3(process.env.ETH_RPC_URL || 'https://eth.llamarpc.com'); // Perform the contract analysis console.error('Analyzing address:', address); const result = await analyzeAddress(web3, address); // Format the output for MCP response return { content: [{ type: "text", text: formatAnalysisResults(result) }] }; } catch (error) { console.error('Error in auditContract:', error); return { content: [{ type: "text", text: `Error analyzing contract: ${error.message}` }] }; } } ); console.error('Audit tool registered successfully'); }
  • main.js:63-63 (registration)
    Invocation of registerAuditTool during MCP server initialization, which executes the tool registration.
    registerAuditTool(server);
  • Primary helper function orchestrating the contract audit: address validation, contract detection, creation info, Etherscan verification, standard detection (ERC20/721/1155), bytecode analysis, basic security heuristics, and result compilation.
    async function analyzeAddress(web3, address) { try { // Validate address if (!web3.utils.isAddress(address)) { throw new Error('Invalid Ethereum address format'); } // Clean and format the address const formattedAddress = web3.utils.toChecksumAddress(address); // Step 1: Check if address is a contract const isContract = await checkIfContract(web3, formattedAddress); let result = { address: formattedAddress, isContract: isContract, isVerified: false, contractName: null, contractCreator: null, creationTx: null, creationTimestamp: null, contractCode: null, sourceCode: null, abi: null, error: null }; // If not a contract, return early if (!isContract) { result.error = 'Address is not a contract'; // Check ETH balance const balance = await web3.eth.getBalance(formattedAddress); result.ethBalance = web3.utils.fromWei(balance, 'ether'); // Check transaction count const txCount = await web3.eth.getTransactionCount(formattedAddress); result.transactionCount = txCount; return result; } // Get creation info const creationInfo = await getContractCreationInfo(formattedAddress); if (creationInfo) { result.contractCreator = creationInfo.contractCreator; result.creationTx = creationInfo.txHash; result.creationTimestamp = creationInfo.timestamp; } // Step 2: Check if contract is verified on Etherscan const verificationInfo = await checkIfVerified(formattedAddress); result.isVerified = verificationInfo.isVerified; // Get bytecode regardless of verification status const bytecode = await web3.eth.getCode(formattedAddress); result.contractCode = bytecode; // Step 3: If verified, get contract code and ABI if (verificationInfo.isVerified) { result.sourceCode = verificationInfo.sourceCode; result.contractName = verificationInfo.contractName; result.abi = verificationInfo.abi; // Check contract interfaces/standards (ERC20, ERC721, etc.) result.standards = await detectContractStandards(formattedAddress, verificationInfo.abi); } else { result.error = 'Contract is not verified on Etherscan'; // Attempt to detect contract type from bytecode result.probableType = await detectContractTypeFromBytecode(bytecode); } // Add security analysis if verified (basic heuristics) if (verificationInfo.isVerified && verificationInfo.sourceCode) { result.securityAnalysis = analyzeContractSecurity(verificationInfo.sourceCode); } return result; } catch (error) { console.error('Error analyzing address:', error); return { address: address, isContract: false, isVerified: false, contractCode: null, sourceCode: null, error: error.message }; } }

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/0xGval/evm-mcp-tools'

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