BlackBoxComs

Description:

Smart contract deployed on Ethereum with Factory features.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "blackboxcoms/BlackBoxComs.sol": {
      "content": "// SPDX-License-Identifier: GPL-3.0-or-later\r
// BlackBoxComs - Production v1.0\r
// admin@blackboxmint.com\r
\r
pragma solidity ^0.8.26;\r
\r
/**\r
 * @title BlackBoxComs\r
 * @notice Decentralized messaging system with anti-spam fees and user blocking\r
 * @dev Production-ready contract with reentrancy protection and gas optimizations\r
 */\r
contract BlackBoxComs {\r
    // Custom errors for gas efficiency\r
    error InsufficientFee();\r
    error InvalidRecipient();\r
    error CannotMessageSelf();\r
    error SenderBlocked();\r
    error InvalidMessageLength();\r
    error InboxFull();\r
    error NotYourMessage();\r
    error AlreadyRead();\r
    error InvalidUser();\r
    error NotOwner();\r
    error ReentrantCall();\r
    error NoFunds();\r
    error TransferFailed();\r
    error FeeTooHigh();\r
    error NotAuthorized();\r
    error MessageNotFound();\r
    error RateLimited();\r
    struct Message {\r
        address sender;\r
        address recipient;\r
        string content;\r
        uint32 timestamp;\r
        bool isRead;\r
    }\r
\r
    mapping(address => uint256[]) private userMessages;\r
    mapping(uint256 => Message) private messages;\r
    mapping(address => mapping(address => bool)) public blockedUsers;\r
    mapping(address => uint256) public messageCount;\r
    mapping(address => uint256) public lastMessageTime;\r
    \r
    uint256 public nextMessageId = 1;\r
    uint256 public messageFee = 0.0001 ether; // Reduced spam prevention fee\r
    address public owner;\r
    uint8 private _status = 1;\r
    uint256 public constant MAX_MESSAGES_PER_USER = 1000;\r
    uint256 public constant MAX_MESSAGE_LENGTH = 500;\r
    uint256 public constant MESSAGE_COOLDOWN = 30 seconds;\r
\r
    event MessageSent(uint256 indexed messageId, address indexed sender, address indexed recipient, uint32 timestamp);\r
    event MessageRead(uint256 indexed messageId, address indexed reader);\r
    event UserBlocked(address indexed blocker, address indexed blocked);\r
    event UserUnblocked(address indexed blocker, address indexed unblocked);\r
    event FeeChanged(uint256 oldFee, uint256 newFee);\r
    event MessageDeleted(uint256 indexed messageId, address indexed deleter);\r
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\r
\r
    modifier onlyOwner() { if (msg.sender != owner) revert NotOwner(); _; }\r
    modifier nonReentrant() { if (_status != 1) revert ReentrantCall(); _status = 2; _; _status = 1; }\r
\r
    /**\r
     * @notice Initialize contract with deployer as owner\r
     */\r
    constructor() {\r
        owner = msg.sender;\r
    }\r
\r
    /**\r
     * @notice Send a message to another user with anti-spam fee\r
     * @param _recipient Address to send message to\r
     * @param _content Message content (max 500 chars)\r
     */\r
    function sendMessage(address _recipient, string calldata _content) external payable nonReentrant {\r
        if (block.timestamp < lastMessageTime[msg.sender] + MESSAGE_COOLDOWN) revert RateLimited();\r
        if (msg.value < messageFee) revert InsufficientFee();\r
        if (_recipient == address(0)) revert InvalidRecipient();\r
        if (_recipient == msg.sender) revert CannotMessageSelf();\r
        if (blockedUsers[_recipient][msg.sender]) revert SenderBlocked();\r
        uint256 contentLength = bytes(_content).length;\r
        if (contentLength == 0 || contentLength > MAX_MESSAGE_LENGTH) revert InvalidMessageLength();\r
        if (messageCount[_recipient] >= MAX_MESSAGES_PER_USER) revert InboxFull();\r
\r
        uint256 messageId = ++nextMessageId;\r
        messages[messageId] = Message({\r
            sender: msg.sender,\r
            recipient: _recipient,\r
            content: _content,\r
            timestamp: uint32(block.timestamp),\r
            isRead: false\r
        });\r
\r
        userMessages[_recipient].push(messageId);\r
        messageCount[_recipient]++;\r
        lastMessageTime[msg.sender] = block.timestamp;\r
        emit MessageSent(messageId, msg.sender, _recipient, uint32(block.timestamp));\r
    }\r
\r
    /**\r
     * @notice Mark a received message as read\r
     * @param _messageId ID of the message to mark as read\r
     */\r
    function markAsRead(uint256 _messageId) external {\r
        Message storage message = messages[_messageId];\r
        if (message.recipient != msg.sender) revert NotYourMessage();\r
        if (message.isRead) revert AlreadyRead();\r
        message.isRead = true;\r
        emit MessageRead(_messageId, msg.sender);\r
    }\r
\r
    /**\r
     * @notice Block a user from sending messages to you\r
     * @param _user Address to block\r
     */\r
    function blockUser(address _user) external {\r
        if (_user == address(0) || _user == msg.sender) revert InvalidUser();\r
        blockedUsers[msg.sender][_user] = true;\r
        emit UserBlocked(msg.sender, _user);\r
    }\r
\r
    /**\r
     * @notice Unblock a previously blocked user\r
     * @param _user Address to unblock\r
     */\r
    function unblockUser(address _user) external {\r
        if (_user == address(0)) revert InvalidUser();\r
        blockedUsers[msg.sender][_user] = false;\r
        emit UserUnblocked(msg.sender, _user);\r
    }\r
\r
    function getMyMessages(uint256 _offset, uint256 _limit) external view returns (uint256[] memory messageIds, uint256 total) {\r
        uint256[] storage allMessages = userMessages[msg.sender];\r
        total = allMessages.length;\r
        \r
        if (_offset >= total) {\r
            return (new uint256[](0), total);\r
        }\r
        \r
        uint256 end = _offset + _limit;\r
        if (end > total) {\r
            end = total;\r
        }\r
        \r
        uint256 length = end - _offset;\r
        messageIds = new uint256[](length);\r
        \r
        for (uint256 i = 0; i < length; i++) {\r
            messageIds[i] = allMessages[_offset + i];\r
        }\r
    }\r
\r
    function getMessage(uint256 _messageId) external view returns (Message memory) {\r
        Message storage message = messages[_messageId];\r
        if (message.sender == address(0)) revert MessageNotFound();\r
        if (message.sender != msg.sender && message.recipient != msg.sender) {\r
            revert NotAuthorized();\r
        }\r
        return message;\r
    }\r
    \r
    /**\r
     * @notice Delete a received message (storage cleanup)\r
     * @param _messageId ID of the message to delete\r
     */\r
    function deleteMessage(uint256 _messageId) external nonReentrant {\r
        Message storage message = messages[_messageId];\r
        if (message.sender == address(0)) revert MessageNotFound();\r
        if (message.recipient != msg.sender) revert NotYourMessage();\r
        \r
        delete messages[_messageId];\r
        messageCount[msg.sender]--;\r
        emit MessageDeleted(_messageId, msg.sender);\r
    }\r
    \r
    function getMessageCount(address _user) external view returns (uint256) {\r
        return messageCount[_user];\r
    }\r
    \r
    function isBlocked(address _blocker, address _user) external view returns (bool) {\r
        return blockedUsers[_blocker][_user];\r
    }\r
\r
    /**\r
     * @notice Update the message fee (owner only)\r
     * @param _fee New fee amount (max 0.01 ETH)\r
     */\r
    function setMessageFee(uint256 _fee) external onlyOwner {\r
        if (_fee > 0.01 ether) revert FeeTooHigh();\r
        uint256 oldFee = messageFee;\r
        messageFee = _fee;\r
        emit FeeChanged(oldFee, _fee);\r
    }\r
    \r
    function transferOwnership(address _newOwner) external onlyOwner {\r
        if (_newOwner == address(0)) revert InvalidUser();\r
        emit OwnershipTransferred(owner, _newOwner);\r
        owner = _newOwner;\r
    }\r
\r
    /**\r
     * @notice Withdraw accumulated fees (owner only)\r
     */\r
    function withdraw() external onlyOwner nonReentrant {\r
        uint256 balance = address(this).balance;\r
        if (balance == 0) revert NoFunds();\r
        (bool success, ) = payable(owner).call{value: balance}("");\r
        if (!success) revert TransferFailed();\r
    }\r
    \r
    function emergencyWithdraw() external onlyOwner nonReentrant {\r
        uint256 balance = address(this).balance;\r
        if (balance > 0) {\r
            (bool success, ) = payable(owner).call{value: balance}("");\r
            if (!success) revert TransferFailed();\r
        }\r
    }\r
    \r
    // View functions for frontend integration\r
    function getContractInfo() external view returns (\r
        uint256 totalMessages,\r
        uint256 currentFee,\r
        address contractOwner\r
    ) {\r
        return (nextMessageId - 1, messageFee, owner);\r
    }\r
}"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": false,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "remappings": []
  }
}}

Tags:
Factory|addr:0x6231d12a960a6b940345088fa2efd3eeb9d758a5|verified:true|block:23692774|tx:0xd7069cb66036e46f3420cb9b2b61bbe3b3336757e26d7a9b578faad1fd1082b2|first_check:1761903860

Submitted on: 2025-10-31 10:44:20

Comments

Log in to comment.

No comments yet.