simulate_transaction
Preview transaction outcomes on a forked chain to detect reverts, gas issues, and risks before execution.
Instructions
Simulate a transaction on a forked chain WITHOUT actually executing it. Detects reverts, abnormal gas usage, and other red flags. Use this to preview what will happen before sending a real transaction.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| chainId | No | Chain ID to simulate on | |
| from | Yes | Sender address | |
| to | Yes | Target contract address | |
| data | Yes | Transaction calldata (hex) | |
| value | No | ETH value to send (in wei) | 0 |
Implementation Reference
- src/risk-engine/simulator.ts:60-132 (handler)The handler function for `simulate_transaction` which simulates a transaction on a forked chain using viem, estimates gas, checks for gas anomalies, and captures revert reasons.
export async function simulateTransaction(req: SimulationRequest): Promise<SimulationResult> { const chainConfig = CHAIN_MAP[req.chainId]; if (!chainConfig) { return { success: false, gasUsed: 0n, gasAnomaly: false, revertReason: `Unsupported chain ID: ${req.chainId}`, riskIndicators: ["unsupported_chain"], estimatedCostEth: "0", }; } const client = createPublicClient({ chain: chainConfig.chain, transport: http(chainConfig.rpcUrl), }); const riskIndicators: string[] = []; try { // Estimate gas const gasEstimate = await client.estimateGas({ account: req.from, to: req.to, data: req.data, value: req.value || 0n, }); // Check for gas anomalies const gasAnomaly = gasEstimate > GAS_THRESHOLDS.suspicious; if (gasAnomaly) { riskIndicators.push("high_gas_usage"); } if (gasEstimate > GAS_THRESHOLDS.dangerous) { riskIndicators.push("extremely_high_gas"); } // Simulate the call const result = await client.call({ account: req.from, to: req.to, data: req.data, value: req.value || 0n, }); // Get gas price for cost estimation const gasPrice = await client.getGasPrice(); const costWei = gasEstimate * gasPrice; const costEth = Number(costWei) / 1e18; return { success: true, gasUsed: gasEstimate, gasAnomaly, returnData: result.data, riskIndicators, estimatedCostEth: costEth.toFixed(6), }; } catch (error: any) { const revertReason = extractRevertReason(error); riskIndicators.push("transaction_reverts"); return { success: false, gasUsed: 0n, gasAnomaly: false, revertReason, riskIndicators, estimatedCostEth: "0", }; } } - src/risk-engine/simulator.ts:14-43 (schema)Input (SimulationRequest) and Output (SimulationResult) interfaces for the `simulate_transaction` tool.
export interface SimulationRequest { /** Chain to simulate on */ chainId: number; /** The sender address (agent's wallet) */ from: Address; /** Target contract address */ to: Address; /** Calldata */ data: Hex; /** ETH value to send (in wei) */ value?: bigint; /** Optional block number to fork from */ blockNumber?: bigint; } export interface SimulationResult { success: boolean; /** Gas used by the transaction */ gasUsed: bigint; /** Whether gas usage is abnormally high */ gasAnomaly: boolean; /** Revert reason if the transaction failed */ revertReason?: string; /** Return data from the call */ returnData?: Hex; /** Risk indicators from simulation */ riskIndicators: string[]; /** Estimated gas cost in ETH */ estimatedCostEth: string; } - src/mcp-server/server.ts:93-110 (registration)Registration and tool execution handler within the MCP server implementation.
}, async ({ chainId, from, to, data, value }) => { const result = await simulateTransaction({ chainId, from: from as Address, to: to as Address, data: data as Hex, value: BigInt(value), }); return { content: [{ type: "text" as const, text: JSON.stringify({ ...result, gasUsed: result.gasUsed.toString(), }, null, 2), }],