---
title: Simulate Transaction RPC Endpoint Specification
version: 2022.09.05
description: Simulate Transaction RPC Endpoint Specification
---
> specification for a new RPC method, `tx_optimizeSwap` for simulating transactions
# Simulate Transaction RPC Endpoint Specification
[TOC]
## Simple Summary
Wallet/DApp browser software should provide as much information as possible when presenting a transaction to the user to sign, as there may be unforeseen consequences including a potential loss of funds. A new JSONRPC method `eth_simulateTransaction` enables wallets to perform a dry run of the transaction so that it can provide more information about what might happen such as token movements.
## Abstract
This is a standard for a new JSONRPC endpoint `eth_simulateTransaction` that enables clients to perform a dry run (transaction simulation) before signing and submitting an actual transaction.
`eth_simulateTransaction`: the base RPC method
`tx_optimizeSwap`: built ontop of `eth_simulateTransaction` with the use case of simulating swap transactions for the purposes of triggering OpenMev Router Backrunning function
### Transaction Parameters for Simulation
#### Example
Block number: 15048064
Current block: 15048064
Use Pending Block:
Block number: []
Current block: []
Tx index: 0
Maximum Block Index: 199
From: 0x0000000000000000000000000000000000000000
Gas: 8000000
Gas Price: 0
Value: 0
Use Block Header Overrides
Block number: 0
Timestamp: 1656554914
State Overrides
Add contracts and set state overrides.
Access Lists:
This Simulation will have the Berlin fork enabled, which includes support for EIP-2930 Optional access lists.
Add address to access list
> Recommended Access List
## Motivation
When transaction signing is requested and presented to the user, wallet/DApp browser software ("wallets") should attempt to inform the user of what the transaction entails and what the side effects may be.
Currently, most wallets simply show basic transaction parameters such as the recipient address, the value of ETH being transferred, the gas price/limit, and the encoded data. For well-known transaction types such as ERC20 `approve()` and `transfer()`, some wallets decode the call data and present additional information.
For most smart contract transactions however, what the transaction entails is completely opaque to average users, and a malicious transaction may even appear completely harmless (a smart contract transaction will show the value being transferred as zero as if no ETH is moved, but may nevertheless be moving other types of assets such as ERC20 tokens if an allowance was set previously).
This is terrible for user experience as it encourages users to be accustomed to signing transactions blindly, which may have adverse consequences such as loss of funds.
A new JSONRPC method `eth_simulateTransaction` aims to improve the situation by providing a way for wallets to perform a dry run and read events emitted (such as the ERC20 `Transfer` events), thereby enabling the user to make a more informed decision about whether to sign a transaction that is requested.
## Specification
#### `eth_simulateTransaction`
Performs a dry-run of the transaction and returns a transaction result object. The transaction will not be added to the blockchain. Note that the actual transaction may have a different result for a variety of reasons including EVM mechanics, node performance, and the difference in the state of the blockchain when the transaction is processed.
##### Parameters
1. `Object` - The transaction object
- `from`: `DATA`, 20 Bytes - The address the transaction is send from.
- `to`: `DATA`, 20 Bytes - (optional when creating new contract) The address the transaction is directed to.
- `gas`: `QUANTITY` - (optional, default: 90000) Integer of the gas provided for the transaction execution. It will return unused gas.
- `gasPrice`: `QUANTITY` - (optional, default: To-Be-Determined) Integer of the gasPrice used for each paid gas
- `value`: `QUANTITY` - (optional) Integer of the value sent with this transaction
- `data`: `DATA` - The compiled code of a contract OR the hash of the invoked method signature and encoded parameters. For details see [Ethereum Contract ABI](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI)
- `nonce`: `QUANTITY` - (optional) Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce.
##### Example Parameters
```js
params: [{
"from": "0x1111111111111111111111111111111111111111",
"to": "0x2222222222222222222222222222222222222222",
"gas": "0x200000",
"gasPrice": "0x3b9aca00",
"value": "0x0",
"data": "0xdeadbeef000000000000000000000001111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000000000abcde"
}]
```
##### Returns
`Object` - A transaction result object.
- `transactionHash`: `DATA`, 32 Bytes - hash of the transaction.
- `from`: `DATA`, 20 Bytes - address of the sender.
- `to`: `DATA`, 20 Bytes - address of the receiver. null when it's a contract creation transaction.
- `gasUsed`: `QUANTITY` - The amount of gas used by this specific transaction alone.
- `contractAddress`: `DATA`, 20 Bytes - The contract address created, if the transaction was a contract creation, otherwise `null`.
- `logs`: `Array` - Array of log objects, which this transaction generated.
##### Example
Request
```bash
curl -X POST --data \
'{
"jsonrpc": "2.0",
"method": "eth_sendTransaction",
"params": [
{see above
}
],
"id": 1
}'
```
- Response
```jsonc
// Result
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"transactionHash":
"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"from": "0x1111111111111111111111111111111111111111",
"to": "0x2222222222222222222222222222222222222222",
"gasUsed": "0x123456",
"contractAddress": "0x3333333333333333333333333333333333333333", // or null, if none was created
"logs": [
{
// logs as returned by getFilterLogs, etc.
}, ...
]
}
}
```
## Rationale
The request parameters are the same as `eth_sendTransaction`, and the response is a subset of a transaction receipt object you can obtain using `eth_getTransactionReceipt`, for consistency and familiarity.
Note that it does not require a signed transaction (raw tx), as the motivation is to provide more information to the user before signing happens.
## Implementation
There is an existing method `eth_estimateGas` that already performs transaction dry runs, but the method only returns the amount of gas used by the transaction. The code for `eth_estimateGas` may be reusable for the implementation of `eth_simulateTransaction`.
## SushiGuard Router Integration
The purpose of this new RPC Method/Service is for providing an optimisic simulation for the purposes of determining if a users transaction will trigger the backrunning function without inccuring additional overhead.
It follows that only a subset of overall transactions will meet this criteria. Below are some heruistics for determining if a transaction has such potential.
> Note: over time we can backtest non-simulated submitted user transactions to further narrow the profile if need be
### Test Cases
Test cases: ** Essentially any trade size over 0.1% of pool reserve value, with an alternate market on uniswap will trigger a backrun**
These trades would be simulated via the RPC Method and a transaction generated would then be submitted afterwards.
### Backrun Criteria
Does it have to have an alt market on uniswap or can it have two markets on sushi with different pairings? Im assuming markets have same pairings or can be different?
Same pairing only, eg.
- USDC-WETH (on sushi)
- USDC-WETH (on uni)
#### Alternative pooling to Trigger Backruns
>**Warning**
> This section is non-normative, and meant for facilitating discussion
- WETH9-WETH10 pool
That could work if on both exchanges
? Or even create WETH-'FOLD' market on uni-V2
? Or just use a lower liquidity pool (...)
- How much lower in liquidity does the pool have to be?
> Examples
https://analytics.sushi.com/pairs/0xec8c342bc3e07f05b9a782bc34e7f04fb9b44502
### Simulate Transaction RPC Endpoint
Use EthereumJS VM ?
#### Gnois Safe Transaction Simulator Demo
**Gnosis Safe Transaction Simulator reference and demo dapp**
Example:
https://github.com/rmeissner/safe-simulator/
https://github.com/rmeissner/safe-simulator-app
https://github.com/rmeissner/safe-simulator-gh-action
https://rimeissner.dev/safe-simulator-app/
##### Tenderly Simulator Endpoint
https://docs.tenderly.co/simulations-and-forks/how-to-simulate-a-transaction
##### Sushiswap Furo UI example
Sushi's Furo DApp uses Tenderly to provide similar functionality
### Example, Typescript
```typescript
import {ethers, providers, Signer} from "ethers"
import axios from "axios"
const {
REACT_APP_TENDERLY_ACCESS_KEY,
} = process.env
export const sendTransaction = async (provider: any, sender: string, contract: any, funcName: string, ...args: any[]) => {
if (provider instanceof providers.JsonRpcProvider) {
const unsignedTx = await contract.populateTransaction[funcName](...args)
const transactionParameters = [{
to: contract.address,
from: sender,
data: unsignedTx.data,
gas: ethers.utils.hexValue(3000000),
gasPrice: ethers.utils.hexValue(1),
value: ethers.utils.hexValue(0)
}];
try {
const txHash = await provider.send('eth_sendTransaction', transactionParameters)
return {
txHash: txHash
}
} catch(err) {
console.log(err)
}
} else if (provider instanceof Signer) {
try {
const tx = await contract[funcName](...args)
return {
txHash: tx.hash
}
} catch (err) {
console.log(err)
}
}
}
export const simulateTransaction = async (senderAddr: string, contract: any, funcName: string, ...args: any[]) => {
const unsignedTx = await contract.populateTransaction[funcName](...args)
const apiURL = `https://api.tenderly.co/api/v1/account/me/project/project/simulate`
const body = {
"network_id": "1",
"from": senderAddr,
"to": contract.address,
"input": unsignedTx.data,
"gas": 21204,
"gas_price": "0",
"value": 0,
"save_if_fails": true
}
const headers = {
headers: {
'content-type': 'application/JSON',
'X-Access-Key': REACT_APP_TENDERLY_ACCESS_KEY as string,
}
}
const resp = await axios.post(apiURL, body, headers);
return resp
}
```
## Security Considerations
Wallets and DApp browsers utilizing `eth_simulateTransaction` must highlight that it can only provide an _estimated_ outcome and that the actual mileage may vary.