Ten minutes with AVAX. Every command below uses the live, verified registry.
You deploy it, you own it. checkJob() answers "run now?" - a timestamp, a price threshold, anything you code. performJob() does the work. The schedule lives in your code, not in PeekPeak.
An off-chain worker checks every active job on every block - free, no transaction, no cost to you. If checkJob() says yes and your escrow covers the run, it executes. You never configure it and never talk to it.
One immutable on-chain contract. It holds your escrow, pays the executor exact gas plus a flat 0.005 AVAX tip per successful run, and lets you withdraw or pause in one call - any time, no lock-up.
You interact with exactly two of these: your contract, which you write, and the registry, which you fund. The keeper is our problem. And a job can never charge more than its escrow - it auto-stops the moment the balance can't cover one more execution.
0xb012fe01cd851c454bd5c7d20c3e3e3f98b4643d0xb012fe01…98b4643dVerified on Snowtrace ↗ - immutable, non-upgradeable bytecode.
Estimate only - nothing here is saved or sent. The schedule lives in your own contract (step 01); gas limit and price ceiling are chosen when you register (step 02). Values are in the chain's native gas token, and the flat keeper tip is set by the protocol, not per job.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
interface IAutoJob {
function checkJob() external view returns (bool canExec, bytes memory execPayload);
function performJob(bytes calldata execPayload) external;
}
contract MyKeeper is IAutoJob {
address public immutable REGISTRY_ADDRESS;
uint256 public nextRun = block.timestamp + 1 hours;
error NotRegistry();
constructor(address registry) { REGISTRY_ADDRESS = registry; }
function checkJob() external view returns (bool, bytes memory) {
return (block.timestamp >= nextRun, "");
}
function performJob(bytes calldata) external {
if (msg.sender != REGISTRY_ADDRESS) revert NotRegistry();
if (block.timestamp < nextRun) return; // idempotent
nextRun = block.timestamp + 1 hours; // effect first
// ...your maintenance call here...
}
}Three rules: checkJob must be view-only; performJob restricted to the registry; and it flips its own condition before external calls, so a retry can never double-execute. The 1 hours in nextRun is your frequency - change it to run more or less often. PeekPeak has no frequency setting; your contract's condition is the frequency.
Download SKILL.md and drop it into .cursor/rules/, .claude/skills/, or your repo root. Then paste the kickoff prompt below - fill in the three CAPS placeholders - and the agent implements the interface, writes the Foundry tests, and generates the deploy script.
You are integrating with PeekPeak (autonomous execution for Avalanche). Read SKILL.md (.cursor/rules/, .claude/skills/, or the repo root) and follow it top to bottom. - Target contract: 0xYOUR_CONTRACT (Avalanche C-Chain, chainId 43114) - Maintenance to run when due: WHAT_TO_DO (e.g. voter.distribute()) - Schedule / trigger condition: WHEN (e.g. every 1 hour) Ship the IAutoJob adapter, the three required Foundry tests, and the deploy + register script (0.2 AVAX escrow) exactly as the rulefile specifies. Use the registry address from the rulefile's Live registries section. Do not modify the target contract. Show me every command before broadcasting anything.
# 1. deploy your keeper (any Foundry/Hardhat project) forge create src/MyKeeper.sol:MyKeeper \ --constructor-args 0xb012fe01cd851c454bd5c7d20c3e3e3f98b4643d \ --rpc-url https://avalanche-c-chain-rpc.publicnode.com \ --interactive # 2. register it: target, gasLimit=500000, ceiling=100 gwei, 0.2 AVAX escrow cast send 0xb012fe01cd851c454bd5c7d20c3e3e3f98b4643d \ "registerJob(address,uint32,uint64)" 0xYOUR_KEEPER 500000 100 \ --value 0.2ether \ --rpc-url https://avalanche-c-chain-rpc.publicnode.com \ --interactive
gasLimit 500000 and ceiling 100 gwei here are the "Gas / execution" and "Gas price" knobs from the calculator above - together they cap what a single execution can ever charge you. Fund the escrow for as many runs as you want banked - deposits are withdrawable at any time, no lock-up.
# 3. it fires itself when your condition hits. # To test right now (testnets only): warp the condition in a # forked test, or expose a setReady(bool) that is OWNER-GATED - # an open setter lets anyone trip your job and grind the escrow. # Then watch it land on the dashboard. # top up or withdraw any time (jobIds are on the dashboard) cast send 0xb012fe01cd851c454bd5c7d20c3e3e3f98b4643d \ "depositGas(bytes32)" 0xYOUR_JOB_ID \ --value 0.1ether \ --rpc-url https://avalanche-c-chain-rpc.publicnode.com \ --interactive
When your own condition hits, the worker executes it and the escrow pays gas + tip. Top up or withdraw at any time. Retired the job? Pause it (setJobStatus) so the keeper stops checking it, then withdraw the rest.