Skip to main content

Automation Layer — Core Functions

This page documents what builders call on the Automation Layer and what they must implement in their own contracts to get automated execution.

Quick model

  • You choose a non-zero unique id per unit of work in your contract.
  • You register that id with createAccount(id) (fee in the active fee tokenUSDC today).
  • You implement two hooks in your contract:
    • checkSimpleAutomation(id) → bool (view): return true only when it’s safe to run.
    • simpleAutomation(id): your action logic (runs when check == true).
  • You can cancel later with cancelAccount(id).

Interfaces you implement (in your contract)

interface Automate {
function simpleAutomation(uint256 id) external;
function checkSimpleAutomation(uint256 id) external view returns (bool);
}

Rules

  • id must be > 0 and unique per calling contract.
  • The same id is echoed back to your contract on both calls, so you don’t need the Automation Layer’s internal accountNumber.

Functions you call on the Automation Layer

1) createAccount

Purpose
Register a new automated account for your (contract, id) pair.

Signature

function createAccount(uint256 id) external;

Behavior & Fees

  • Transfers the account creation fee (in the active fee token) from your contract to the protocol owner.
  • Assigns an internal accountNumber (you don’t need it for your logic).
  • Emits AccountCreated(address customer).

Requirements

  • Your contract must hold the fee token and must have approved the Automation Layer as spender.
  • id must be non-zero and unique for your contract.

Snippet (your contract)

AutomationLayer(automationLayerAddress).createAccount(myId);

2) cancelAccount

Purpose
Stop future automation for (address, id).

Signature

function cancelAccount(uint256 id) external;

Behavior

  • Marks the account as canceled.
  • Refunds the stored accountCreationFee (in fee token) from the owner back to your contract.
  • Emits AccountCancelled(uint256 accountNumber, address account).

Requirements

  • Must be called by the same contract that created the account (msg.sender check).

Snippet

AutomationLayer(automationLayerAddress).cancelAccount(myId);

3) getAccountsByAddress

Purpose
List all internal accountNumbers associated with an address (useful for indexing/debugging).

Signature

function getAccountsByAddress(address accountAddress)
external
view
returns (uint256[] memory);

Example (ethers v6)

const accounts = await automation.getAccountsByAddress(myContractAddress);
console.log(accounts);

4) checkSimpleAutomation (Automation Layer view)

Purpose
For a given accountNumber, returns whether that account is eligible to run right now. Nodes call this; you can, too, for diagnostics.

Signature

function checkSimpleAutomation(uint256 accountNumber)
external
view
returns (bool);

5) isAccountCanceled

Purpose
Query if an account is canceled.

Signature

function isAccountCanceled(uint256 accountNumber)
external
view
returns (bool);

6) getCancelledAccounts

Purpose
Return all canceled accountNumbers.

Signature

function getCancelledAccounts() external view returns (uint256[] memory);

What nodes call on your contract

You implement these; nodes will call them:

checkSimpleAutomation

Keep it cheap, deterministic, and return true only when your action will succeed.

function checkSimpleAutomation(uint256 id) external view returns (bool) {
// Example:
// return block.timestamp >= nextDue[id] && balance[id] >= threshold[id];
return _isReady(id);
}

simpleAutomation

Your action. Must succeed when checkSimpleAutomation(id) returns true.

function simpleAutomation(uint256 id) external {
// Do work: transfer/mint/settle/etc.
_doWork(id);
}

Tip: Make the action idempotent or guard it so repeated calls within the same window can’t cause harm.


Active fee token (today: USDC) & approvals

The Automation Layer uses a fee token address stored on-chain (named duh in the contract). Treat duh() as “feeToken()”.
To be future-proof (in case the protocol changes the fee token later), read the token from the Automation Layer and approve that token.

Minimal interface

interface IERC20 {
function approve(address spender, uint256 amount) external returns (bool);
}
interface AutomationLayer {
function duh() external view returns (address); // current fee token (USDC today)
}

Generic approvals (recommended)

contract MyAutomatedContract {
address public automationLayerAddress;

/// Approve any ERC-20 as the fee token (future-proof).
function approveAutomationFeesFor(address token, uint256 amount) external {
require(IERC20(token).approve(automationLayerAddress, amount), "approve failed");
}

/// Approve the CURRENT fee token used by the Automation Layer (USDC today).
function approveCurrentFeeToken(uint256 amount) external {
address feeToken = AutomationLayer(automationLayerAddress).duh();
require(IERC20(feeToken).approve(automationLayerAddress, amount), "approve failed");
}
}

Ethers example (read fee token & approve Max):

const feeToken = await automation.duh(); // USDC today
const erc20 = new ethers.Contract(feeToken, ['function approve(address,uint256) returns (bool)'], signer);
await erc20.approve(automationAddress, ethers.MaxUint256);

Node prechecks: If allowance/balance is insufficient, nodes won’t call your action.


Practical skeleton (Solidity)

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

interface IERC20 {
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address src, address dst, uint256 amount) external returns (bool);
}
interface IAutomationLayer {
function createAccount(uint256 id) external;
function cancelAccount(uint256 id) external;
function duh() external view returns (address); // fee token (USDC today)
}

contract MyAutomated {
address public automationLayerAddress; // set on deploy/init
uint256 public nextId = 1; // ensure non-zero, unique IDs

mapping(uint256 => uint256) public nextDue;
uint256 public interval = 30 days;

/* ---- Approvals ---- */
function approveCurrentFeeToken(uint256 amount) external {
address feeToken = IAutomationLayer(automationLayerAddress).duh();
require(IERC20(feeToken).approve(automationLayerAddress, amount), "approve failed");
}

/* ---- Register / Cancel ---- */
function register() external {
uint256 id = nextId++;
nextDue[id] = block.timestamp + interval;
IAutomationLayer(automationLayerAddress).createAccount(id);
}

function cancel(uint256 id) external {
IAutomationLayer(automationLayerAddress).cancelAccount(id);
}

/* ---- Automation Hooks ---- */
function checkSimpleAutomation(uint256 id) external view returns (bool) {
return block.timestamp >= nextDue[id];
}

function simpleAutomation(uint256 id) external {
// …perform work…
nextDue[id] = block.timestamp + interval;
}
}

Events (emitted by the Automation Layer)

event AccountCreated(address indexed customer);
event AccountCancelled(uint256 indexed index, address indexed account);
event TransactionSuccess(uint256 indexed index);

Notes

  • AccountCreated does not include your id or the internal accountNumber. If you need the accountNumber off-chain, read getAccountsByAddress(yourContractAddress) and compare before/after.
  • TransactionSuccess(index) indicates an automation ran for that accountNumber.

Networks (Automation Layer + USDC)

The fee token is USDC on all supported networks today.

NetworkAutomationLayer AddressUSDC (fee token)
Polygon0x5fc876A1e9BB3f6c76990C4248b23F1B64E3c8dB0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174
Optimism0x1Bb81875e6133a4791a8FaB68aF6e455de9E1B040x0b2C639c533813f4Aa9D7837CAf62653d097Ff85
Base0x1Bb81875e6133a4791a8FaB68aF6e455de9E1B040x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
Arbitrum0x1Bb81875e6133a4791a8FaB68aF6e455de9E1B040xaf88d065e77c8cC2239327C5EDb3A432268e5831

Builders do not interact with the sequencer; it’s managed by the protocol.


Troubleshooting

  • “Fee transfer failed.” Ensure your contract holds enough fee token and has granted sufficient allowance to the Automation Layer.
  • Action not triggering. Verify checkSimpleAutomation(id) returns true and your action won’t revert.
  • Nothing happens after register. Confirm approvals, balances, and addresses match the Networks table.