Development of Smart Contract Monitoring System
Deployed contract without monitoring—production server without logs. When something breaks, you learn from Twitter. Smart contract monitoring system solves three tasks: real-time alerts on important events, historical analytics of usage patterns and anomalies, operational control of gas usage and failed transactions.
What to Monitor
Critical (immediate alert, on-call):
- Ownership or role changes
- Upgrade/migrate function calls
- Withdrawals above threshold
- Pause/unpause calls
- Failed transactions to critical functions
High (Telegram/Slack alert, 15 minutes):
- Unusually large transactions
- Sharp TVL changes (>10% per block)
- New addresses with large positions
- Oracle price deviations
Medium (hourly digest):
- Transaction volume trends
- Unique users
- Gas usage patterns
- Error rates by function
Low (daily report):
- General protocol statistics
- New users, retention
- Fees collected
Architecture
Event Listener Service
class ContractMonitor {
private provider: ethers.WebSocketProvider;
private contracts: Map<string, ethers.Contract> = new Map();
private alertQueue: AlertQueue;
async addContract(config: ContractConfig): Promise<void> {
const contract = new ethers.Contract(config.address, config.abi, this.provider);
this.contracts.set(config.address.toLowerCase(), contract);
contract.on('*', async (event) => {
await this.processEvent(config.name, event);
});
}
private async processEvent(contractName: string, event: ethers.EventLog): Promise<void> {
const enriched = {
contractName,
eventName: event.eventName,
args: Object.fromEntries(
Object.entries(event.args).filter(([k]) => isNaN(Number(k)))
),
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
timestamp: Date.now(),
};
const severity = this.assessSeverity(enriched);
if (severity !== 'low') {
await this.alertQueue.push({ ...enriched, severity });
}
}
private assessSeverity(event: any): 'low' | 'medium' | 'high' | 'critical' {
const criticalEvents = ['OwnershipTransferred', 'RoleGranted', 'Upgraded', 'Paused'];
if (criticalEvents.includes(event.eventName)) return 'critical';
if (event.args?.amount && BigInt(event.args.amount) > LARGE_AMOUNT_THRESHOLD) return 'high';
return 'low';
}
}
Invariant Checker
const invariants = [
{
name: 'tvl_drop',
check: async (state) => {
const drop = (state.prevTVL - state.currentTVL) / state.prevTVL;
return drop < 0.15; // not more than 15% per block
},
message: (s) => `TVL dropped from ${s.prevTVL} to ${s.currentTVL}`,
},
{
name: 'total_supply_consistency',
check: async (state) => {
return Math.abs(state.totalSupply - state.sumOfTopBalances) < state.totalSupply * 0.001;
},
},
];
Alerting and Integrations
Telegram Bot
async function sendTelegramAlert(alert: Alert): Promise<void> {
const emoji = { critical: '🚨', high: '⚠️', medium: 'ℹ️' }[alert.severity];
const message = `
${emoji} *${alert.severity.toUpperCase()}: ${alert.eventName}*
Contract: \`${alert.contractName}\`
Block: [${alert.blockNumber}](https://etherscan.io/block/${alert.blockNumber})
Tx: [${alert.txHash.slice(0, 10)}...](https://etherscan.io/tx/${alert.txHash})
${formatArgs(alert.args)}
_${new Date(alert.timestamp).toISOString()}_
`.trim();
await fetch(`https://api.telegram.org/bot${BOT_TOKEN}/sendMessage`, {
method: 'POST',
body: JSON.stringify({
chat_id: ALERT_CHAT_ID,
text: message,
parse_mode: 'Markdown',
}),
});
}
Metrics and Dashboard
Key panels: Protocol Health (TVL, active users, tx/hour), Transaction Flow, Gas Usage, Error Rate, Security Events.
Metrics stored in Prometheus, visualized in Grafana.
Development: 4-6 weeks for MVP, 8-12 weeks for full system with Grafana dashboards and cross-chain support.







