How To Automate Smart Contract Execution Using Chainlink Keepers

The Chainlink Spring 2022 Hackathon kicks off 4/22! Registrations are now open, check out this page to learn more.

Smart contracts are not self-executing, meaning they require an externally owned account, oracle, or contract to initiate their own functions. This creates a problem for many dApps that require their smart contracts to execute at regular time intervals (e.g. every 24 hours), when predefined conditions are met (e.g. Ethereum hitting a specific price), or following a computation (e.g. a loan is calculated to be undercollateralized). 

In the past, developers would solve this problem by creating and maintaining their own centralized scripts to trigger their smart contracts, or trigger them manually. However, this effectively undermines the purpose of building a decentralized blockchain application, and opens up the possibility of downtime if the centralized script or manual triggering process fails. 

In this tutorial you will learn how to use Chainlink Keepers to automate your smart contract execution in a reliable and decentralized manner.

Why Every Smart Contract Developer Should Use Decentralized Automation

Chainlink Keepers unlock a new form of decentralized smart contract automation, enabling developers to transform the way they build and maintain dApps. There are three main benefits to decentralized smart contract automation.

Firstly, it is essential to remove any centralized points of failure in your operations. Chainlink Keepers is powered by a decentralized network of Keeper nodes—the same hyper-reliable nodes that currently secure tens of billions in value across DeFi via Chainlink Data Feeds—removing centralized points of failure.  

Secondly, rather than investing time and resources in creating scripts for on-chain monitoring and contract execution, developers can plug into Chainlink Keepers’s optimized infrastructure by simply creating a Keeper-compatible contract and registering it. This saves time, reduces the DevOps workload, and allows developers to focus on writing more great code. 

Lastly, by using Chainlink Keepers, developers can enhance the security of their protocol. Developers no longer have to risk exposing their own private key when initiating transactions from centralized servers—the nodes on the Chainlink Keeper Network will sign on-chain transactions. 

Get Started With Chainlink Keepers

You can automate your smart contracts with Chainlink Keepers in two steps:

  1. Create and deploy a Keeper-compatible contract 
  2. Register the contract on the Chainlink Keepers app to create an Upkeep

After these steps have been completed, Chainlink Keepers will perform the Upkeep job as specified without any further input.

If you are new to Solidity, we recommend following some of the beginner tutorials before continuing. This tutorial is particularly comprehensive and useful. We will now show you how to make your contract Keeper-compatible. If you prefer watching a video on the topic please watch our video tutorial.

How To Write a Keeper-Compatible Contract

Keeper-compatible contracts have a checkUpkeep function and a performUpkeep function with the required inputs and outputs expected by Chainlink Keepers. To help prevent errors we will use the Keeper-compatible interface before we specify what our check and perform functions should do.

Importing the Keeper-Compatible Interface

Start by importing the KeeperCompatibleInterface into your contract. 

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// KeeperCompatible.sol imports the functions from both ./KeeperBase.sol and
// ./interfaces/KeeperCompatibleInterface.sol

import "@chainlink/contracts/src/v0.8/KeeperCompatible.sol";

There are two functions to this interface: 

The checkUpkeep Function

Chainlink Keepers use a decentralized network to monitor the checkUpkeep function securely and cost-efficiently off-chain during every block and then initiate an on-chain transaction to execute the smart contract function when predefined conditions are met.

function checkUpkeep(
  bytes calldata checkData
)
  external
  returns (
    bool upkeepNeeded,
    bytes memory performData
  );

The checkUpkeep function takes a bytes parameter named checkData that is set when you register your Upkeep on the Keepers app. This value is optional and can be used in your logic to determine if checkUpkeep returns true.   

checkUpkeep returns a bool called upkeepNeeded. When true, this will call performUpkeep. It also returns performData in  Bytes format (optional additional data) that the Keeper should call performUpkeep with if Upkeep is needed. For more information, see the Developer Documentation.

The performUpkeep Function

If the off-chain simulation of your checkUpkeep confirms your predefined conditions are met (upkeepNeeded == true from checkUpkeep), the Keeper will broadcast a transaction to the blockchain executing the performUpkeep with performData as an input.

function performUpkeep(
  bytes calldata performData
) external;

A rotating node selection process prevents gas price auction wars between nodes and stabilizes costs of automating your contracts.

An animation showing how Keepers work

Here is an example contract snippet from Chainlink Keepers user Entropyfi where checkUpkeep checks whether the Entropyfi prediction game is due for settlement.

/**
* @dev chainlink keeper checkUpkeep function to constantly check whether we need function call
**/
function checkUpkeep(bytes calldata checkData) external override returns (bool upkeepNeeded, bytes memory performData) {
     PoolStatus currState = status.currState;
     uint256 lastUpdateTimestamp = status.lastUpdateTimestamp;
     uint256 durationOfGame = status.durationOfGame;
     uint256 durationOfBidding = status.durationOfBidding;

     if (currState == PoolStatus.Accepting && block.timestamp > lastUpdateTimestamp.add(durationOfBidding)) {
          upkeepNeeded = true;
     } else if (currState == PoolStatus.Locked && block.timestamp > lastUpdateTimestamp.add(durationOfGame)) {
          upkeepNeeded = true;
     } else {
          upkeepNeeded = false;
     }
     performData = checkData;
}

Chainlink Keepers will constantly call the checkUpkeep function, and if the upkeepNeeded is evaluated to true, then the nodes will execute the performUpkeep function.

/**
* @dev once checkUpKeep been triggered, keeper will call performUpKeep
**/
function performUpkeep(bytes calldata performData) external override {
     PoolStatus currState = status.currState;
     uint256 lastUpdateTimestamp = status.lastUpdateTimestamp;
     uint256 durationOfGame = status.durationOfGame;
     uint256 durationOfBidding = status.durationOfBidding;

     if (currState == PoolStatus.Accepting && block.timestamp > lastUpdateTimestamp.add(durationOfBidding)) {
          startGame();
     }
     if (currState == PoolStatus.Locked && block.timestamp > lastUpdateTimestamp.add(durationOfGame)) {
          endGame();
     }
     performData;
}

Start With Some Sample Code

Whether you are creating a new contract or already have a contract deployed that contains a function that needs to be automated there are guides to help you get started in the Chainlink Keepers Developer Documentation.

Start with the example contract here. The example below represents a simple counter contract.

// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;

// KeeperCompatible.sol imports the functions from both ./KeeperBase.sol and
// ./interfaces/KeeperCompatibleInterface.sol
import "@chainlink/contracts/src/v0.7/KeeperCompatible.sol";

contract Counter is KeeperCompatibleInterface {
    /**
    * Public counter variable
    */
    uint public counter;

    /**
    * Use an interval in seconds and a timestamp to slow execution of Upkeep
    */
    uint public immutable interval;
    uint public lastTimeStamp;

    constructor(uint updateInterval) {
      interval = updateInterval;
      lastTimeStamp = block.timestamp;

      counter = 0;
    }

    function checkUpkeep(bytes calldata /* checkData */) external override returns (bool upkeepNeeded, bytes memory /* performData */) {
        upkeepNeeded = (block.timestamp - lastTimeStamp) > interval;
        // We don't use the checkData in this example. The checkData is defined when the Upkeep was registered.
    }
    function performUpkeep(bytes calldata /* performData */) external override {
        //We highly recommend revalidating the upkeep in the performUpkeep function
        if ((block.timestamp - lastTimeStamp) > interval ) {
            lastTimeStamp = block.timestamp;
            counter = counter + 1;
        }
        // We don't use the performData in this example. The performData is generated by the Keeper's call to your checkUpkeep function
    }
}
Diagram showing potential Keepers triggers
There are a huge range of possible triggers for smart contract automation.

Chainlink Keepers can monitor the state of any on-chain or off-chain condition, such as the passage of time (e.g. did 24 hours pass?) or a computation (e.g. is the loan calculated to be undercollateralized?). Once a condition is met, Chainlink Keepers submit a transaction on-chain to trigger the function to execute. 

You can also start with a Chainlink Keepers utility contract such as the EthBalanceMonitor contract or these examples.

How to Register Your Contract as an Upkeep on the Network

Once you have your Keeper-compatible contract, head over to the Chainlink Keepers app and click “Register new Upkeep”.  

Registering a new Upkeep

For a detailed step-by-step guide on how to register, see the Chainlink Developer Documentation.

Important note (for non-ETH chains): your Upkeep must be funded with ERC-677 LINK (not ERC-20, which is common across many token bridges). Use PegSwap to make your LINK tokens ERC-677 compatible.

Once registered and approved, you can add additional funds and see all the details for your Upkeep on the Chainlink Keepers app. 

Screenshot illustrating how to register a timed Upkeep

Image of the Keepers dashboard

Get Started Today

Now that you know how easy it is to automate your smart contracts with Chainlink Keepers, you can get started with integrating Keepers and unlock a huge range of use cases, such as DEX limit orders, cross-chain NFT minting, rebasing and rebalancing tokens, and much more. 

Learn more by visiting the developer documentation and joining the technical discussion in Discord. If you want to schedule a call to discuss the integration more in-depth, reach out here.

To learn more, visit chain.link, subscribe to the Chainlink newsletter, and follow Chainlink on Twitter, YouTube, and Reddit.