Skip to main content
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {ISchedulerHelper} from "./interfaces.sol/ISchedulerHelper.sol";

/// @title AutoCounter
/// @notice Contract that automatically increases a counter value at regular intervals.
contract AutoCounter {
    uint256 public counter = 0;
    ISchedulerHelper public schedulerHelper;

    /// @notice Emitted when a counter increase schedule is created.
    /// @param  scheduleId  uint256  Unique identifier for the scheduled automation.
    event CounterIncreaseScheduled(uint256 indexed scheduleId);

    /// @notice Increase `counter` by the specified amount.
    /// @param  increaseBy  uint256  Amount to increase `counter` by.
    function increaseCounter(uint256 increaseBy) external {
        counter += increaseBy;
    }

    constructor(address _schedulerHelper) {
        schedulerHelper = ISchedulerHelper(_schedulerHelper);
    }

    /// @notice Schedule `increaseCounter` calls via SchedulerHelper.
    /// @param  maxFeePerGas          uint256  Max total fee per unit of gas (EIP-1559).
    /// @param  maxPriorityFeePerGas  uint256  Optional tip for inclusion (EIP-1559).
    /// @param  value                 uint256  Value attached to each call (not needed in this example).
    function scheduleCounterIncrease(
        uint256 maxFeePerGas,
        uint256 maxPriorityFeePerGas,
        uint256 value
    ) external payable {
        // Call `increaseCounter` with `100` for the `increaseBy` param.
        uint256 counterIncreaseAmount = 100;

        // Gas limit for each scheduled `increaseCounter` call.
        uint32 gasLimit = 50_000;

        // Scheduled call submission frequency.
        uint32 frequency = 900;

        // When using the `SchedulerHelper` contract, you only have to specify the number of calls that you want to schedule,
        // it calculates the `maxBlockNumber` for you.
        uint32 numCalls = 10;

        // Max block drift (e.g. if in 900 blocks (frequency) your scheduled call is not included in a finalized block,
        // there is a 100 block window where it can wait in the Scheduled Transactions mempool before being dropped).
        uint32 ttl = 100;

        // SchedulerHelper handles RitualWallet deposit for you.
        uint256 scheduleId = schedulerHelper.schedule{value: msg.value}(
            ISchedulerHelper.Call({
                target: address(this),
                // casting to 'uint96' is safe because uint96 is a subset of uint256
                // forge-lint: disable-next-line(unsafe-typecast)
                msgValue: uint96(value),
                callData: abi.encodeWithSelector(
                    this.increaseCounter.selector,
                    counterIncreaseAmount
                )
            }),
            frequency,
            numCalls,
            gasLimit,
            ttl,
            maxFeePerGas,
            maxPriorityFeePerGas
        );

        emit CounterIncreaseScheduled(scheduleId);
    }
}