Simulate an EVM transaction against a forked chain state using Tenderly, and verify that the resulting asset changes match stated intent. Intended to be invoked by other skills as a pre-execution safety gate.
This skill should be invoked before any onchain transaction is sent when:
data hex string from a swap router)If this skill is not installed, calling skills should warn the user that pre-execution verification is unavailable and ask for explicit confirmation before proceeding.
One environment variable is required:
bash
export TENDERLY_NODE_ACCESS_KEY="your-key-here"
Obtain a key from Tenderly — the free tier supports approximately 62,500 simulations per month (400 TUs per simulation, 25M TU/month free).
The Tenderly gateway uses a per-chain subdomain. Route to the correct endpoint based on the transaction's chainId. The access key is passed as a header — do not embed it in the URL:
ChainchainIdEndpointBase8453``https://base.gateway.tenderly.coEthereum1``https://mainnet.gateway.tenderly.coOptimism10``https://optimism.gateway.tenderly.coArbitrum One42161``https://arbitrum.gateway.tenderly.coPolygon137``https://polygon.gateway.tenderly.co
If the chainId is not in this list, skip verification, warn the user that the chain is unsupported, and require explicit confirmation before proceeding.
Add new entries as additional chains become supported.
The calling skill provides a transaction payload with the following fields:
FieldTypeNotesfromaddressThe wallet sending the transactiontoaddressThe contract being calleddatahex stringEncoded calldatavaluehex stringNative token value (e.g. "0x0")chainIdintegerUsed to select the correct Tenderly endpoint
For cross-chain swaps, chainId refers to the source chain — the chain where the transaction is sent. Verify the outbound leg only.
bash
TENDERLY_URL="https://base.gateway.tenderly.co"
curl -sS -X POST "$TENDERLY_URL" \
-H "Content-Type: application/json" \
-H "X-Access-Key: $TENDERLY_NODE_ACCESS_KEY" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tenderly_simulateTransaction",
"params": [
{
"from": "0xYourWalletAddress",
"to": "0xContractAddress",
"data": "0xCalldata",
"value": "0x0"
},
"latest"
]
}'
FieldDescriptionresult.assetChangesERC-20 token transfers: token address, from, to, amountresult.balanceChangesNative token (ETH) balance changes per address
After Tenderly simulation, check the following before approving execution:
If any check fails, stop and surface the discrepancy clearly. Do not proceed to execution without explicit user confirmation.
text
"Verifying transaction on Base via Tenderly..."
"Verification complete. Asset changes:"
" → Send 5 USDC from 0xYour... to 0xRouter..."
" ← Receive 0.00242 WETH at 0xYour..."
"All checks passed. Proceeding to execution."
If a check fails:
text
"Verification flagged an issue:"
" Output token destination is 0xUnexpected... — expected 0xYour..."
"Do not proceed until this is resolved. Aborting."
ConditionActionTENDERLY_NODE_ACCESS_KEY not setWarn that verification is unavailable; require explicit user confirmation before proceedingchainId not in supported listWarn that chain is unsupported for verification; require explicit user confirmationTenderly returns an errorSurface the error message; treat as verification failure and require confirmationRate limit hit (HTTP 429)Warn the user; do not retry automatically; require confirmation to proceed without verificationVerification passes all checksReturn control to the calling skill to proceed with executionVerification fails a checkHalt; surface the specific discrepancy; do not execute