# Tenderly — Debug and Monitor Smart Contracts Like a Pro
Smart contract bugs can cost millions. Traditional debugging tools are limited — you can't easily step through failed transactions or simulate changes before deployment. Tenderly solves this with a comprehensive platform for debugging, monitoring, simulating, and testing smart contracts. Whether you're tracking down a mysterious revert or optimizing gas costs, Tenderly provides the insights you need to ship production-ready code with confidence.
What is Tenderly?
Tenderly is a Web3 development platform offering:
- Transaction debugging — Step through any transaction, even failed ones
- Gas profiling — Identify expensive operations and optimize costs
- Alerts — Real-time notifications for contract events
- Simulations — Test transactions before sending them
- Forks — Create private testnets from any network state
- Monitoring — Track contract performance and usage
- Web3 Actions — Serverless functions triggered by on-chain events
Used by teams at Aave, Uniswap, Compound, and thousands of other projects, Tenderly is essential for professional smart contract development.
Getting Started
Create an Account
Add a Contract
Option 1: Search by Address
- Click "Add Contract"
- Paste contract address
- Select network (Ethereum, Polygon, Arbitrum, etc.)
- Tenderly auto-detects verified contracts
Option 2: Import from Hardhat/Foundry
Install Tenderly CLI:
npm install --save-dev @tenderly/hardhat-tenderly
Configure hardhat.config.js:
require("@tenderly/hardhat-tenderly");
module.exports = {
tenderly: {
username: "your-username",
project: "your-project"
}
};
Push contracts:
npx hardhat tenderly:verify ContractName --network mainnet
Transaction Debugging
Debug Any Transaction
Tenderly's killer feature: debug any transaction on any EVM chain, including failed transactions.
Steps:
You'll see:
- Call trace — every function call, nested calls, and external calls
- State changes — storage updates, balance changes
- Gas usage — per operation
- Events emitted — all logs
- Execution stack — Solidity source code with highlighted lines
- Debugger — step-by-step execution
Example: Debugging a Failed Transfer
Let's debug a transaction that reverted:
Transaction: 0xabc123...
Error: execution reverted
In Tenderly:
require(balanceOf[msg.sender] >= amount, "Insufficient balance");
balanceOf[sender] was 50 but amount was 100Without Tenderly, you'd only see "execution reverted" — with it, you know exactly why.
Step-by-Step Debugging
Click Debugger tab:
- Step Over — Execute current line
- Step Into — Enter function call
- Step Out — Exit function
- Continue — Run until next breakpoint
Hover over variables to see their values at any point in execution.
Viewing State Changes
The State Changes tab shows:
- Storage updates — which slots changed and to what values
- Balance changes — ETH transferred
- Contract creation — if new contracts were deployed
Filter by contract or variable name for clarity.
Gas Profiling
Optimize your contract's gas consumption with Tenderly's gas profiler.
How to Use the Gas Profiler
- Total gas — overall transaction cost
- Per function — gas used by each function
- Per opcode — most expensive operations (SSTORE, SLOAD, etc.)
- Flame graph — visual representation of gas usage
Example: Finding Expensive Loops
function batchTransfer(address[] calldata recipients, uint256 amount) external {
for (uint i = 0; i < recipients.length; i++) {
_transfer(msg.sender, recipients[i], amount);
}
}
Gas profiler shows:
- SSTORE operations dominate (90% of gas)
- Each
_transferwrites tobalanceOfmapping twice
Optimization: Batch update balances in memory, write to storage once.
function batchTransfer(address[] calldata recipients, uint256 amount) external {
uint256 totalAmount = recipients.length * amount;
require(balanceOf[msg.sender] >= totalAmount);
balanceOf[msg.sender] -= totalAmount; // One SSTORE
for (uint i = 0; i < recipients.length; i++) {
balanceOf[recipients[i]] += amount; // Multiple SSTOREs, but unavoidable
}
}
Gas saved: ~5,000 per transfer (one SSTORE eliminated).
Simulations
Test transactions before sending them to avoid failed transactions and wasted gas.
Simulate a Transaction
- From address — caller
- To address — contract
- Function — method to call
- Parameters — function arguments
Tenderly executes the transaction in a sandboxed environment and shows:
- Will it succeed or revert?
- Gas cost
- State changes
- Events emitted
Use Cases
Test before deployment:
// Simulate minting 1M tokens to see gas cost
simulate: mint(0x123..., 1000000)
Test complex interactions:
// Simulate a flash loan attack to verify defenses
simulate: flashLoan(10000 ETH) → swap() → exploit()
Test with different states:
- Fork at a specific block
- Modify contract storage (e.g., set balance to 1M ETH)
- Simulate transaction in this modified state
Forks — Private Testnets from Any State
Tenderly Forks create a private, simulated version of any EVM network at any block height.
Create a Fork
- Network — Ethereum Mainnet, Polygon, Arbitrum, etc.
- Block number — current or historical block
You get a private RPC URL (e.g., https://rpc.tenderly.co/fork/abc123).
Use the Fork
With MetaMask:
With Hardhat:
module.exports = {
networks: {
tenderlyFork: {
url: "https://rpc.tenderly.co/fork/abc123"
}
}
};
Run tests:
npx hardhat test --network tenderlyFork
Fork Features
Modify state:
- Set any address balance
- Change contract storage
- Fast-forward time
Unlimited ETH:
- No need for faucets
- Test large transactions
Instant mining:
- No waiting for block confirmations
- Perfect for CI/CD
Example: Testing a Live Protocol
You want to test an Aave liquidation:
All without spending real ETH or affecting mainnet.
Alerts — Real-Time Monitoring
Set up alerts to be notified when specific events occur.
Create an Alert
- Contract — which contract to monitor
- Event — which event to trigger on (e.g., Transfer, Approval, OwnershipTransferred)
- Conditions — filter by parameters (e.g., amount > 10 ETH)
- Destination — Email, Slack, Discord, Webhook
Example Alerts
Monitor large transfers:
Event: Transfer
Condition: value > 1000000 (1M tokens)
Destination: Slack #security
Detect contract ownership changes:
Event: OwnershipTransferred
Destination: Email
Track failed transactions:
Status: Failed
Destination: Discord #dev-ops
Monitor gas spikes:
Condition: gasUsed > 5000000
Destination: Webhook
Web3 Actions — Serverless Functions
Web3 Actions are serverless functions triggered by blockchain events.
Create a Web3 Action
- Webhook — HTTP endpoint
- Block — every N blocks
- Transaction — specific contract/event
const { ethers } = require("ethers");
module.exports = async (context) => {
const { transaction, network } = context;
// Your logic here
console.log(New transfer: ${transaction.hash});
// Send notification, update database, trigger another transaction, etc.
};
Example: Auto-Rebalancing Bot
Trigger when token price deviates from target:
module.exports = async (context) => {
const { provider, secrets } = context;
const price = await getTokenPrice(provider);
const targetPrice = 1.0;
if (Math.abs(price - targetPrice) > 0.05) {
// Price deviated > 5%
await rebalance(provider, secrets.PRIVATE_KEY);
}
};
Example: Automated Treasury Management
Transfer funds when balance is low:
module.exports = async (context) => {
const { provider, secrets } = context;
const balance = await provider.getBalance(treasuryAddress);
if (balance < ethers.parseEther('10')) {
// Refill treasury
const signer = new ethers.Wallet(secrets.PRIVATE_KEY, provider);
await signer.sendTransaction({
to: treasuryAddress,
value: ethers.parseEther('100')
});
}
};
Monitoring Dashboards
Create custom dashboards to track contract performance.
Available Metrics
- Transaction volume — number of transactions
- Gas usage — total gas consumed
- Unique users — distinct callers
- Function calls — which functions are called most
- Error rate — percentage of failed transactions
- Average gas cost — per transaction or function
Create a Dashboard
- Line chart (transactions over time)
- Bar chart (top functions by gas)
- Table (recent failed transactions)
Best Practices
1. Debug Failed Transactions Immediately
When a transaction fails in production:
2. Simulate Before Every Mainnet Deployment
Before deploying to mainnet:
3. Set Up Alerts for Critical Events
Monitor:
- Ownership transfers
- Large withdrawals
- Failed transactions
- Gas spikes
- Unusual activity
4. Use Forks for Integration Testing
Test your dApp against real protocols:
5. Profile Gas on Every Release
Run gas profiler on key functions:
- Identify regressions (gas increases)
- Optimize hot paths
- Compare before/after optimizations
Pricing
Free Tier:
- 5,000 transactions/month
- Basic debugging
- 3 alerts
- 1 fork
Developer Tier ($50/month):
- 50,000 transactions/month
- Advanced debugging
- Unlimited alerts
- 10 forks
- Web3 Actions
Team Tier ($200/month):
- 500,000 transactions/month
- Team collaboration
- Custom SLAs
- Priority support
Most solo developers and small teams can stay on the free tier.
Tenderly CLI
Install:
npm install -g @tenderly/cli
Login:
tenderly login
Export ABI:
tenderly export init
tenderly export
Push contracts:
tenderly contracts upload
Conclusion
Tenderly is an essential tool for professional smart contract development. Its powerful debugging, simulation, and monitoring capabilities catch bugs before they reach production, optimize gas costs, and provide real-time insights into contract behavior. Whether you're building a simple token or a complex DeFi protocol, Tenderly helps you ship with confidence.
Start debugging smarter today — sign up for Tenderly and connect your first contract. Practice advanced debugging techniques with Solingo's security challenges to build bulletproof smart contracts.
Next steps:
- Debug a failed transaction from Etherscan
- Create a fork and test a complex interaction
- Set up alerts for your deployed contracts
- Use the gas profiler to optimize an expensive function