Skip to content

AutomationExecutor ​

Scheduled task execution with caller restrictions, cooldowns, and execution limits. Enables automated recurring actions for AI agent wallets.

Inheritance: ERC7579ExecutorBase

Source: packages/contracts/src/modules/AutomationExecutor.sol

Storage ​

solidity
struct Task {
    address caller;
    address target;
    uint256 value;
    bytes calldata_;
    uint48 cooldown;
    uint48 maxExecutions;
    uint48 executionCount;
    uint48 lastExecuted;
}

mapping(address account => mapping(bytes32 taskId => Task)) public tasks;

Functions ​

onInstall ​

solidity
function onInstall(bytes calldata data) external

Initialize with task definitions. Called automatically during module installation.

Each task is defined with:

FieldTypeDescription
taskIdbytes32Unique identifier for the task
calleraddressAddress authorized to trigger execution
targetaddressTarget contract to call
valueuint256ETH value to send with the call
calldata_bytesEncoded function call data
cooldownuint48Minimum seconds between executions
maxExecutionsuint48Maximum number of executions (0 = unlimited)

executeTask ​

solidity
function executeTask(bytes32 taskId) external

Execute a registered task. The function performs the following checks before execution:

  1. Task exists: Reverts with TaskNotFound if the task ID is not registered
  2. Caller authorized: Reverts with UnauthorizedCaller if msg.sender does not match task.caller
  3. Cooldown elapsed: Reverts with CooldownNotElapsed if not enough time has passed since the last execution (skipped on first execution when lastExecuted == 0)
  4. Execution limit: Reverts with MaxExecutionsReached if executionCount >= maxExecutions (skipped when maxExecutions == 0)

On successful execution, the stored calldata is executed against the target address via the smart account.

onUninstall ​

solidity
function onUninstall(bytes calldata) external

Remove all tasks for the calling account.

Errors ​

solidity
error UnauthorizedCaller();
error CooldownNotElapsed();
error MaxExecutionsReached();
error TaskNotFound();

Usage Example ​

A typical automation setup for periodic rebalancing:

typescript
import { parseEther, encodeFunctionData } from "viem";

const wallet = await client.createWallet({
  owner: "0x...",
  ownerPrivateKey: "0x...",
  policies: [
    {
      type: "automation",
      tasks: [
        {
          id: "daily-rebalance",
          caller: "0xAutomationBot...",
          target: "0xDex...",
          calldata: encodeFunctionData({
            abi: dexAbi,
            functionName: "rebalance",
            args: [parseEther("1")],
          }),
          cooldown: 86_400, // Once per day
          maxExecutions: 0, // Unlimited
        },
      ],
    },
  ],
});

Design Notes ​

  • The executor module type (MODULE_TYPE_EXECUTOR = 2) allows it to execute transactions on behalf of the account
  • Tasks are immutable after installation -- to modify a task, uninstall and reinstall the module
  • The cooldown check is skipped on the first execution (when lastExecuted == 0) to allow immediate first use
  • When using with Foundry's via_ir=true optimizer, block.timestamp may be cached in loops -- use manual time tracking in tests

Released under the MIT License.