Robinhood MainnetChain ID: 4663
Contract detail

FastTrackFactory

FastTrackFactory is a verified Robinhood Chain smart contract at 0x2e2b018e…aa6eb206 with 3 indexed transactions.

Address type
Smart contract
Transactions
3
First indexed block
#26520982
Latest indexed block
#26665521
Emitted events
8
Verification
Verified
Compiler
0.8.34+commit.80d5c536
Verification match
exact
Creation transaction
0x066ad8d9…b20f4a94
Created at block
#26520982
Language
Solidity
License
MIT
Compiler optimization
Disabled
Deployed bytecode hash
0x2e915ce032cefbc63048063954bf8c17ab9a1d36aa6f4d863f1314aeef5b53e5
Related activity

Transactions

Verified contract

Contract source code

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

/*
╔══════════════════════════════════════════════════════════════════════╗
║                                                                      ║
║                         H O O D S C O P E . I O                      ║
║                                                                      ║
║                    FASTTRACK PAYMENT SYSTEM                          ║
║                       ROBINHOOD CHAIN                                ║
║                                                                      ║
║              Stay Alert • Find Alpha • Move Early                    ║
║                                                                      ║
╚══════════════════════════════════════════════════════════════════════╝

Official Website : https://hoodscope.io
Telegram         : https://t.me/HoodScopeHQ
Trends           : https://t.me/HoodScopeTrends
X                : https://x.com/HoodScopeHQ
*/

import "./FastTrackInvoice.sol";

import "./FastTrackInvoice.sol";

/// @notice Creates a unique payment contract for every HoodScope FastTrack order.
contract FastTrackFactory {
    struct Package { uint64 duration; uint192 price; bool enabled; }
    struct Order {
        address invoice;
        address token;
        address payer;
        uint96 amount;
        uint64 duration;
        uint64 createdAt;
        uint64 paidAt;
    }

    address public owner;
    address public pendingOwner;
    address public operator;
    address payable public treasury;
    bool public paused;

    mapping(uint8 => Package) public packages;
    mapping(bytes32 => Order) public orders;
    mapping(address => bytes32) public invoiceOrder;

    event InvoiceCreated(bytes32 indexed orderId, address indexed invoice, address indexed token, uint8 packageId, uint256 amount, uint256 duration);
    event InvoicePaid(bytes32 indexed orderId, address indexed invoice, address indexed payer, uint256 amount, uint256 paidAt);
    event PackageUpdated(uint8 indexed packageId, uint256 duration, uint256 price, bool enabled);
    event OperatorUpdated(address indexed operator);
    event TreasuryUpdated(address indexed treasury);
    event OwnershipTransferStarted(address indexed currentOwner, address indexed pendingOwner);
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    event Paused(bool paused);

    error Unauthorized();
    error InvalidOrder();
    error InvalidPackage();
    error DuplicateOrder();
    error InvalidAddress();

    modifier onlyOwner() { if (msg.sender != owner) revert Unauthorized(); _; }
    modifier onlyOperator() { if (msg.sender != operator) revert Unauthorized(); _; }
    modifier whenActive() { if (paused) revert Unauthorized(); _; }

    constructor(address owner_, address operator_, address payable treasury_) {
        if (owner_ == address(0) || operator_ == address(0) || treasury_ == address(0)) revert InvalidAddress();
        owner = owner_;
        operator = operator_;
        treasury = treasury_;
        _setPackage(1, 3 hours, 0.01 ether, true);
        _setPackage(2, 6 hours, 0.018 ether, true);
        _setPackage(3, 12 hours, 0.032 ether, true);
        _setPackage(4, 24 hours, 0.055 ether, true);
    }

    function createInvoice(bytes32 orderId, address token, uint8 packageId) external onlyOperator whenActive returns (address invoice) {
        if (orderId == bytes32(0) || token == address(0)) revert InvalidOrder();
        if (orders[orderId].invoice != address(0)) revert DuplicateOrder();
        Package memory selected = packages[packageId];
        if (!selected.enabled || selected.price == 0 || selected.duration == 0) revert InvalidPackage();
        bytes32 salt = keccak256(abi.encode(orderId, token, packageId));
        invoice = address(new FastTrackInvoice{salt: salt}(treasury, orderId, selected.price));
        orders[orderId] = Order(invoice, token, address(0), uint96(selected.price), selected.duration, uint64(block.timestamp), 0);
        invoiceOrder[invoice] = orderId;
        emit InvoiceCreated(orderId, invoice, token, packageId, selected.price, selected.duration);
    }

    function markPaid(bytes32 orderId, address payer, uint256 amount) external {
        Order storage order = orders[orderId];
        if (msg.sender != order.invoice || order.paidAt != 0 || amount != order.amount) revert InvalidOrder();
        order.payer = payer;
        order.paidAt = uint64(block.timestamp);
        emit InvoicePaid(orderId, msg.sender, payer, amount, block.timestamp);
    }

    function setPackage(uint8 packageId, uint64 duration, uint192 price, bool enabled) external onlyOwner {
        _setPackage(packageId, duration, price, enabled);
    }

    function _setPackage(uint8 packageId, uint64 duration, uint192 price, bool enabled) internal {
        if (packageId == 0 || duration == 0 || price == 0) revert InvalidPackage();
        packages[packageId] = Package(duration, price, enabled);
        emit PackageUpdated(packageId, duration, price, enabled);
    }

    function setOperator(address next) external onlyOwner {
        if (next == address(0)) revert InvalidAddress();
        operator = next;
        emit OperatorUpdated(next);
    }

    function setTreasury(address payable next) external onlyOwner {
        if (next == address(0)) revert InvalidAddress();
        treasury = next;
        emit TreasuryUpdated(next);
    }

    function setPaused(bool value) external onlyOwner { paused = value; emit Paused(value); }
    function transferOwnership(address next) external onlyOwner {
        if (next == address(0)) revert InvalidAddress();
        pendingOwner = next;
        emit OwnershipTransferStarted(owner, next);
    }
    function acceptOwnership() external {
        if (msg.sender != pendingOwner) revert Unauthorized();
        address previous = owner;
        owner = msg.sender;
        pendingOwner = address(0);
        emit OwnershipTransferred(previous, msg.sender);
    }
}