I created a bare bone Chainlink keeper for testing purpose. In checkUpkeep, I set upkeepNeeded to true and emit an event. In performUpkeep, I increment a counter and emit another event. Surprisingly, only the event in performUpkeep is emitted. Anyone knows why the event in checkUpkeep is not emitted?

Link to contract deployed on kovan: https://kovan.etherscan.io/address/0xE5c13FEe7F4DDBB19f0941b8616f8B9D5EB77dB5#events

Link to keeper: https://keepers.chain.link/kovan/2738

Contract code:

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

interface KeeperCompatibleInterface {
    function checkUpkeep(bytes calldata checkData) external returns (bool upkeepNeeded, bytes memory performData);
    function performUpkeep(bytes calldata performData) external;

contract Huma is KeeperCompatibleInterface {

    event UpkeepChecked(uint256 timestamp);
    event UpkeepPerformed( uint counter );
    uint public counter;

    function checkUpkeep(bytes calldata checkData) external override returns (bool upkeepNeeded, bytes memory performData) {       
        upkeepNeeded = true;
        performData = checkData;
        emit UpkeepChecked(block.timestamp);

    function performUpkeep(bytes calldata /*performData*/) external override {
        emit UpkeepPerformed(counter);

1 Answer 1


Chainlink keepers only simulate calling checkUpkeep.

Per the docs.

Because checkUpkeep is only ever performed off-chain in simulation, for most cases it is best to treat this as a view function and not modify any state. This might not always be possible if you want to use more advanced Solidity features like DelegateCall. It is a best practice to import the KeeperCompatible.sol contract and use the cannotExecute modifier to ensure that the method can be used only for simulation purposes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.