7Block Labs
Blockchain Security

ByAUJay

Chainlink Oracle Security Best Practices for Automation: Upkeep Permissions and Griefing Risks

Concise Summary

Check out this 2025 field guide on toughening up Chainlink Automation (v2.1). It covers concrete strategies for permissioning, gas controls, and anti-griefing techniques. You’ll learn how to gate perform calls, set up registrar approvals, adjust gas thresholds, and implement monitoring practices to keep attackers at bay and protect your LINK from being drained or triggering unwanted actions.


Why this matters now

Chainlink Automation is super important for things like liquidation bots and cross-chain rebalancers. As of August 29, 2024, only v2.1 registries are in play--so if you’ve got older upkeeps, they’re not running anymore. This means your security setup needs to align with v2.1’s forwarder model, the new admin flows, and those offchain configuration features.

If you’ve made the leap to migrate or if you’re setting up some brand new upkeeps, check out this security checklist to help you dodge griefing and permission bugs that could throw you off and lead to lost funds or unexpected executions. You can find all the details here: (docs.chain.link).


TL;DR for decision‑makers

  • Make sure you’re using Automation v2.1. Lock your perform function to the specific Forwarder or Upkeep address, and handle admin tasks with two-step transfers. Check out the details here.
  • To avoid any gas-related headaches, set a cap on your on-chain gas price using the offchainConfig’s “gas price threshold.” It’s also smart to keep a 3-5x LINK buffer to dodge any potential DoS attacks during gas spikes. More info can be found here.
  • When it comes to log-triggered workflows, be sure to filter heavily and keep service limits in mind. Don’t forget to establish manual fallback triggers and validate your performData on-chain. You can find more guidance here.

1) Upkeep permissions you must get right

1.1 The “Forwarder” is your runtime gate

  • Each v2.1 upkeep comes with its own unique Forwarder contract that calls your target contract during the perform stage. Make sure your contract recognizes this Forwarder as the only valid caller and reverts if anything else tries to make a call. You can grab the address from the Automation app or by using registry.getForwarder(upkeepID), and then be sure to store or allowlist it in your contract. (docs.chain.link)
  • Here’s a key detail: when it comes to time-based upkeeps, you need to give permission based on the Upkeep address (which you can find in the app) rather than the Forwarder. (docs.chain.link)

Example Gating Pattern:

pragma solidity ^0.8.20;

interface IRegistry {
  function getForwarder(uint256 upkeepID) external view returns (address);
}

contract SecuredAutomation {
  address public forwarder; // set after registration/migration
  address public owner;

  error OnlyForwarder();
  error OnlyOwner();

  constructor() { owner = msg.sender; }

  function setForwarder(address _fwd) external {
    if (msg.sender != owner) revert OnlyOwner();
    forwarder = _fwd;
  }

  modifier onlyForwarder() {
    if (msg.sender != forwarder) revert OnlyForwarder();
    _;
  }

  // performUpkeep entry
  function performUpkeep(bytes calldata performData) external onlyForwarder {
    // always re-validate local state against performData before effects
    _execute(performData);
  }

  function _execute(bytes calldata data) internal {
    // secure logic...
  }
}

This helps avoid the issue where "anyone can call performUpkeep," which could lead to griefing or random state changes. You can check out more about it here.

1.2 Upkeep admin: pause, cancel, withdraw, and transfer correctly

On the v2.1 registry, the upkeep admin has a few handy capabilities:

  • They can easily pause or unpause an upkeep, which means they can stop checks and performances when it’s paused.
  • If needed, they can cancel an upkeep and withdraw LINK after a block delay that’s specific to the network.
  • There's also the option to update parameters, such as gas limit, checkData, offchainConfig, and they can toss in some extra funds too.
  • Transferring admin rights is a two-step process: first, use transferUpkeepAdmin(id, proposed), and then the new admin has to run acceptUpkeepAdmin(id).

You can find these flows on v2.1 interfaces and explorers. Just a heads-up, make sure to use a multisig instead of a single EOA to handle them. Check it out here: (sepolia.etherscan.io).

Practical Guidance

  • When you're registering, go ahead and use a production multisig for the adminAddress.
  • Make sure to document your runbook so you can easily pause specific upkeeps if something goes wrong (like if you spot an exploit vector).
  • It's a smart move to keep the admin key separate from your deployer keys.

1.3 Registrar auto‑approval and allowlists

The v2.1 Registrar comes with some cool auto-approval options, like creating an allowlist of senders. However, when you’re working in production, it’s a good idea to stick with manual approval or just allowlist trusted factories. This way, you can keep rogue registrations from draining your LINK. Make sure to review and configure AutoApproveType along with the allowed senders in your deployment pipeline. Check out the details here.

1.4 Migrations change the authorized caller

When you make the jump to v2.1 (or any later registries), a new Forwarder gets assigned. It's crucial to update the allowed caller in your target contract; if you don’t, Automation will cease to function. Be sure to add this update to your migration checklist. (docs.chain.link)


2) Griefing risks and how to neutralize them

Griefing is when someone messes with your automation to waste gas, hit the wrong timing, or get it stuck by fiddling with triggers, gas, or call paths. Here are some solid defenses to keep in mind.

2.1 Direct-call griefing: unsecured performUpkeep

Risk

If performUpkeep can be called by anyone without checking for a Forwarder, then any external owner account (EOA) or bot can trigger it with whatever performData they want.

Mitigation

To handle this, make sure msg.sender is the Forwarder (or the Upkeep address if it’s cron-related). Also, in performUpkeep, it's essential to always double-check the conditions against the current on-chain state--don’t ever take performData at face value. You can find more details in the Chainlink docs.

Key Patterns:

  • Idempotency: This is all about making sure that the same piece of work doesn’t get done more than once. If the target state is already achieved, we just short-circuit and move on. Check out more on this in the Chainlink Automation docs.
  • Bounded work: Here, we want to keep the processing load manageable by setting a cap. This way, we can divide the tasks into multiple upkeeps (think of it like range partitions) which helps us keep gas costs predictable. For more details, head over to the Chainlink Automation docs.

2.2 Log‑spam griefing on log‑trigger upkeeps

Risk

Attackers can send out matching logs to push offchain checks or overwhelm your upkeep by exceeding the per-block processing limits, especially on noisy chains. Just a heads up, automation nodes can only handle a limited number of logs per block for each upkeep--like 20 on Ethereum and even fewer on some Layer 2s.

Mitigations

Here are a few strategies to help you dodge these risks:

  • Tight Filtering: Use specific topics and known sender addresses in your ILogAutomation implementation to keep things under control.
  • Manual Conditional Upkeep: Set up a manual backup for those logs that didn't get processed.
  • Source and Payload Validation: Always check each log’s origin and data on-chain before making any state changes. You can find more details in the Chainlink documentation.

Risk

If your upkeep runs when gas prices are high, you might end up paying way too much in fees or even face delays if you don’t have enough funds.

Mitigations:

  • Set a maximum gas price with the offchainConfig’s “gas price threshold” (it’s CBOR-encoded) using setUpkeepOffchainConfig. Just a heads up: nodes can still increase gas prices if a transaction is already in progress, so it’s wise to add a little buffer to your threshold. And if you're all about that ultra-low latency, maybe skip this option. (docs.chain.link)
  • Get a grip on how billing works: LINK spent = (gasUsed + overhead) × gasPrice × (1 + premium) ÷ LINK/native rate. This way, you can size those buffers just right! (docs.chain.link)
  • Keep a balance of 3-5 times the minimum LINK required for each upkeep to handle any sudden gas price spikes without a hitch. (docs.chain.link)

Just to give you a bit more insight, Chainlink nodes pick and adjust gas prices using estimators and percentiles based on recent blocks. This is yet another reason why it's not a great idea to run too close to the minimum. You can check out the details here.

2.4 “Flickering” eligibility

Risk: When checkUpkeep quickly switches between true and false, you might run into some issues with consensus and mempool delays, leading to missed or duplicated attempts. To avoid this, it's smart to keep eligibility consistent until the work gets done and re-validated in performUpkeep. (docs.chain.link)

2.5 Underfunding as a denial‑of‑service vector

Risk

Attackers might try to mess with your most costly code paths during peak gas times, draining your LINK and stopping execution dead in its tracks.

Mitigations:

  • Be proactive! Keep your balance topped up and set up a dedicated station contract that keeps an eye on minimum balances across your upkeeps, refueling whenever you're running low. Check it out here.
  • Don’t forget, you need ERC‑677 LINK on the mainnet. If you need to convert, use PegSwap to swap ERC‑20 LINK when necessary. More details can be found here.

2.6 Streams and allowlisting

When you're working with Data Streams and Automation (StreamsLookup), make sure your upkeep is on the allowlist for the feeds you're querying. If you overlook the allowlists, it could lead to issues like non-execution and even unnecessary DoS investigations. To avoid these headaches, double-check the allowlist status during your rollout. You can find more info here.

2.7 Minimum spend retention

Automation has a tiny minimum lifetime spend requirement (like 0.1 LINK) to help keep the spam at bay. If your upkeep hasn’t reached that spend level, this amount will stick around when you cancel. So, make sure to factor this into your cost model to dodge any unexpected “dust.” Check out more details here: (blog.chain.link)


3) Concrete configuration moves (do these)

3.1 Register upkeeps with secure defaults

When you're getting ready to register--whether you're doing it through the UI or programmatically--make sure to keep these things in mind:

  • adminAddress: This should be a multisig that your ops team manages.
  • gasLimit: Take some time to test this on the testnet and make sure you’ve added some extra room. If it’s set too low, you could run into issues during simulations. On the flip side, if the limit is too high, you might find that it raises the minimum balance requirements. For more details, check out the documentation.
  • offchainConfig: Here, you want to set {"maxGasPrice": ...} (don’t forget to CBOR-encode this) for upkeeps that aren’t super time-sensitive. You can apply this setting using setUpkeepOffchainConfig. For more info, take a look at the documentation.

CBOR Encoding Reference (Conceptual Example)

Here's a simple breakdown of CBOR encoding with an example based on the official documentation.

What’s CBOR?

CBOR (Concise Binary Object Representation) is a binary data serialization format. It's great for efficiently storing and transmitting data, especially when dealing with scenarios where size matters.

Basic structure

CBOR encodes data types like integers, strings, arrays, and maps. Each data type has a specific representation, which helps keep everything compact.

Example

Let’s take a look at a basic example, encoding a small dataset:

{
  "name": "Alice",
  "age": 30,
  "hobbies": ["reading", "hiking", "coding"]
}

Here's how it would be represented in CBOR:

0xA3                # map of 3 items
  0x67             # "name" (string with 7 characters)
  0x41 0x6C 0x69 0x63 0x65 0x      # "Alice" (string)
  0x63             # "age" (string with 3 characters)
  0x1E             # integer 30
  0x66             # "hobbies" (string with 6 characters)
  0x83             # array of 3 items
    0x67         # "reading" (string with 7 characters)
    0x67         # "hiking" (string with 6 characters)
    0x66         # "coding" (string with 6 characters)

Key Points to Remember

  • Compactness: CBOR is designed to reduce the size of data.
  • Efficiency: It’s perfect for resource-constrained environments.
  • Easy to Use: Encoding and decoding can be done with various libraries.

If you want to dive deeper, check out the official CBOR documentation.

// Encode {"maxGasPrice": 2 gwei}
(bytes memory payload, ) = CBOREncoder.encode(2_000_000_000, 64);
// registry.setUpkeepOffchainConfig(upkeepId, payload);

Make sure to stick to the encoding rules laid out in the gas-threshold guide. This helps you dodge any silent misconfigurations. Check it out here: (docs.chain.link)

3.2 Lock down performUpkeep

  • Make sure msg.sender matches forwarder (or the Upkeep address for cron jobs).
  • Double-check the conditions right at the beginning of performUpkeep and bail out early if it’s not eligible anymore.
  • Ensure the function is idempotent; this way, the same work subset won’t be executed more than once. (docs.chain.link)

3.3 Partition heavy workloads

When you're dealing with large loops or a bunch of accounts, it's a good idea to create multiple upkeeps by splitting them into index ranges using checkData. This approach helps limit the gas used for each transaction and minimizes the risk if something goes wrong during execution. You can find more info on this here.

3.4 Configure registrar policies

If your team runs a registrar or uses programmatic registration flows, here are a couple of important tips:

  • It’s best to keep auto-approval turned off in production. If you do need to enable it, make sure to allowlist only the senders you’ve explicitly approved.
  • Keep an eye on those RegistrationRequested and RegistrationApproved events. You can check them out here: (sepolia.etherscan.io).

3.5 Monitor and alert like SREs

  • Check out the Automation debugging script to help you figure out any paused, underfunded, or gas-limit-failing upkeeps. Then, plug those results into your alerting stack. (docs.chain.link)
  • Keep an eye on your minimum balance versus your buffer (aim for 3-5×), track any failed simulations, and watch out for those gas-price threshold hits. (docs.chain.link)

4) Practical examples you can lift today

A secured liquidation bot (conditional upkeep)

  • We've got a forwarder-gated performUpkeep in place.
  • The checkUpkeep function takes care of computing the minimum undercollateralized accounts off-chain and sends an encoded subset in performData.
  • Then, perform double-checks on-chain to make sure those accounts are still good to liquidate and that the local TWAPs haven't drifted.

Benefits include bounded gas, idempotent execution, and the absence of public entry points that could be exploited by griefers for spam. You can dive deeper into this here.

Log‑triggered rebalancer with fallback

  • Primary: We kick things off with log-triggered upkeep that gets activated by a vault RebalanceQueued event. We make sure to have strict filtering for both topics and emitters.
  • Fallback: Just in case, we've set up a low-frequency conditional upkeep that checks on the same condition every N minutes. This helps us catch any logs we might have missed because of block-log caps. Check out the details in the documentation!

Example C -- Gas‑aware arbitrage protector

  • Set a maximum gas price limit, like 3 gwei on a specific L2, to steer clear of burning LINK when blocks get congested.
  • Be okay with accepting some delays; just steer clear of using thresholds for trades that need to happen right away.
  • Set up alerts for when the threshold blocks execution for more than X minutes. (docs.chain.link)

Example D -- Automated refueling of upkeeps

  • Set up an “Automation Station” that keeps an eye on all your upkeep balances and automatically boosts them when they get close to your set thresholds. This way, you're batching operations and dodging those gas spike DoS issues across your upkeep fleet. Check it out here: (docs.chain.link)

5) Emerging best practices we’re seeing in 2025

  • Treat Forwarder addresses like rotating “service accounts.” Whenever you’re doing a migration, make sure to update all permissions. It’s a good idea to automate this in your deployment tools. (docs.chain.link)
  • Don’t forget to encode and set gas thresholds for each network and upkeep type. Keep an eye on the difference between what you’ve realized and what you’ve configured for gas, and tweak this every quarter. (docs.chain.link)
  • Take the initiative to break down large upkeeps into smaller, more manageable scopes. Use checkData range sharding to help with predictable fees and quicker incident isolation. (docs.chain.link)
  • Make sure to incorporate pause/cancel/withdraw runbooks into your incident response. Get some practice in on testnets using the registry’s admin functions so that you’re ready to go when it counts. (sepolia.etherscan.io)

6) Operations: what to watch daily/weekly/monthly

  • Daily

    • Keep an eye on underfunded upkeeps, failed simulations, any paused states, and those pesky threshold blocks (gas prices too high). You can find more info here.
  • Weekly

    • Check out your gas spend versus your budget, premium percentages, and LINK/native FX; make sure to adjust those minimum balances as needed. More details are available here.
  • Monthly/Quarterly

    • Don’t forget to re-test those “flicker” scenarios in staging to ensure everything runs smoothly.
    • Take some time to review the registrar auto-approval settings and allowlists; if the policy says so, rotate those admin keys too. You can dive deeper into this here.

7) Quick secure‑by‑default checklist

  • We're using Automation v2.1 now, and all upkeeps have been smoothly migrated. Check out the details here.
  • The performUpkeep is gated to the Forwarder (or the Upkeep address for cron jobs). You can find more info here.
  • Our admin setup is a multisig; we’ve practiced the pause, cancel, and withdraw runbooks. For transparency, here’s our address on Etherscan: link.
  • We’ve set a gas price threshold where latency isn’t a big deal, and we’ve got alerts monitoring those threshold blocks. More on this here.
  • There's a LINK balance buffer of 3-5 times the minimum required, plus we’ve set up automatic refueling to keep things running smoothly. Learn more about managing upkeeps here.
  • We filter log triggers by topics and emitters; there's a manual fallback for conditional upkeep. Details can be found here.
  • We always re-validate performData on-chain, ensuring that our work is idempotent and bounded. More about this process here.
  • Lastly, our streams upkeeps are allowlisted for the necessary feeds. You can read up on it here.

Final note on costs and reliability

When it comes to automation, offchain simulation and gas bidding can sometimes lead to wasted attempts on-chain. But remember, you’ll still need to cover the costs when things go smoothly, and managing gas price fluctuations is key. To keep things running efficiently and affordably, get a good grasp of the billing formula, know the gas limits set by the registry, and establish policies for thresholds. Keeping these factors in check will help strike a balance between reliability and cost. And don’t forget to keep your Forwarder gates nice and secure. Check out more details in this blog post.


Need help implementing this?

7Block Labs: Streamlining Automation for Teams Across L1s/L2s

At 7Block Labs, we’ve got your back when it comes to automating processes for your teams across various L1s and L2s. Here’s how we can help:

  • We’ll take a close look at your contracts.
  • We encode offchainConfig thresholds to keep everything running smoothly.
  • We set up registrar policies tailored to your needs.
  • We create incident runbooks and alerts to ensure you’re always in the loop.

And of course, before we make the jump to production, we’ll thoroughly battle-test everything on testnets to make sure it’s all systems go!


Get a free security quick-scan of your smart contracts

Submit your contracts and our engineer will review them for vulnerabilities, gas issues and architecture risks.

Related Posts

Blockchain Security

ByAUJay

Building 'Bio-Authenticated' Infrastructure for Secure Apps When it comes to keeping our applications safe, using bio-authentication is a game changer. This method relies on unique biological traits, like fingerprints or facial recognition, which adds a whole new layer of security. By integrating bio-authentication into our infrastructure, we can ensure that only the right people have access to sensitive information. So, what exactly does bio-authentication look like in action? Think about it: instead of juggling passwords or worrying about someone guessing your security questions, you’re simply using your own unique features to log in. It’s not only convenient but also super secure. The road to creating this bio-authenticated infrastructure isn’t just about implementing tech; it's also about making sure it’s user-friendly. We want people to feel comfortable and confident using these systems. With advancements in technology, the future is looking bright for secure applications. By focusing on bio-authentication, we’re paving the way for safer digital experiences.

Hey everyone, exciting news! Bio-authenticated infrastructure is finally making its debut! Back in January 2026, WebAuthn Level 3 reached the W3C Candidate Recommendation stage, and NIST has put the finishing touches on SP 800-63-4. And with passkeys coming into the mix, we can look forward to smoother logins and a big drop in support calls. Just a heads up--don’t forget to roll those out!

Blockchain Security

ByAUJay

Protecting High-Value Transactions from Front-Running

Front-running protection for high-value on-chain transactions is a must-have for enterprise treasuries these days. Our strategy brings together private order flow, encrypted mempools, batch auctions, and Solidity hardening to completely seal off any potential leak paths while keeping everything secure.

Blockchain Security

ByAUJay

Making Sure Your Upgradable Proxy Pattern is Free of Storage Issues

Quick rundown: When it comes to upgradeable proxies, storage collisions can cause all sorts of sneaky headaches--think data corruption, dodging access controls, and throwing audits into chaos. This playbook is your essential buddy for identifying these tricky issues, steering clear of them, and safely migrating with tools like EIP-1967, UUPS, and ERC-721.

7BlockLabs

Full-stack blockchain product studio: DeFi, dApps, audits, integrations.

7Block Labs is a trading name of JAYANTH TECHNOLOGIES LIMITED.

Registered in England and Wales (Company No. 16589283).

Registered Office address: Office 13536, 182-184 High Street North, East Ham, London, E6 2JA.

© 2026 7BlockLabs. All rights reserved.