# Secure Upkeeps Using the Forwarder
Source: https://docs.chain.link/chainlink-automation/guides/forwarder

> For the complete documentation index, see [llms.txt](/llms.txt).

This tutorial explains how to use the `Forwarder` to add additional security to your Automation upkeeps. To learn how other Chainlink Automation contracts work, click [here](/chainlink-automation/reference/automation-contracts).## What is a Forwarder? When is it used?Each registered upkeep under the Chainlink Automation network has its own unique `Forwarder` contract. The `Forwarder` address becomes available only after upkeep registration, as we deploy a new forwarder for each upkeep. The `Forwarder` contract is the intermediary between the Automation Registry and your Upkeep contract, so you make it the `msg.Sender` for your upkeep.If you don't use the forwarder address, your contract's `performUpkeep` function is open and callable by anyone. If your contract is without risk of accepting unintentional external data, you don't need to use the forwarder address.## Securing your upkeepIf your upkeep's perform function needs to be permissioned, please consider setting `msg.sender` as your forwarder address at the top of your `performUpkeep` function.To make this work you will need to:- Create `forwarder` as a mutable address variable on your contract that only *you* can update. `forwarder` is a unique value that cannot change for your upkeep.
- Create a `setForwarder` function in your contract so you can update the `forwarder` address.
- Register your upkeep and then retrieve its forwarder address from the Chainlink Automation App or programmatically.
- Call the `setForwarder` function, passing the forwarder address as an input argument.> **CAUTION: Permissioning for time-based upkeeps**
>
> For [time-based upkeeps](/chainlink-automation/guides/job-scheduler), the **Upkeep address** is the address of the contract that is calling your contract. Do **not** use the forwarder address to permission time-based upkeeps.
>
> In the [Chainlink Automation App](https://automation.chain.link/), open the Details page for your upkeep. Locate the listed **Upkeep address** and use it instead of the **Forwarder address** for permissioning.### Finding the forwarder addressAfter you register an upkeep, its forwarder address is available in the Chainlink Automation App. Alternatively, you can fetch it programmatically using `registry.getForwarder(upkeepID)` from the Registry interface.### Time-based upkeepsFor time-based upkeeps, do **not** use the listed forwarder address. Instead, use the **Upkeep address** shown in the Chainlink Automation App:![Upkeep address in Chainlink Automation App](/images/automation/cron-upkeep-address.png)The **Upkeep address** is shown in the middle card of the **Details** section for your upkeep.### Custom or log trigger upkeepsFor custom upkeeps or log trigger upkeeps, use the **Forwarder address** listed in the Chainlink Automation App:![Forwarder address in Chainlink Automation App](/images/automation/forwarder-address-ui.png)The **Forwarder address** is shown in the left card of the **Details** section for your upkeep.## Code exampleThe code sample below uses the Forwarder:```sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
 * @dev Example contract which uses the Forwarder
 *
 * @notice important to implement {AutomationCompatibleInterface}
 */

/**
 * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY.
 * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.
 * DO NOT USE THIS CODE IN PRODUCTION.
 */
import {
  AutomationCompatibleInterface
} from "@chainlink/contracts/src/v0.8/automation/interfaces/AutomationCompatibleInterface.sol";
import {OwnerIsCreator} from "@chainlink/contracts/src/v0.8/shared/access/OwnerIsCreator.sol";

contract CounterwForwarder is AutomationCompatibleInterface, OwnerIsCreator {
  uint256 public counter; // counter counts the number of upkeeps performed
  uint256 public interval; // interval specifies the time between upkeeps
  uint256 public lastTimeStamp; // lastTimeStamp tracks the last upkeep performed
  address public s_forwarderAddress;

  constructor(
    uint256 updateInterval
  ) {
    interval = updateInterval;
  }

  function checkUpkeep(
    bytes calldata /*checkData*/
  ) external override returns (bool, bytes memory) {
    bool needsUpkeep = (block.timestamp - lastTimeStamp) > interval;
    return (needsUpkeep, bytes(""));
  }

  function performUpkeep(
    bytes calldata /*performData*/
  ) external override {
    require(msg.sender == s_forwarderAddress, "This address does not have permission to call performUpkeep");
    lastTimeStamp = block.timestamp;
    counter = counter + 1;
  }

  /// @notice Set the address that `performUpkeep` is called from
  /// @dev Only callable by the owner
  /// @param forwarderAddress the address to set
  function setForwarderAddress(
    address forwarderAddress
  ) external onlyOwner {
    s_forwarderAddress = forwarderAddress;
  }
}
```