Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Guides

Setting Up Natural Language Transaction Simulation for Risk Assessment

A technical guide to building a pre-transaction simulation system. Use LLMs to parse user intent, construct and execute a simulation, and analyze outcomes for slippage, fees, and security risks.
Chainscore © 2026
introduction
DEVELOPER GUIDE

Introduction to Natural Language Transaction Simulation

Learn how to use natural language to simulate and assess the risk of blockchain transactions before execution.

Natural Language Transaction Simulation (NLTS) allows developers to describe a desired on-chain action in plain English, which a system then translates into a simulated transaction. This simulation runs against a forked version of the target blockchain state, predicting outcomes like token balances, contract state changes, and potential errors without spending real gas. Tools like Chainscore's Risk API and OpenAI's function calling enable this by parsing user intent (e.g., "Swap 1 ETH for USDC on Uniswap V3") into structured calldata for a specific contract. This bridges the gap between high-level intent and low-level execution, making Web3 interactions more accessible.

Setting up NLTS for risk assessment involves a multi-step pipeline. First, a natural language processing (NLP) model interprets the user's query, identifying key entities: the action (swap, lend, approve), assets (ETH, USDC), amounts (1 ETH), and protocol (Uniswap V3). This structured data is then mapped to a known smart contract ABI to construct the transaction parameters. The core of risk assessment happens in the simulation phase. Using a service like Chainscore, the system executes this constructed transaction against a recent, forked mainnet state in an isolated environment (e.g., using Tenderly or Ganache).

The simulation's output is a detailed report crucial for risk analysis. It returns the predicted new state, including post-transaction balances, gas used, and whether the transaction would revert (and why). For risk assessment, you analyze this data for common pitfalls: slippage on DEX swaps, liquidation thresholds in lending protocols, approval risks for malicious contracts, or insufficient liquidity. By programmatically checking these conditions against the simulated result, you can flag high-risk transactions before they are signed by the user's wallet, preventing financial loss.

Implementing this requires integrating several services. A basic workflow in Node.js might use the OpenAI API to parse the query into JSON, then the Chainscore Simulation API to run it. For example, after getting the parsed intent {action: 'swap', fromToken: 'ETH', toToken: 'USDC', amount: '1'}, you would fetch the current pool address and quote from a DEX aggregator like 1inch, build the calldata for the router contract, and finally call POST /v1/simulate on Chainscore's API with the target chainId, from address, to contract, and data.

Beyond basic simulation, advanced risk assessment layers on additional checks. You can simulate sandwich attack viability by checking pool liquidity, assess MEV exposure by analyzing gas price and transaction complexity, or verify compliance with sanctions lists. The key is that simulation provides the ground-truth data for these heuristics. By combining NLTS with real-time market data and threat intelligence feeds, developers can build robust pre-transaction warnings systems that protect users from both technical failures and economic exploits in DeFi.

prerequisites
FOUNDATION

Prerequisites and System Architecture

This guide details the technical requirements and architectural components needed to set up a system for simulating blockchain transactions using natural language.

Before implementing natural language transaction simulation, you need a foundational development environment. This includes Node.js (v18 or later) and Python (3.9+), which are required for running the core simulation engine and associated tooling. You'll also need access to a JSON-RPC provider for the target blockchain (e.g., an Alchemy or Infura endpoint for Ethereum) to fetch real-time state data. Essential developer tools include git for version control and a package manager like npm or yarn. For interacting with AI models, you must have API keys for services like OpenAI or Anthropic, which power the natural language parsing.

The system architecture is modular, designed to separate concerns for maintainability and scalability. The core component is the Simulation Engine, built on frameworks like Foundry's forge or Hardhat. This engine executes the transaction against a forked version of the mainnet. A Natural Language Parser, typically an LLM API client, interprets user intents (e.g., "swap 1 ETH for DAI") and constructs the corresponding calldata and target contract address. A State Manager handles pre- and post-execution state snapshots, while a Risk Analyzer module evaluates the simulation results for common vulnerabilities like slippage, front-running, or unexpected token approvals.

Key dependencies form the backbone of the simulation stack. For Ethereum Virtual Machine (EVM) chains, the ethers.js or viem libraries are essential for constructing and signing transactions. The @chainlink/automation or Gelato SDKs can be integrated for simulating time-based conditions. To fork the blockchain state locally, you will use tools like Anvil (from Foundry) or Hardhat Network. The code snippet below shows a basic setup for forking mainnet with Anvil, which is a prerequisite for accurate simulation:

bash
# Fork Ethereum mainnet at a specific block
anvil --fork-url $RPC_URL --fork-block-number 19000000

A critical prerequisite is understanding the data flow. The process begins when a user's natural language query is sent to the LLM parser. The parser must be prompted with the Application Binary Interface (ABI) of relevant DeFi protocols to correctly generate transaction parameters. These parameters are passed to the simulation engine, which executes the tx on the forked chain. The engine returns a detailed receipt, including gas used, state changes, and potential revert reasons. This output is then processed by the risk assessment layer, which applies predefined heuristics to flag issues before the user signs a real transaction on-chain.

For production-grade assessment, you must implement persistent storage for simulation results and user sessions. This can be a simple database (PostgreSQL) or a decentralized option like Tableland. Logging and monitoring via services like Datadog or Sentry are crucial for debugging LLM misinterpretations or simulation failures. Finally, consider the security of your API endpoints; implement rate limiting and validate all incoming inputs to prevent malicious payloads from being forwarded to your node provider or LLM service.

key-concepts
TECHNICAL ARCHITECTURE

Core Components of the Simulation System

Natural language transaction simulation requires a robust backend to parse user intent, model on-chain state, and predict outcomes. These are the essential building blocks.

05

Result Aggregation & Reporting

Presents the simulation outcome in a developer-friendly format. This includes:

  • A clear summary of success/failure and total gas cost.
  • A detailed breakdown of all state changes (e.g., token balance deltas).
  • Visualizations of potential portfolio value over time.
  • Actionable warnings and severity scores for identified risks.
step-1-intent-parsing
FOUNDATION

Step 1: Parsing User Intent with an LLM

The first step in simulating a user's transaction is to accurately interpret their natural language request. This guide explains how to use a Large Language Model (LLM) to parse intent into a structured, actionable format.

A user's request, like "swap 1 ETH for USDC on Arbitrum," is unstructured text. An LLM's role is to extract the semantic intent and convert it into a structured object. This object, often called an IntentPayload, should contain all necessary parameters for the next simulation step. Key fields include the target chainId, the from and to token addresses, the input amount, and the core action (e.g., swap, bridge, deposit). Using a system prompt that defines this schema is critical for consistent output.

For reliable parsing, you must provide the LLM with context. This includes a list of supported networks (e.g., Ethereum Mainnet, Arbitrum, Base) with their chain IDs, and a token list with addresses for each chain. Without this, the model may hallucinate incorrect addresses or unsupported chains. Frameworks like LangChain or LlamaIndex can help structure this context retrieval, but a simple, well-crafted prompt with inline JSON examples often suffices for a focused use case. The goal is deterministic parsing, not creative writing.

Here is a simplified example using the OpenAI API format. The system prompt defines the task and output schema, while the user prompt contains the raw request.

System Prompt:

code
You are a transaction intent parser. Convert the user's request into a JSON object.
Output format:
{
  "action": "swap",
  "chainId": 42161,
  "fromToken": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
  "toToken": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
  "amount": "1000000000000000000"
}
Supported chain IDs: Ethereum (1), Arbitrum (42161).
Use the native token address for ETH.

User Prompt: "Swap 1 ETH for USDC on Arbitrum" The expected output is the structured JSON object above, with amount in wei (1 ETH = 1e18 wei).

Error handling is essential. The parser must identify ambiguous or impossible requests. If a user asks to "bridge SOL to Ethereum," but your system only supports EVM chains, the LLM should return an error flag or a null result instead of guessing. You can instruct the model to return a field like "error": "Unsupported source chain: Solana". This prevents faulty data from propagating into the simulation engine. Logging these parsing errors also helps improve your token list and prompt engineering over time.

The output from this step is not yet a transaction. It is a canonical representation of user intent that is chain-agnostic. This IntentPayload becomes the input for Step 2, where you will use a router or solver to find the optimal path—like a specific DEX (Uniswap, 1inch) or bridge protocol (Across, Stargate)—and generate the exact calldata for simulation. Clean, structured intent parsing separates the what from the how, making your risk assessment pipeline more modular and robust.

step-2-transaction-construction
CORE DATA STRUCTURE

Step 2: Constructing the Transaction Object

The transaction object is the fundamental data structure that defines the operation you want to simulate. It must be constructed with precise parameters to ensure the simulation accurately reflects on-chain execution.

A transaction object for simulation must mirror the structure of a real blockchain transaction. At minimum, it requires a from address (the signer), a to address (the contract you're interacting with), and data (the encoded function call). For operations involving value transfer, you must also specify value. For EVM chains, this structure aligns with the standard eth_call RPC parameters. The data field is the most critical component; it is the ABI-encoded payload that specifies which smart contract function to call and with what arguments.

Constructing the data field requires using the Application Binary Interface (ABI) of the target smart contract. You use the contract's ABI to encode the function signature and its arguments. In JavaScript, libraries like ethers.js or viem handle this encoding. For example, to encode a call to a transfer function, you would use contract.interface.encodeFunctionData('transfer', [recipientAddress, amount]). This encoded hex string becomes the data field. An incorrect data payload is the most common source of simulation failure.

Beyond the basic fields, advanced simulations require populating additional parameters to reflect real-world conditions. This includes setting a specific blockNumber or blockTag (e.g., 'latest') for state consistency. You may also need to define gasLimit and gasPrice/maxFeePerGas to model execution costs and priority. For simulating transactions from smart accounts (ERC-4337), the object must include sender and paymasterAndData fields. Tools like the Chainscore Simulation API accept these extended parameters.

Here is a concrete example of a transaction object for simulating a USDC transfer on Ethereum using ethers.js v6:

javascript
const transactionObject = {
  from: '0xAbC123...', // Simulated sender
  to: USDC_CONTRACT_ADDRESS,
  data: usdcContract.interface.encodeFunctionData('transfer', ['0xDef456...', ethers.parseUnits('100', 6)]),
  value: 0, // ERC-20 transfers use data, not value
  gasLimit: 100000,
  maxFeePerGas: ethers.parseUnits('30', 'gwei'),
  maxPriorityFeePerGas: ethers.parseUnits('2', 'gwei')
};

This object is now ready to be sent to a simulation endpoint.

Finally, consider the state context. A simulation can be run against the latest blockchain state or a specific historical state. For risk assessment, you might simulate against a forked mainnet state to test interactions with live protocols. The transaction object itself is stateless; the simulation engine applies it to the specified blockchain state (live, forked, or custom) to predict the outcome. Accurate object construction ensures the simulation engine has all the necessary information to produce a reliable preview of gas usage, state changes, and potential revert reasons.

step-3-executing-simulation
IMPLEMENTATION

Step 3: Executing the Simulation via RPC

This step details how to call the `eth_call` RPC method with a specially formatted payload to simulate a transaction and receive a detailed risk assessment.

The core of natural language simulation is the eth_call RPC request. Instead of sending a standard transaction, you construct a call to the target smart contract. The key innovation is in the data field: you encode a function call to the simulate method of the simulation service's adapter contract, passing the user's plain-text intent as a string argument. For example, to simulate swapping 1 ETH for USDC on Uniswap V3, the data payload would encode a call like simulate("swap 1 ETH for USDC on Uniswap"). This request is sent to the RPC endpoint of the simulation service, not the public Ethereum RPC.

The simulation service's node processes this eth_call uniquely. It intercepts the request, parses the natural language intent using its internal models, and executes a dry-run of the corresponding transaction against a forked version of the blockchain state. This fork is identical to the mainnet at the current block, allowing the simulation to interact with real contract addresses and prices without spending gas or altering any state. The service dynamically constructs the actual transaction calldata, simulates its execution, and analyzes the outcome.

The RPC response contains a structured risk assessment instead of standard call return data. A successful response is a JSON object detailing the simulated transaction's effects. Critical fields include status (success/failure), gasUsed, and an array of assetChanges showing token balances before and after. Most importantly, it includes a riskIndicators object with flags for high-risk patterns like slippageExceeded, insufficientLiquidity, approvalToUnknownContract, or potentialSandwichAttack. This allows your application to programmatically evaluate transaction safety before user signing.

Error handling is crucial. The RPC call may fail with a standard JSON-RPC error if the intent is unparseable or the simulation itself reverts. You should catch these errors and parse the revert reason, which the service formats to explain the failure (e.g., "Simulation Failed: Insufficient liquidity for this trade size"). This provides immediate, actionable feedback to the user. Always implement a timeout for the RPC call, as complex simulations involving multiple DApp interactions may take several seconds to compute.

For developers, integrating this is a straightforward extension of existing RPC workflows. You replace the direct eth_sendTransaction or standard eth_call with this specialized simulation call. Libraries like ethers.js or viem can be used. The code snippet below shows a basic implementation using viem:

javascript
import { createPublicClient, http } from 'viem';
import { mainnet } from 'viem/chains';

const simulationClient = createPublicClient({
  chain: mainnet,
  transport: http('https://rpc.chainscore.dev') // Simulation service RPC
});

try {
  const riskReport = await simulationClient.call({
    to: '0x...', // Simulation adapter address
    data: encodeFunctionData({
      abi: simulatorAbi,
      functionName: 'simulate',
      args: ['swap 1 ETH for USDC on Uniswap V3']
    })
  });
  console.log(riskReport);
} catch (error) {
  console.error('Simulation failed:', error.reason);
}

By executing the simulation via RPC, you move risk assessment from a passive, advisory role to an active, programmatic gate in your transaction flow. This enables features like blocking high-risk transactions, requesting explicit user confirmation for medium-risk items, or automatically adjusting parameters (like slippage tolerance) to find a safer route. The RPC layer provides a standardized, chain-agnostic interface that integrates seamlessly with existing wallets, dApps, and developer tooling.

step-4-risk-analysis
STEP 4

Analyzing Simulation Results for Risk

After running a transaction simulation, the next critical step is interpreting the output to identify potential risks. This guide explains how to analyze simulation results, focusing on state changes, gas usage, and error logs.

A successful simulation returns a detailed result object. The most important component is the stateChanges array, which enumerates every modification the transaction would make to the blockchain state. You should scrutinize this list for unexpected interactions, such as token approvals to unknown contracts, transfers to suspicious addresses, or changes to critical storage slots in a protocol. For example, a simulation of a simple token swap might reveal an additional, hidden call to a setApprovalForAll function, a common red flag for phishing attempts.

Gas analysis is another vital risk indicator. Compare the gasUsed from the simulation against the transaction's gas limit and typical costs for similar operations. Anomalously high gas usage can signal complex, obfuscated logic or an infinite loop. Furthermore, examine the logs (events) emitted during execution. Legitimate DeFi interactions emit predictable events like Swap, Transfer, or Deposit. Missing expected events or the presence of unfamiliar ones can indicate a malicious or malfunctioning contract.

The simulation's error field is crucial. A transaction that reverts in simulation has failed a safety check, preventing potential loss. You must analyze the revert reason, which could be a custom error like InsufficientLiquidity or a generic execution reverted. Tools like the OpenChain simulation API provide human-readable traces that map opcodes to source code, helping you understand why a revert occurred. Always treat a revert in simulation as a blocked transaction, not a negative result.

For advanced risk assessment, perform comparative simulations. Execute the same transaction on a forked mainnet state and a clean, local testnet state. Differences in outcomes can reveal dependencies on specific, potentially manipulated, on-chain conditions like oracle prices or pool reserves. This technique helps identify MEV (Maximal Extractable Value) opportunities for the user or sandwich attack vulnerabilities where a user's trade might be front-run.

Finally, document and score the risks. Create a summary that includes: the risk type (e.g., 'approval risk', 'gas griefing'), the severity level (high, medium, low), and the evidence (specific state change or log entry). This structured output can feed into a user-facing warning system or an automated policy engine. By systematically analyzing these data points, you transform raw simulation output into actionable security intelligence.

IMPLEMENTATION OPTIONS

Risk Parameters and Data Sources

Comparison of approaches for sourcing and parameterizing risk data in a transaction simulation pipeline.

Risk Parameter / Data SourceOn-Chain Oracles (e.g., Chainlink)Off-Chain Aggregators (e.g., DefiLlama)Custom Indexer & API

Price Feed Latency

< 1 sec

2-5 sec

Configurable (1-30 sec)

Maximal Extractable Value (MEV) Data

Smart Contract Vulnerability Scores

Protocol Exploit History

Limited

Gas Price Forecast Accuracy

High

Medium

Varies by model

Implementation Complexity

Low

Low

High

Data Freshness SLA

99.9%

~99%

Dependent on infra

Monthly Cost for High Volume

$500-2000

$0-200

$1000+ (infra)

integration-ux
TUTORIAL

Integrating the Simulation into a dApp Frontend

This guide explains how to integrate Chainscore's natural language transaction simulation API into a decentralized application frontend to provide real-time risk assessment to users.

Integrating transaction simulation begins with installing the necessary client library. For a React-based dApp, you can install the official @chainscore/sdk package via npm or yarn. This SDK provides a lightweight client for interacting with the simulation API without requiring a backend server. The core functionality is accessed through the ChainscoreClient class, which you instantiate with your project's API key obtained from the Chainscore Dashboard. This key authenticates your requests and tracks usage.

The primary method for simulation is client.simulateTransaction. This function requires a transaction object that matches the structure expected by your target blockchain's RPC (e.g., an EIP-1559 transaction for Ethereum). You pass this transaction along with a natural language description of the user's intent. For example, a description for a swap on Uniswap V3 might be: "Swap 1 ETH for at least 3000 USDC on the Ethereum mainnet." The API uses this description to contextualize the simulation and generate a risk assessment report.

Handling the API response is critical for user experience. The simulation returns a JSON object containing a risk_score (a number from 0-100), a summary of potential risks in plain text, and a detailed breakdown of simulated outcomes. Your frontend should parse this response and present the risk_score prominently, perhaps with a color-coded indicator (e.g., green for low risk, red for high risk). The summary can be displayed in a collapsible panel to give users clear, actionable warnings about slippage, approval risks, or unexpected token transfers before they sign.

For optimal performance, implement simulation calls reactively. Trigger the simulation automatically when a user finalizes transaction parameters in your UI, such as after setting swap amounts or recipient addresses. Use debouncing to avoid excessive API calls on every keystroke. Always handle errors gracefully—network issues or invalid transaction data should display a user-friendly message without breaking the dApp's flow. The simulation is read-only and does not require a wallet connection, so it can run before the user even clicks "Connect Wallet," providing early feedback.

Advanced integration involves caching and state management. You can cache simulation results for identical transaction payloads to reduce API load and latency. For complex dApps, consider adding the simulation state to your global store (e.g., Redux or Zustand) so that different UI components can access the risk assessment. Remember, the simulation is a pre-execution check; the final on-chain transaction may still fail due to state changes. Always couple the simulation with standard error handling from your wallet provider (like MetaMask) and blockchain RPC.

NATURAL LANGUAGE SIMULATION

Frequently Asked Questions

Common questions and troubleshooting for developers implementing natural language transaction simulation for on-chain risk assessment.

Natural language transaction simulation is a method of analyzing smart contract interactions by describing them in plain English, which is then parsed and executed in a simulated blockchain environment. Instead of requiring raw calldata or ABI definitions, a system interprets user intent like "swap 1 ETH for USDC on Uniswap V3" and constructs the corresponding transaction. This simulation runs against a forked mainnet state (using tools like Foundry's cheatcodes or Hardhat Network) to predict outcomes such as token balances, slippage, and potential security risks before the user signs the transaction. It bridges the gap between user-friendly interfaces and the technical execution layer.

conclusion-next-steps
IMPLEMENTATION SUMMARY

Conclusion and Next Steps

You have now configured a system to simulate and assess transaction risk using natural language. This guide covered the core setup, from defining an agent to analyzing results.

The system you've built allows you to proactively test smart contract interactions before they are executed on-chain. By simulating transactions through an agent that interprets plain English, you can identify unintended consequences, such as excessive slippage, unexpected fee structures, or security vulnerabilities. This moves risk assessment from a reactive audit to an integrated part of the development and user workflow. Tools like Foundry's forge for local simulation and frameworks like the OpenAI API for intent parsing form the technical backbone.

To enhance your setup, consider these next steps. First, integrate with a blockchain oracle like Chainlink to pull in real-time price feeds for more accurate slippage and liquidation simulations. Second, expand your agent's knowledge base by fine-tuning a model on historical transaction data and audit reports from platforms like Immunefi. Finally, automate the simulation pipeline by connecting it to your CI/CD process, running tests on every pull request that involves approve or transferFrom calls.

For production deployment, you must address key operational concerns. Gas estimation accuracy is critical; calibrate your simulations using tools like EthGasStation or the eth_estimateGas RPC call. Implement rate limiting and caching for your LLM API calls to manage costs and latency. Furthermore, establish a logging and alerting system to flag high-risk simulation outcomes, perhaps using a service like Datadog or Sentry. The goal is to create a feedback loop where simulation data continuously improves the agent's risk models.

The broader ecosystem offers advanced tools to build upon. Explore Tenderly's Simulation API for a more robust environment that includes state overrides and fork management. For intent-centric architectures, research projects like Anoma or SUAVE which are designing blockchains around this paradigm. Academic papers on "Transaction Simulation for Ethereum" (e.g., from the Stanford Blockchain Club) provide deeper insights into state space exploration and formal verification techniques that can be incorporated.

Ultimately, natural language simulation shifts the security model. It empowers end-users to understand "what could happen" and allows developers to stress-test contracts under complex, multi-step scenarios. By adopting these practices, you contribute to a safer Web3 ecosystem where transactions are transparent and risks are quantified before any value is put at stake. Start by simulating one critical user journey in your application this week.

How to Set Up Natural Language Transaction Simulation | ChainScore Guides