ResourceBasedTimelockedCall

Description:

Smart contract deployed on Ethereum with Factory features.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.19;

// src/core/BaseReentrancy.sol

abstract contract BaseReentrancy {
    // ----------------------------------------------------------------------------------------------------
    // Constants
    // ----------------------------------------------------------------------------------------------------
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    // ----------------------------------------------------------------------------------------------------
    // Errors
    // ----------------------------------------------------------------------------------------------------
    error ReentrantCall();

    // ----------------------------------------------------------------------------------------------------
    // Storage layout
    // ----------------------------------------------------------------------------------------------------
    uint256 private _status;

    // ----------------------------------------------------------------------------------------------------
    // Modifiers
    // ----------------------------------------------------------------------------------------------------
    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == _ENTERED) {
            revert ReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

// src/core/interfaces/IOperableResource.sol

interface IOperableResource {
    function owner() external view returns (address);
    function operatorAddress() external view returns (address);
}

// src/core/interfaces/IResourceBasedTimelockedCall.sol

interface IResourceBasedTimelockedCall {
    error Unauthorized();
    error HashRequired();
    error HashAlreadyEnqueued();
    error HashNotEnqueued();
    error TimelockInPlace();
    error InvalidTimelockDuration();
    error InvalidResourceAddress();

    struct TimelockedCallInfo {
        uint256 targetEpoch;     // The unix epoch at which the hash can be consumed
        address createdBy;       // The address of the scheduler
    }

    /// @notice Triggers when a hash is scheduled for further execution
    event HashScheduled(bytes32 h, address postedBy);

    /// @notice Triggers when a hash is consumed by the address specified.
    event HashConsumed(bytes32 h, address consumerAddress);

    /// @notice Triggers when a hash is cancelled.
    event HashCancelled(bytes32 h, address consumerAddress);

    function schedule(bytes32 h) external;
    function cancel(bytes32 h) external;
    function consume(bytes32 h) external;
    function hashExists(bytes32 h) external view returns (bool);
    function getInfo(bytes32 h) external view returns (TimelockedCallInfo memory);
}

// src/core/ResourceBasedTimelockedCall.sol

/**
 * @title Allows a resource to schedule and consume time-locked hashes.
 */
contract ResourceBasedTimelockedCall is IResourceBasedTimelockedCall, BaseReentrancy {
    /// @dev A reasonable time-window for manipulating the block timestamp as a miner.
    uint256 constant internal _TIMESTAMP_MANIPULATION_WINDOW = 5 minutes;

    /// @notice The address of the operable smart contract.
    IOperableResource public immutable RESOURCE;

    /// @notice The time-lock duration of the consumer.
    uint256 public immutable TIMELOCK_DURATION;

    /// @notice The time-lock info of a given hash.
    mapping (bytes32 => TimelockedCallInfo) public queue;

    /// @dev Throws if the sender is not the expected resource address.
    modifier onlyResource() {
        if (msg.sender != address(RESOURCE)) revert Unauthorized();
        _;
    }

    constructor(
        address newResource,
        uint256 newTimeLockDuration
    ) {
        if (newTimeLockDuration < _TIMESTAMP_MANIPULATION_WINDOW) revert InvalidTimelockDuration();

        RESOURCE = IOperableResource(newResource);
        TIMELOCK_DURATION = newTimeLockDuration;
    }

    /**
     * @notice Schedules a hash for further execution.
     * @dev Throws if the sender is not the expected resource, nor the owner/operator of such resource.
     * @param h Specifies the hash to schedule.
     */
    function schedule(bytes32 h) external override nonReentrant {
        if (h == bytes32(0)) revert HashRequired();
        if (queue[h].createdBy != address(0)) revert HashAlreadyEnqueued();

        queue[h] = TimelockedCallInfo({
            createdBy: msg.sender,
            targetEpoch: block.timestamp + TIMELOCK_DURATION
        });

        emit HashScheduled(h, msg.sender);

        // Validate the message sender
        _enforceValidSender();
    }

    /**
     * @notice Cancels an existing hash.
     * @param h Specifies the hash to cancel.
     */
    function cancel(bytes32 h) external nonReentrant {
        if (queue[h].createdBy == address(0)) revert HashNotEnqueued();

        delete queue[h];
        emit HashCancelled(h, msg.sender);

        // Validate the message sender
        _enforceValidSender();
    }

    /**
     * @notice Consumes the hash specified.
     * @dev Throws if the sender is not the expected resource.
     * @param h Specifies the hash to consume.
     */
    function consume(bytes32 h) external override nonReentrant onlyResource {
        if (queue[h].targetEpoch < 1) revert HashNotEnqueued();
        if (block.timestamp < queue[h].targetEpoch) revert TimelockInPlace();

        delete queue[h];
        emit HashConsumed(h, msg.sender);
    }

    /**
     * @notice Indicates if the hash specified was enqueued.
     * @param h Specifies the hash to evaluate.
     * @return bool Returns true if the hash specified was enqueued.
     */
    function hashExists(bytes32 h) external override view returns (bool) {
        return queue[h].targetEpoch > 0;
    }

    /**
     * @notice Gets the details of the hash specified.
     * @param h Specifies the hash to evaluate.
     * @return TimelockedCallInfo Returns a struct containing the details.
     */
    function getInfo(bytes32 h) external override view returns (TimelockedCallInfo memory) {
        return queue[h];
    }

    /// @dev Throws if the sender is not the expected resource, nor the owner/operator of such resource.
    function _enforceValidSender() private view {
        address theOwner = RESOURCE.owner();
        address theOperator = RESOURCE.operatorAddress();

        if (
            (msg.sender != address(RESOURCE)) && 
            (msg.sender != theOwner) && 
            (msg.sender != theOperator)
        ) revert Unauthorized();
    }
}

Tags:
Factory|addr:0xaa26771820b3f35cc28cb1f9136e52a5ed825d12|verified:true|block:23448079|tx:0xa8169adc1c77dff8d32c63180f0344cd74a7fcc68c993ddab6a54aa5a9a2544f|first_check:1758901819

Submitted on: 2025-09-26 17:50:22

Comments

Log in to comment.

No comments yet.