Skip to content
Chain 4441 · LiteForge TestnetHead#0
LitVM·Scan
Hard Money Web3 Explorer
Verified Contract
0x71769F1Eb5eFDA83d6D12eec2fa59399B4e9ba0f
Pin to watchlist
scan to copy
zkLTC Balance
0
hard money native
Transactions
3,701
Token transfers
0
Validations
0
blocks produced
Hard Money Score
100
/100
PURE HARD MONEY
share of activity in native zkLTC vs. tokens
native
3,701
tokens
0
Contract name
LitClinicMoodCheck
Compiler
v0.8.26+commit.8a97fa7a
Optimization
enabled · 200 runs
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

import "./LitClinicFeeRouter.sol";

/// @notice Clinical Modules V2 - mood check (3 txs per wallet per UTC day, any mood).
contract LitClinicMoodCheck is Ownable, Pausable, ReentrancyGuard {
    uint256 private constant DAILY_MOOD_LIMIT = 3;

    LitClinicFeeRouter public feeRouter;
    uint256 public moodFee;

    uint256 public totalMoodTx;
    uint256 public happyTxCount;
    uint256 public sadTxCount;
    uint256 public angryTxCount;
    uint256 public surprisedTxCount;
    mapping(address => uint256) public userMoodTxCount;
    mapping(address => mapping(uint256 => uint256)) public dailyMoodTxCount;

    bytes32 private constant SOURCE_TYPE = bytes32(bytes("CLINICAL_ACTION"));
    bytes32 private constant SOURCE_ID = bytes32(bytes("mood:check"));

    event MoodChecked(
        address indexed user,
        uint256 indexed day,
        uint8 indexed mood,
        uint256 dailyMoodTxCount,
        uint256 totalMoodTx
    );
    event FeeRouterUpdated(address indexed feeRouter);
    event MoodFeeUpdated(uint256 feeWei);

    error ZeroAddress();
    error IncorrectPayment();
    error InvalidMood();
    error DailyLimitReached();

    constructor(address initialOwner, address feeRouter_, uint256 moodFee_) Ownable(initialOwner) {
        if (feeRouter_ == address(0)) revert ZeroAddress();
        feeRouter = LitClinicFeeRouter(payable(feeRouter_));
        moodFee = moodFee_;
    }

    function currentDay() external view returns (uint256) {
        return block.timestamp / 1 days;
    }

    function dailyCountOf(address user, uint256 day) external view returns (uint256) {
        return dailyMoodTxCount[user][day];
    }

    function pause() external onlyOwner {
        _pause();
    }

    function unpause() external onlyOwner {
        _unpause();
    }

    function setFeeRouter(address feeRouter_) external onlyOwner {
        if (feeRouter_ == address(0)) revert ZeroAddress();
        feeRouter = LitClinicFeeRouter(payable(feeRouter_));
        emit FeeRouterUpdated(feeRouter_);
    }

    function setMoodFee(uint256 feeWei) external onlyOwner {
        moodFee = feeWei;
        emit MoodFeeUpdated(feeWei);
    }

    function checkMood(uint8 mood) external payable nonReentrant whenNotPaused {
        if (mood == 0 || mood > 4) revert InvalidMood();
        if (msg.value != moodFee) revert IncorrectPayment();
        uint256 day = block.timestamp / 1 days;
        if (dailyMoodTxCount[msg.sender][day] >= DAILY_MOOD_LIMIT) revert DailyLimitReached();

        feeRouter.routeFee{value: msg.value}(SOURCE_TYPE, SOURCE_ID);

        totalMoodTx += 1;
        userMoodTxCount[msg.sender] += 1;
        dailyMoodTxCount[msg.sender][day] += 1;

        if (mood == 1) happyTxCount += 1;
        else if (mood == 2) sadTxCount += 1;
        else if (mood == 3) angryTxCount += 1;
        else surprisedTxCount += 1;

        emit MoodChecked(msg.sender, day, mood, dailyMoodTxCount[msg.sender][day], totalMoodTx);
    }
}