Ready to Implement Chainlink Automation?
Get expert guidance on automating your smart contract functions.
Complete Guide
Quick Answer
Chainlink Automation enables time-based (every X seconds/minutes/hours) and conditional (checkUpkeep returns true) execution. Cost: 0.01–0.05 LINK per performUpkeep call (~$0.10–$0.50) + gas. Daily automation: ~$40–$180/year. Frequent (every 5 min): ~$3,000–$15,000/year. Pre-fund your upkeep with sufficient LINK to avoid lapses.
Two Automation Types
Time-based: Execute every X seconds/minutes/hours. Example: compound DeFi vault rewards every 24 hours.
Custom logic (conditional): Execute when your contract's `checkUpkeep()` function returns true. Example: liquidate positions when health factor drops below 1.0.
Time-Based Automation
// Register at automation.chain.link → set schedule (every 24h = 86400 seconds)
// When time triggers: Chainlink calls performUpkeep()
contract DailyRewardDistributor {
function performUpkeep(bytes calldata) external {
// Only Chainlink Automation calls this
require(msg.sender == AUTOMATION_FORWARDER, "Not authorized");
_distributeRewards();
}
function _distributeRewards() internal {
uint256 pendingRewards = rewardPool.balanceOf(address(this));
if (pendingRewards == 0) return;
// Distribute proportionally to all stakers
uint256 rewardPerShare = pendingRewards * 1e18 / totalStaked;
cumulativeRewardPerShare += rewardPerShare;
emit RewardsDistributed(pendingRewards, cumulativeRewardPerShare);
}
}Custom Logic Automation
// checkUpkeep: called off-chain continuously to check if action needed
// performUpkeep: called on-chain only when checkUpkeep returns true
contract AutoLiquidator is AutomationCompatibleInterface {
ILendingProtocol public lendingProtocol;
// Chainlink checks this off-chain every few seconds (gas-free)
function checkUpkeep(bytes calldata checkData)
external view override
returns (bool upkeepNeeded, bytes memory performData)
{
// Decode which positions to check
address[] memory positions = abi.decode(checkData, (address[]));
address[] memory liquidatable;
for (uint256 i = 0; i < positions.length; i++) {
if (lendingProtocol.isLiquidatable(positions[i])) {
liquidatable[liquidatable.length] = positions[i];
}
}
upkeepNeeded = liquidatable.length > 0;
performData = abi.encode(liquidatable);
}
// Called on-chain only when upkeepNeeded = true
function performUpkeep(bytes calldata performData) external override {
require(msg.sender == AUTOMATION_FORWARDER, "Not authorized");
address[] memory toLiquidate = abi.decode(performData, (address[]));
for (uint256 i = 0; i < toLiquidate.length; i++) {
// Re-check before liquidating (state may have changed)
if (lendingProtocol.isLiquidatable(toLiquidate[i])) {
lendingProtocol.liquidate(toLiquidate[i]);
}
}
}
}Log-Trigger Automation
// Trigger automation when a specific event is emitted on-chain
contract EventTriggeredAction is ILogAutomation {
// Triggered when a specific event fires
function checkLog(Log calldata log, bytes calldata checkData)
external pure override
returns (bool upkeepNeeded, bytes memory performData)
{
// Decode event data
address triggeredContract = address(uint160(uint256(log.topics[1])));
uint256 amount = abi.decode(log.data, (uint256));
// Trigger action if amount exceeds threshold
upkeepNeeded = amount >= THRESHOLD;
performData = abi.encode(triggeredContract, amount);
}
function performUpkeep(bytes calldata performData) external override {
(address triggeredContract, uint256 amount) = abi.decode(performData, (address, uint256));
// Execute automated response to the logged event
_respondToEvent(triggeredContract, amount);
}
}