Docs/Contract Reference

Contract Reference

Complete Solidity interface reference for all AutoLoop contracts.


Core Contracts

AutoLoop.sol

The main protocol orchestrator. Manages controller registration, loop execution, and fee distribution.

// Execute a standard loop
function performUpdate(address _autoLoopCompatibleContract) external;

// Execute a VRF loop with proof
function performVRFUpdate(
    address _autoLoopCompatibleContract,
    uint256[4] calldata proof,
    uint256[2] calldata uPoint,
    uint256[4] calldata vComponents
) external;

// Controller management
function registerController(address _controller) external;
function removeController(address _controller) external;
function isController(address _address) external view returns (bool);

// Protocol admin
function setBaseFee(uint256 _fee) external;
function setProtocolFeePortion(uint256 _portion) external;
function setMaxGas(uint256 _gas) external;
function withdrawFees(address payable _to) external;

AutoLoopRegistrar.sol

Entry point for registering new contracts. Validates ERC-165 interface support.

// Register a contract and optionally deposit ETH
function registerAutoLoop(address _contract) external payable;

// Check if a contract implements a supported interface
function isCompatible(address _contract) external view returns (bool);

AutoLoopRegistry.sol

State management for registered contracts, balances, and configuration.

// Registration status
function isRegistered(address _contract) external view returns (bool);
function getRegisteredContracts() external view returns (address[] memory);

// Balance management
function getBalance(address _contract) external view returns (uint256);
function deposit(address _contract) external payable;
function requestRefund(address _contract, address _to) external;

// Configuration
function getMaxGas(address _contract) external view returns (uint256);
function setMaxGas(address _contract, uint256 _gas) external;

VRFVerifier.sol

Gas-efficient on-chain ECVRF proof verification using the secp256k1 curve.

// Verify an ECVRF proof and derive random output
function verify(
    uint256[2] calldata publicKey,  // [pkX, pkY]
    uint256[4] calldata proof,
    uint256[2] calldata uPoint,
    uint256[4] calldata vComponents,
    bytes calldata message
) external pure returns (bool valid, uint256 output);

Base Contracts (For Developers)

AutoLoopCompatible

Inherit for standard automation with no randomness.

import "@luckymachines/autoloop/src/AutoLoopCompatible.sol";

contract MyGame is AutoLoopCompatible {
    // Return true when the contract is ready for the next tick
    function shouldProgressLoop() external view override returns (bool) {
        return block.timestamp >= lastTick + INTERVAL;
    }

    // Execute game logic — only callable by AutoLoop
    function progressLoop() external override onlyAutoLoop {
        lastTick = block.timestamp;
        // your logic here
    }
}

Interface ID: Default (no ERC-165 required) Gas per tick: ~90,000

AutoLoopHybridVRFCompatible

Inherit for selective VRF — cheap standard ticks with randomness only when requested.

import "@luckymachines/autoloop/src/AutoLoopHybridVRFCompatible.sol";

contract MyGame is AutoLoopHybridVRFCompatible {
    function shouldProgressLoop() external view override returns (bool) {
        return block.timestamp >= lastTick + INTERVAL;
    }

    // Called on standard ticks (no VRF)
    function _onTick() internal override {
        turnCount++;
        // Set needsVRF for the NEXT tick
        if (turnCount % 10 == 0) {
            needsVRF = true;
        }
    }

    // Called on VRF ticks (when needsVRF was true)
    function _onVRFTick(uint256[] calldata randomWords) internal override {
        needsVRF = false;
        uint256 lootRoll = randomWords[0] % 100;
        // use randomness
    }
}

Interface ID: Detected via ERC-165 Gas per standard tick: ~90,000 Gas per VRF tick: ~240,000

Key concept: Set needsVRF = true to request randomness on the next tick. Workers read this flag before executing and will generate an ECVRF proof only when it's true.

AutoLoopVRFCompatible

Inherit for full VRF — verifiable randomness on every tick.

import "@luckymachines/autoloop/src/AutoLoopVRFCompatible.sol";

contract DiceGame is AutoLoopVRFCompatible {
    function shouldProgressLoop() external view override returns (bool) {
        return block.timestamp >= lastTick + INTERVAL;
    }

    function progressLoop(uint256[] calldata randomWords) external override onlyAutoLoop {
        lastTick = block.timestamp;
        uint256 roll = randomWords[0] % 6 + 1;
        // use roll
    }
}

Interface ID: Detected via ERC-165 Gas per tick: ~240,000

VRF Key Registration

For VRF and Hybrid VRF contracts, each controller must register its secp256k1 public key:

// Called by the contract owner or admin
function registerControllerKey(
    address controller,
    uint256 pkX,
    uint256 pkY
) external;

The pkX and pkY are the x and y coordinates of the controller's public key on the secp256k1 curve. Derive them from the private key:

const { secp256k1 } = require("@noble/curves/secp256k1");
const publicKey = secp256k1.getPublicKey(privateKeyHex, false);
const pkX = "0x" + Buffer.from(publicKey.slice(1, 33)).toString("hex");
const pkY = "0x" + Buffer.from(publicKey.slice(33, 65)).toString("hex");

Access Control

AutoLoop uses OpenZeppelin's AccessControl for role-based permissions:

RoleWho Has ItWhat It Does
DEFAULT_ADMIN_ROLEProtocol deployerCan grant/revoke all roles
CONTROLLER_ROLERegistered workersCan call performUpdate / performVRFUpdate

The onlyAutoLoop modifier on base contracts ensures only the AutoLoop contract can call progressLoop() — not arbitrary addresses.

Events

AutoLoop Events

event LoopExecuted(address indexed contract, address indexed controller, uint256 gasCost, uint256 fee);
event ControllerRegistered(address indexed controller);
event ControllerRemoved(address indexed controller);
event FeesWithdrawn(address indexed to, uint256 amount);

Registry Events

event ContractRegistered(address indexed contract, address indexed owner);
event Deposited(address indexed contract, uint256 amount);
event RefundRequested(address indexed contract, address indexed to, uint256 amount);

Constants

ConstantValueDescription
BASE_FEE70%Percentage of gas cost charged as protocol fee
PROTOCOL_FEE_PORTION50%Protocol's share of the base fee
CONTROLLER_FEE_PORTION50%Controller's share of the base fee
MAX_GAS1,000,000Default maximum gas per execution
GAS_BUFFER94,293Overhead gas for protocol operations
CONTROLLER_REGISTRATION_FEE0.001 ETHCost to register as a controller

Source Code

All contracts are open-source: