OpenZeppelin Defender Integration (Automation)
Smart contracts don't live in isolation. They need to execute scheduled tasks (reward distribution, rebalancing), react to on-chain events (liquidations, lock-up expiration), and do this without manual intervention. The usual approach is a server with a cron job and a private key. OpenZeppelin Defender eliminates the need to store keys on a server and adds monitoring, alerts, and audit trail out of the box.
Defender Components and How They Connect
Relayer — a managed wallet that sends transactions on your behalf. The private key is stored in Defender's HSM, you never see it. Relayer automatically manages nonce and gas price (EIP-1559), handles resubmit for stuck transactions.
Actions (formerly Autotask) — serverless JavaScript functions that run on schedule or via webhook. Inside Action you get a prebuilt Relayer for transaction signing and Provider for reading chain state.
Monitor (formerly Sentinel) — monitoring for on-chain events and function calls. When a condition triggers — webhook, email, or Action call.
Proposal — mechanism for executing transactions via Safe{Wallet} multisig or Timelock. Instead of direct function call — a proposal is created that must be approved by signers.
Typical Architecture: Automatic Liquidations
Consider a real scenario: lending protocol, need to liquidate positions with health factor < 1.
Monitor → watches Transfer and Borrow events
→ when collateral price drops via Price Feed
→ triggers Action
Action → reads health factor via view-function
→ if HF < 1, calls liquidate() via Relayer
→ logs result
Action code:
const { ethers } = require("ethers");
const { DefenderRelayProvider, DefenderRelaySigner } = require('@openzeppelin/defender-relay-client/lib/ethers');
exports.handler = async function(credentials) {
const provider = new DefenderRelayProvider(credentials);
const signer = new DefenderRelaySigner(credentials, provider, { speed: 'fast' });
const lending = new ethers.Contract(LENDING_ADDRESS, LENDING_ABI, signer);
// Get list of positions for liquidation (off-chain via Subgraph)
const positions = await getUnderwaterPositions();
for (const position of positions) {
const hf = await lending.getHealthFactor(position.borrower);
if (hf < ethers.parseEther("1")) {
const tx = await lending.liquidate(position.borrower, position.collateral);
console.log(`Liquidated ${position.borrower}: ${tx.hash}`);
}
}
};
speed: 'fast' — Relayer uses maxPriorityFeePerGas from Defender's gas oracle. Also available: safeLow, average, rapid.
Monitor: Setting Up Alerts
Monitor is configured for a specific contract, network, and condition. Three types of conditions:
- Event trigger — contract emitted a specific event
- Function call — a function was called (even if it reverted)
- Expression — arbitrary expression based on event args or call args
Example: alert on any treasury withdrawal over 50 ETH:
Event: Withdrawal(address indexed to, uint256 amount)
Condition: amount > 50000000000000000000
When triggered — webhook to Slack or PagerDuty. For critical events we configure Action to automatically pause the contract via Pausable.
Safe Deployment via Proposal
For contracts with multisig (Safe{Wallet}) or Timelock, we recommend managing upgrades via Defender Proposal instead of direct calls:
// Hardhat task to create proposal
const { AdminClient } = require('@openzeppelin/defender-admin-client');
const client = new AdminClient({ apiKey, apiSecret });
await client.createProposal({
contract: { address: PROXY_ADDRESS, network: 'mainnet' },
title: 'Upgrade to V2',
description: 'Fix reentrancy in withdraw()',
type: 'upgrade',
newImplementation: NEW_IMPL_ADDRESS,
via: SAFE_ADDRESS,
viaType: 'Gnosis Safe'
});
Proposal is visible in Defender interface. Safe signers see details and approve via UI. The entire process is logged — who created, who approved, when executed.
Hardhat and Foundry Integration
For Hardhat — @openzeppelin/hardhat-upgrades plus @openzeppelin/defender-deploy-client:
// hardhat.config.js
module.exports = {
defender: {
apiKey: process.env.DEFENDER_KEY,
apiSecret: process.env.DEFENDER_SECRET
}
};
Foundry — integration via Defender API directly or via CLI defender-deploy. Less native, but works.
Timeline Estimates
Basic Relayer + Action setup for automating one task: 1 day. Full integration with Monitor, alerts, Safe Proposal workflow and testnet testing: 2-3 days.
Defender cost depends on plan (free tier exists with limits on Actions and Monitors count). These are project operational expenses, not one-time development cost.







