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": []
}
}}
Submitted on: 2025-10-31 10:44:20
Comments
Log in to comment.
No comments yet.