0

I have a factory contract which deploys a custom contract. The custom contract imports Automation Compatible.sol and implements checkUpkeep() and performUpkeep()

The factory contract has a function for creating a new custom contract. When a new custom contract is created, the same function calls the following function, passing the new contract as a parameter, to register it.

function registerUpkeepForDeployedContract(address _deployedContract) private returns (bool) {
        bytes memory registrationData =
            abi.encode("", hex"", _deployedContract, 200000, owner(), 0, hex"", hex"", hex"", 1000000000000000000);

        LinkTokenInterface(link).approve(registrar, 1000000000000000000);
        bool success = LinkTokenInterface(link).transferAndCall(registrar, 1000000000000000000, registrationData);
        if (!success) revert DerivativeFactory__LinkTransferAndCallFailed();
        return success;
    }

link and registrar are set in the constructor with the relevant testnet's addresses. I send LINK tokens to the factory contract before attempting to create and register a new custom contract, but the transaction reverts everytime. The revert is happening because of the registerUpkeepForDeployedContract() shared above, versions of the same factory contract without Automation registration have worked fine.

If anyone can offer any help I'd be very grateful. Thanks!

Edit: I tried a slightly different way based on this example from the Chainlink docs, but it still reverts. Here is what I did:

I defined these outside the contract:

struct RegistrationParams {
    string name;
    bytes encryptedEmail;
    address upkeepContract;
    uint32 gasLimit;
    address adminAddress;
    uint8 triggerType;
    bytes checkData;
    bytes triggerConfig;
    bytes offchainConfig;
    uint96 amount;
}

interface AutomationRegistrarInterface {
    function registerUpkeep(RegistrationParams calldata requestParams) external returns (uint256);
}

and added this function to be called when a new Automation Compatible contract is created, passing its address as a parameter:

function registerAndPredictID(address _deployedContract) public {
        RegistrationParams memory params = RegistrationParams({
            name: "",
            encryptedEmail: hex"",
            upkeepContract: _deployedContract,
            gasLimit: 2000000,
            adminAddress: owner(),
            triggerType: 0,
            checkData: hex"",
            triggerConfig: hex"",
            offchainConfig: hex"",
            amount: 1000000000000000000
        });

        LinkTokenInterface(link).approve(registrar, params.amount);
        uint256 upkeepID = AutomationRegistrarInterface(registrar).registerUpkeep(params);
        if (upkeepID != 0) {
            emit UpkeepRegistered(upkeepID, _deployedContract);
        } else {
            revert("auto-approve disabled or registration failed");
        }
    }

Edit: I put together a basic test contract with the above premise and Automation Compatible to try out in Remix - it is still reverting after sending it LINK and trying to call registerAndPredictID() with its own address:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {AutomationCompatible} from "@chainlink/contracts/src/v0.8/automation/AutomationCompatible.sol";

struct RegistrationParams {
    string name;
    bytes encryptedEmail;
    address upkeepContract;
    uint32 gasLimit;
    address adminAddress;
    uint8 triggerType;
    bytes checkData;
    bytes triggerConfig;
    bytes offchainConfig;
    uint96 amount;
}

interface AutomationRegistrarInterface {
    function registerUpkeep(RegistrationParams calldata requestParams) external returns (uint256);
}

contract AutoTest is Ownable, AutomationCompatible {
    error NoLinkToWithdraw();
    error LinkTransferFailed();

    event UpkeepRegistered(uint256 upkeepID, address derivativeContract);

    address public link;
    address public registrar;

    constructor(address _link, address _registrar) Ownable(msg.sender) {
        link = _link;
        registrar = _registrar;
    }

    function registerAndPredictID(address _deployedContract) public {
        RegistrationParams memory params = RegistrationParams({
            name: "",
            encryptedEmail: '0x',
            upkeepContract: _deployedContract,
            gasLimit: 2000000,
            adminAddress: msg.sender,
            triggerType: 0,
            checkData: '0x',
            triggerConfig: '0x',
            offchainConfig: "",
            amount: 5000000000000000000
        });

        LinkTokenInterface(link).approve(registrar, params.amount);
        uint256 upkeepID = AutomationRegistrarInterface(registrar).registerUpkeep(params);
        if (upkeepID != 0) {
            emit UpkeepRegistered(upkeepID, _deployedContract);
        } else {
            revert("auto-approve disabled or registration failed");
        }
    }

    function checkUpkeep(bytes calldata /* checkData */ )
        external
        view
        cannotExecute
        returns (bool upkeepNeeded, bytes memory /* performData */ )
    {
        upkeepNeeded = (block.timestamp >= block.timestamp + 10 minutes);
        return (upkeepNeeded, bytes(""));
    }

  
    function performUpkeep(bytes calldata /* performData */ ) external {
        
    }

    function withdrawLink() public onlyOwner {
        uint256 balance = LinkTokenInterface(link).balanceOf(address(this));
        if (balance == 0) revert NoLinkToWithdraw();

        if (!LinkTokenInterface(link).transfer(msg.sender, balance)) revert LinkTransferFailed();
    }
}

2 Answers 2

0

After discussing this with someone from Chainlink, it turned out the registrar address in the docs was out of date. I'm happy to have helped find this.

0

Hello palmcivet

The docs are being updated, but if you are on one of these networks, please use these updated addresses:

  • Eth Sepolia Registrar: 0xb0E49c5D0d05cbc241d68c05BC5BA1d1B7B72976
  • Polygon Registrar: 0x0Bc5EDC7219D272d9dEDd919CE2b4726129AC02B
  • Arb Goerli Registry: 0x3202a5e8f50f31a89a785eE096468DB338E93DF3
  • Opt Goerli Registrar: 0xCA7A0b1F8153EcD3861899d468dC946F22B39114

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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