write_contract
Execute state-changing smart contract functions like minting, swapping, or staking by automatically fetching contract ABIs and handling transaction execution with wallet integration.
Instructions
Execute state-changing functions on a smart contract. Automatically fetches ABI from block explorer if not provided (requires ETHERSCAN_API_KEY). Use this to call any write function on verified contracts. Requires wallet to be configured (via private key or mnemonic).
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| contractAddress | Yes | The contract address | |
| functionName | Yes | Function name to call (e.g., 'mint', 'swap', 'stake', 'approve') | |
| args | No | Function arguments as strings (e.g., ['0xAddress', '1000000']) | |
| value | No | ETH value to send with transaction in ether (e.g., '0.1' for payable functions) | |
| abiJson | No | Full contract ABI as JSON string (optional - will auto-fetch verified contract ABI if not provided) | |
| network | No | Network name or chain ID. Defaults to Ethereum mainnet. |
Implementation Reference
- src/core/tools.ts:1182-1233 (handler)The handler function for the 'write_contract' tool. It processes inputs, parses ABI if necessary, constructs contract parameters, calls the underlying writeContract service, and returns a formatted response with the transaction hash or error details.contractAddress, abi, functionName, args, privateKey, network = 'ethereum' }) => { try { // Parse ABI if it's a string const parsedAbi = typeof abi === 'string' ? JSON.parse(abi) : abi; const contractParams: Record<string, any> = { address: contractAddress as Address, abi: parsedAbi, functionName, args }; const txHash = await services.writeContract( privateKey as Hex, contractParams, network ); return { content: [ { type: 'text', text: JSON.stringify( { network, transactionHash: txHash, message: 'Contract write transaction sent successfully' }, null, 2 ) } ] }; } catch (error) { return { content: [ { type: 'text', text: `Error writing to contract: ${error instanceof Error ? error.message : String(error)}` } ], isError: true }; } }
- src/core/tools.ts:1151-1180 (schema)Zod schema defining the input parameters for the write_contract tool: contractAddress, abi, functionName, args, privateKey, and optional network.contractAddress: z .string() .describe('The address of the smart contract to interact with'), abi: z .array(z.any()) .describe( 'The ABI (Application Binary Interface) of the smart contract function, as a JSON array' ), functionName: z .string() .describe( "The name of the function to call on the contract (e.g., 'transfer')" ), args: z .array(z.any()) .describe( "The arguments to pass to the function, as an array (e.g., ['0x1234...', '1000000000000000000'])" ), privateKey: z .string() .describe( 'Private key of the sending account in hex format (with or without 0x prefix). SECURITY: This is used only for transaction signing and is not stored.' ), network: z .string() .optional() .describe( "Network name (e.g., 'ethereum', 'optimism', 'arbitrum', 'base', 'polygon') or chain ID. Defaults to Ethereum mainnet." ) },
- src/core/tools.ts:1148-1234 (registration)The server.tool call that registers the 'write_contract' tool with the MCP server, providing name, description, input schema, and handler function.'write_contract', 'Write data to a smart contract by calling a state-changing function. This modifies blockchain state and requires gas payment and transaction signing.', { contractAddress: z .string() .describe('The address of the smart contract to interact with'), abi: z .array(z.any()) .describe( 'The ABI (Application Binary Interface) of the smart contract function, as a JSON array' ), functionName: z .string() .describe( "The name of the function to call on the contract (e.g., 'transfer')" ), args: z .array(z.any()) .describe( "The arguments to pass to the function, as an array (e.g., ['0x1234...', '1000000000000000000'])" ), privateKey: z .string() .describe( 'Private key of the sending account in hex format (with or without 0x prefix). SECURITY: This is used only for transaction signing and is not stored.' ), network: z .string() .optional() .describe( "Network name (e.g., 'ethereum', 'optimism', 'arbitrum', 'base', 'polygon') or chain ID. Defaults to Ethereum mainnet." ) }, async ({ contractAddress, abi, functionName, args, privateKey, network = 'ethereum' }) => { try { // Parse ABI if it's a string const parsedAbi = typeof abi === 'string' ? JSON.parse(abi) : abi; const contractParams: Record<string, any> = { address: contractAddress as Address, abi: parsedAbi, functionName, args }; const txHash = await services.writeContract( privateKey as Hex, contractParams, network ); return { content: [ { type: 'text', text: JSON.stringify( { network, transactionHash: txHash, message: 'Contract write transaction sent successfully' }, null, 2 ) } ] }; } catch (error) { return { content: [ { type: 'text', text: `Error writing to contract: ${error instanceof Error ? error.message : String(error)}` } ], isError: true }; } } );
- Supporting helper function that creates a wallet client from the provided private key and network, then invokes viem's writeContract method to execute the contract interaction.export async function writeContract( privateKey: Hex, params: Record<string, any>, network = 'ethereum' ): Promise<Hash> { const client = getWalletClient(privateKey, network); return await client.writeContract(params as any); }