Skip to main content
Glama
0xGval
by 0xGval

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