Trigger Smart Contract Execution With Chainlink Automation

Smart contracts are not self-executing, meaning they require an externally owned account, oracle, or contract to trigger 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 Automation to trigger smart contract execution in a reliable, automatic, and decentralized manner.

Why Use Decentralized Automation To Trigger a Smart Contract?

Chainlink Automation unlocks a new way to trigger smart contract execution in a decentralized manner, enabling developers to transform the way they build and maintain dApps. There are three main benefits to decentralized smart contact automation.

Firstly, it is essential to remove any centralized points of failure in your operations. Chainlink Automation is powered by a decentralized network of 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 triggering smart contract execution, developers can plug into Chainlink Automation’s optimized infrastructure by simply creating an Automation-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 Automation, 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 Automation Network will sign on-chain transactions.

Get Started With Chainlink Automation

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

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

After these steps have been completed, Chainlink Automation 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 Automation-compatible. If you prefer watching a video on the topic please watch our video tutorial.

How To Create Automated Triggers for Smart Contracts

To create an automated trigger for smart contract execution, you need to write an Automation-compatible smart contract. Automation-compatible contracts have a checkUpkeep function and a performUpkeep function with the required inputs and outputs expected by Chainlink Automation. To help prevent errors we will use the Automation-compatible interface before we specify what our check and perform functions should do.

Importing the Automation-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 Automation uses a decentralized network to monitor the checkUpkeep function securely and cost-efficiently off-chain during every block and then initiates 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 Automation 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 Automation Node 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 Automation Node 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 Automation 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 Automation Nodes 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 Automation 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 Automation 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, Automation nodes submit a transaction on-chain to trigger the smart contract to execute.

You can also start with a Chainlink Automation utility contract such as the EthBalanceMonitor contract.

How to Register Your Contract as an Upkeep on the Network

Once you have your Automation-compatible contract, head over to the Chainlink Automation 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 Automation 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 Automation, you can get started with integrating Chainlink Automation 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.

Chainlink 2023 Fall Hackathon

Disclaimer

Level
Medium
Duration
180 min
Stack
Ethereum, Solidity, Javascript
Services
Requirements
  • Web3.js or Ethers.js
  • Hardhat or Foundry
Last updated: Aug 28, 2024