通过 RPC 模拟
Node RPC 允许您读取区块链数据并发送交易。但您也可以在 Node 上模拟交易。通过 RPC 进行模拟的优势在于,您可以通过单个 RPC URL 执行所有这些操作。通过 RPC 或 API 进行的模拟仅在受支持的网络上可用。查看受支持网络列表。
example
https://mainnet.gateway.tenderly.co/$TENDERLY_NODE_ACCESS_KEY
tenderly_simulateTransaction 方法。请参阅 RPC 参考。
示例
- request
- response.json
request
curl https://mainnet.gateway.tenderly.co/$TENDERLY_NODE_ACCESS_KEY \
-X POST \
-H "Content-Type: application/json" \
-d \
'{
"id": 0,
"jsonrpc": "2.0",
"method": "tenderly_simulateTransaction",
"params": [
{
"from": "0xe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2",
"to": "0x6b175474e89094c44da98b954eedeac495271d0f",
"gas": "0x7a1200",
"value": "0x0",
"data": "0x095ea7b3000000000000000000000000f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1000000000000000000000000000000000000000000000000000000000000012b"
},
"0xfc497b"
]
}'
response.json
{
"id": 0,
"jsonrpc": "2.0",
"result": {
"status": true,
"gasUsed": "0xb412",
"cumulativeGasUsed": "0xb412",
"blockNumber": "0xfc497b",
"type": "0x0",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000028000000000000000002000000000000000000000010000000000000000004000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000010000000000000000000000000040000000000000000000000000000800000",
"logs": [
{
"name": "Approval",
"anonymous": false,
"inputs": [
{
"value": "0xe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2",
"type": "address",
"name": "src",
"indexed": true
},
{
"value": "0xf1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1",
"type": "address",
"name": "guy",
"indexed": true
},
{
"value": "299",
"type": "uint256",
"name": "wad",
"indexed": false
}
],
"raw": {
"address": "0x6b175474e89094c44da98b954eedeac495271d0f",
"topics": [
"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925",
"0x000000000000000000000000e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2",
"0x000000000000000000000000f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000012b"
}
}
],
"trace": [
{
"type": "CALL",
"from": "0xe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2",
"to": "0x6b175474e89094c44da98b954eedeac495271d0f",
"gas": "0x79bdb0",
"gasUsed": "0x5fc2",
"value": "0x0",
"input": "0x095ea7b3000000000000000000000000f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1000000000000000000000000000000000000000000000000000000000000012b",
"decodedInput": [
{
"value": "0xf1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1",
"type": "address",
"name": "usr",
"indexed": false
},
{
"value": "299",
"type": "uint256",
"name": "wad",
"indexed": false
}
],
"method": "approve",
"output": "0x0000000000000000000000000000000000000000000000000000000000000001",
"decodedOutput": [
{
"value": true,
"type": "bool",
"indexed": false
}
],
"subtraces": 0,
"traceAddress": []
}
],
"exposureChanges": [
{
"assetInfo": {
"standard": "ERC20",
"type": "Fungible",
"contractAddress": "0x6b175474e89094c44da98b954eedeac495271d0f",
"symbol": "dai",
"name": "Dai",
"logo": "https://coin-images.coingecko.com/coins/images/9956/large/Badge_Dai.png?1696509996",
"decimals": 18,
"dollarValue": "1"
},
"type": "Approve",
"owner": "0xe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2",
"spender": "0xf1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1",
"rawAmount": "0x12b",
"amount": "0.000000000000000299",
"dollarValue": "0.000000000000000299"
}
],
"stateChanges": [
{
"address": "0x6b175474e89094c44da98b954eedeac495271d0f",
"storage": [
{
"slot": "0x6f18ad69436c83a0d8b2c05ee70fa64e30403b1755cc38ee9cb6245926b14b17",
"previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000",
"newValue": "0x000000000000000000000000000000000000000000000000000000000000012b"
}
]
},
{
"address": "0xe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2",
"nonce": {
"previousValue": "0x0",
"newValue": "0x1"
}
}
]
}
}
通过 API 模拟
使用 simulate API 端点以不同参数模拟一笔交易。若要在 Virtual Environments 上使用模拟,我们推荐使用 Simulate RPC 和 Bundle Simulate RPC。
否则,您可以使用 Virtual Environments Simulation API。
Simulation API endpoint on public network
https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_SLUG}/project/${TENDERLY_PROJECT_SLUG}/simulate
Simulation API endpoint on a Virtual Environment
https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_SLUG}/project/${TENDERLY_PROJECT_SLUG}/vnets/{vnetId}/transactions/simulate
请求负载
向该 API 端点发送POST 请求。有关请求负载的完整详情,请参阅 API 参考。
模拟负载类似于 eth_call JSON RPC 调用。
以下字段为必填项:
network_id(string):您希望在其上运行模拟的网络 ID。block_number(number):用于模拟的区块高度,或 “latest”。to(string):交易的接收方地址。from(string):发起交易的地址。input(string):编码后的合约方法调用数据。gas(number):为模拟提供的 gas 数量。
您可以在
from 字段中指定任意发送方地址。由于 Tenderly 模拟的是未签名的交易,您无需
拥有该账户的私钥即可模拟来自特定发送方的交易。simulation_type,可选值为 full、quick 或 ABI。该字段不是必填项,因为默认值为 full。了解更多关于模拟模式的信息。
发起 API 请求时,请添加 X-Access-Key 请求头,其值为访问令牌。
示例
请务必将访问密钥安全地存储在 .env 文件中。
- request.ts
- response.json
request.ts
dotenv.config();
const simulateTransaction = async () => {
const { TENDERLY_ACCOUNT_SLUG, TENDERLY_PROJECT_SLUG, TENDERLY_ACCESS_KEY } = process.env;
const simulation = await axios.post(
`https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_SLUG}/project/${TENDERLY_PROJECT_SLUG}/simulate`,
{
network_id: '1',
block_number: 16533883,
from: '0xe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2',
to: '0x6b175474e89094c44da98b954eedeac495271d0f',
gas: 8000000,
gas_price: 0,
value: 0,
input: '0x095ea7b3000000000000000000000000f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1000000000000000000000000000000000000000000000000000000000000012b',
simulation_type: 'quick',
},
{
headers: {
'X-Access-Key': TENDERLY_ACCESS_KEY as string,
},
},
);
console.log(simulation.data);
};
simulateTransaction();
response.json
{
"transaction": {
"hash": "0x7c1a33fb449b8d4eb5ec042d94d1c7ce2a5acae05f02af58ce4fd8b5c6beaf0a",
"block_hash": "",
"block_number": 16533883,
"from": "0xe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2",
"gas": 8000000,
"gas_price": 0,
"gas_fee_cap": 0,
"gas_tip_cap": 0,
"cumulative_gas_used": 0,
"gas_used": 46098,
"effective_gas_price": 0,
"input": "0x095ea7b3000000000000000000000000f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1000000000000000000000000000000000000000000000000000000000000012b",
"nonce": 0,
"to": "0x6b175474e89094c44da98b954eedeac495271d0f",
"index": 0,
"value": "0x",
"access_list": null,
"status": true,
"addresses": null,
"contract_ids": null,
"network_id": "1",
"timestamp": "2023-02-01T12:11:23Z",
"function_selector": "",
"l1_block_number": 0,
"l1_timestamp": 0,
"deposit_tx": false,
"system_tx": false,
"sig": {
"v": "0x0",
"r": "0x0",
"s": "0x0"
},
"transaction_info": {
"contract_id": "eth:1:0x6b175474e89094c44da98b954eedeac495271d0f",
"block_number": 16533883,
"transaction_id": "0x7c1a33fb449b8d4eb5ec042d94d1c7ce2a5acae05f02af58ce4fd8b5c6beaf0a",
"contract_address": "0x6b175474e89094c44da98b954eedeac495271d0f",
"method": null,
"parameters": null,
"intrinsic_gas": 21584,
"refund_gas": 0,
"call_trace": {
"hash": "0x7c1a33fb449b8d4eb5ec042d94d1c7ce2a5acae05f02af58ce4fd8b5c6beaf0a",
"contract_name": "",
"function_pc": 0,
"function_op": "CALL",
"absolute_position": 0,
"caller_pc": 0,
"caller_op": "CALL",
"call_type": "CALL",
"address": "0xe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2",
"from": "0xe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2",
"from_balance": "0",
"to": "0x6b175474e89094c44da98b954eedeac495271d0f",
"to_balance": "0",
"value": "0",
"block_timestamp": "0001-01-01T00:00:00Z",
"gas": 7978416,
"gas_used": 24514,
"intrinsic_gas": 21584,
"storage_address": "0xe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2",
"input": "0x095ea7b3000000000000000000000000f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1000000000000000000000000000000000000000000000000000000000000012b",
"nonce_diff": [
{
"address": "0xe2E2E2e2e2e2E2E2E2E2e2E2e2E2E2e2e2e2E2e2",
"original": "0",
"dirty": "1"
}
],
"state_diff": [
{
"address": "0x6b175474e89094c44da98b954eedeac495271d0f",
"soltype": null,
"original": null,
"dirty": null,
"raw": [
{
"address": "0x6b175474e89094c44da98b954eedeac495271d0f",
"key": "0x6f18ad69436c83a0d8b2c05ee70fa64e30403b1755cc38ee9cb6245926b14b17",
"original": "0x0000000000000000000000000000000000000000000000000000000000000000",
"dirty": "0x000000000000000000000000000000000000000000000000000000000000012b"
}
]
}
],
"logs": [
{
"name": "",
"anonymous": false,
"inputs": null,
"raw": {
"address": "0x6b175474e89094c44da98b954eedeac495271d0f",
"topics": [
"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925",
"0x000000000000000000000000e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2",
"0x000000000000000000000000f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000012b"
},
"trace_index": null
}
],
"output": "0x0000000000000000000000000000000000000000000000000000000000000001",
"decoded_output": null,
"network_id": "1",
"calls": null
},
"stack_trace": null,
"logs": [
{
"name": "",
"anonymous": false,
"inputs": null,
"raw": {
"address": "0x6b175474e89094c44da98b954eedeac495271d0f",
"topics": [
"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925",
"0x000000000000000000000000e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2",
"0x000000000000000000000000f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000012b"
},
"trace_index": null
}
],
"balance_diff": null,
"nonce_diff": [
{
"address": "0xe2E2E2e2e2e2E2E2E2E2e2E2e2E2E2e2e2e2E2e2",
"original": "0",
"dirty": "1"
}
],
"state_diff": [
{
"address": "0x6b175474e89094c44da98b954eedeac495271d0f",
"soltype": null,
"original": null,
"dirty": null,
"raw": [
{
"address": "0x6b175474e89094c44da98b954eedeac495271d0f",
"key": "0x6f18ad69436c83a0d8b2c05ee70fa64e30403b1755cc38ee9cb6245926b14b17",
"original": "0x0000000000000000000000000000000000000000000000000000000000000000",
"dirty": "0x000000000000000000000000000000000000000000000000000000000000012b"
}
]
}
],
"raw_state_diff": null,
"console_logs": null,
"asset_changes": null,
"balance_changes": [],
"created_at": "2023-02-01T12:11:23Z"
},
"method": "",
"decoded_input": null,
"call_trace": [
{
"call_type": "CALL",
"from": "0xe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2",
"to": "0x6b175474e89094c44da98b954eedeac495271d0f",
"gas": 7978416,
"gas_used": 24514,
"address": "0x6b175474e89094c44da98b954eedeac495271d0f",
"input": "0x095ea7b3000000000000000000000000f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1000000000000000000000000000000000000000000000000000000000000012b",
"output": "0x0000000000000000000000000000000000000000000000000000000000000001"
}
]
},
"simulation": {
"id": "cc4d422b-149c-4043-83ec-d2670c9ffe2c",
"project_id": "dfdc391a-a15d-4590-9aef-8691259c7df4",
"owner_id": "7d5e8b1f-8bf8-4eae-a70f-fb7d354b1cc2",
"network_id": "1",
"block_number": 16533883,
"transaction_index": 0,
"from": "0xe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2",
"to": "0x6b175474e89094c44da98b954eedeac495271d0f",
"input": "0x095ea7b3000000000000000000000000f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1000000000000000000000000000000000000000000000000000000000000012b",
"gas": 8000000,
"gas_price": "0",
"gas_used": 46098,
"value": "0",
"status": true,
"access_list": null,
"queue_origin": "",
"block_header": {
"number": "0xfc497b",
"hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"stateRoot": "0x3a3fd616aa768fc45b78d02fbd216e6a49a19153f92a091f5c4e9a2bbe494ef1",
"parentHash": "0x57067724ea963c92291770db13ff945f9b7e11689d2494ba318cea6cdab1c2e2",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"transactionsRoot": "0x912f0d5b52a308205d1c1a9b15409cbd455b414ac2d2bcb5b13ef01a5b4a41d8",
"receiptsRoot": "0xfdc2b958b59f3ded07e132764112429f8e2827ed0e1d67954e05ee1be5e7e203",
"logsBloom": "0xb0abe9644746d77234090df88b0c836b0d2966107c87597c568582618cc4c773104a2da2b011d90310a8db958c13cb208f196333ba08bb86625b405301beaf22028a2193076aaf7ffb0b64eb77ea6827ec293ac4fb754b719744ff2dd9813d751e5808704bc645bf31107e8472742879cd7acb090b643d4cc27986da095ced5c028143df0223190d1d515345a7e2b1a33333b52587c0c688e57e06e8a390493faff909012981eb860ea2ebc1153684e025c27e2460ae28db74e35eb260fbf8e9522c805356b1022928e8b408235e5e824d7483ecf4ba985a9b470c760c58e06716f0fc28003633d86c35ba840f3512c480039004724dd25a9e599898fab73cf3",
"timestamp": "0x63da56eb",
"difficulty": "0x0",
"gasLimit": "0x1c9c380",
"gasUsed": "0xcb7693",
"miner": "0xdafea492d9c6733ae3d56b7ed1adb60692c98bc5",
"extraData": "0x496c6c756d696e61746520446d6f63726174697a6520447374726962757465",
"mixHash": "0x43f7931adf192e8addc95bfae45f9db586434110ef7eac2d765e4a4b9ed6de4e",
"nonce": "0x0000000000000000",
"baseFeePerGas": "0x32c42d070",
"size": "0x0",
"totalDifficulty": "0x0",
"uncles": null,
"transactions": null
},
"deposit_tx": false,
"system_tx": false,
"nonce": 0,
"addresses": null,
"contract_ids": null,
"shared": false,
"created_at": "2024-01-08T17:30:06.992859393Z"
},
"contracts": [],
"generated_access_list": []
}
探索使用场景
- 预览交易结果:识别并修复可能导致交易失败的问题。
- 资产与余额变化:获取即将发生的所有余额与资产变化的确切美元价值。
- Gas 估算:在发送交易之前准确预测 gas 费用。
- 状态覆盖:修改时间戳、合约数据等区块链状态,以测试不同的场景。