Templates
Start from a working task
Each template fills in the trigger, the call and a sensible gas limit. You only point it at your contract.
Liquidation keeperChecks positions every block and liquidates the first one under water.
conditionUse template
LiquidationResolver.sol
interface IMarket {
function positionCount() external view returns (uint256);
function isLiquidatable(uint256 id) external view returns (bool);
function liquidate(uint256 id) external;
}
contract LiquidationResolver {
IMarket public immutable market;
constructor(IMarket m) { market = m; }
// Gnomon calls this every block. Return (true, call) when a run is due.
function checker() external view returns (bool, bytes memory) {
uint256 n = market.positionCount();
for (uint256 i; i < n && i < 200; ++i) {
if (market.isLiquidatable(i)) {
return (true, abi.encodeCall(IMarket.liquidate, (i)));
}
}
return (false, "");
}
}Limit order on Uniswap v4Fills an order when the pool price crosses your limit.
conditionUse template
LimitResolver.sol
interface IOrders {
function nextFillable() external view returns (bool, uint256 orderId);
function fill(uint256 orderId) external;
}
contract LimitResolver {
IOrders public immutable orders;
constructor(IOrders o) { orders = o; }
function checker() external view returns (bool, bytes memory) {
(bool ok, uint256 id) = orders.nextFillable(); // your price check lives here
if (!ok) return (false, "");
return (true, abi.encodeCall(IOrders.fill, (id)));
}
}Daily vesting releaseReleases vested tokens to the beneficiary once a day.
every 24 hoursUse template
Call
// OpenZeppelin VestingWallet.release(token) is open to anyone,
// so no allow-list is needed for this one.
target: your VestingWallet
call: release(address token)
every: 24 hoursTWAP updatePushes a fresh TWAP every five minutes so readers never see stale data.
every 5 minutesUse template
Oracle.sol
contract Oracle {
address public constant GNOMON_SENDER = 0x0000000000000000000000000000000000000000; // yours
function update() external {
require(msg.sender == GNOMON_SENDER, "not keeper");
// read the pool, write the new observation
}
}Reward distributionDistributes the day’s rewards to stakers at the same hour every day.
every 24 hoursUse template
Call
target: your RewardsDistributor
call: distribute()
every: 24 hours
start at: 00:00 UTCPause on liquidity pullPauses your pool the moment a large LP removal is emitted.
eventUse template
Guard.sol
contract PoolGuard {
address public constant GNOMON_SENDER = 0x0000000000000000000000000000000000000000; // yours
bool public paused;
function pause() external {
require(msg.sender == GNOMON_SENDER, "not keeper");
paused = true;
}
}