// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; /** * @title AERE Security Contract * @dev Manages security monitoring and threat detection with enhanced security */ contract AereSecurity is Ownable, ReentrancyGuard, Pausable { enum ThreatLevel { Low, Medium, High, Critical } enum AlertStatus { Active, Resolved, Investigating } struct SecurityAlert { uint256 id; string alertType; ThreatLevel severity; string message; address reporter; uint256 timestamp; AlertStatus status; string resolution; } struct SecurityMetrics { uint256 totalAlerts; uint256 resolvedAlerts; uint256 criticalAlerts; uint256 lastScanTime; bool systemHealthy; } // State variables mapping(uint256 => SecurityAlert) public alerts; mapping(address => bool) public authorizedReporters; mapping(address => uint256) public reputationScores; mapping(address => uint256) public reportCounts; mapping(address => uint256) public lastReportTime; uint256 public alertCount = 0; SecurityMetrics public securityMetrics; // Security parameters uint256 public constant RATE_LIMIT_WINDOW = 1 hours; uint256 public constant MAX_REPORTS_PER_WINDOW = 10; uint256 public constant MIN_REPUTATION_TO_REPORT = 50; // Events event SecurityAlertCreated(uint256 indexed alertId, ThreatLevel severity, string alertType, address indexed reporter); event AlertResolved(uint256 indexed alertId, string resolution, address indexed resolver); event ThreatDetected(address indexed source, string threatType, ThreatLevel severity, address indexed detector); event ReputationUpdated(address indexed entity, uint256 oldScore, uint256 newScore); event ReporterAuthorized(address indexed reporter, address indexed authorizer); event ReporterRevoked(address indexed reporter, address indexed revoker); modifier onlyAuthorizedReporter() { require(authorizedReporters[msg.sender], "AereSecurity: Not authorized to report"); require(reputationScores[msg.sender] >= MIN_REPUTATION_TO_REPORT, "AereSecurity: Insufficient reputation"); _; } modifier rateLimited() { require( reportCounts[msg.sender] < MAX_REPORTS_PER_WINDOW || block.timestamp > lastReportTime[msg.sender] + RATE_LIMIT_WINDOW, "AereSecurity: Rate limit exceeded" ); if (block.timestamp > lastReportTime[msg.sender] + RATE_LIMIT_WINDOW) { reportCounts[msg.sender] = 0; } reportCounts[msg.sender]++; lastReportTime[msg.sender] = block.timestamp; _; } constructor() { securityMetrics = SecurityMetrics({ totalAlerts: 0, resolvedAlerts: 0, criticalAlerts: 0, lastScanTime: block.timestamp, systemHealthy: true }); // Owner is authorized reporter by default with high reputation authorizedReporters[msg.sender] = true; reputationScores[msg.sender] = 100; emit ReporterAuthorized(msg.sender, msg.sender); emit ReputationUpdated(msg.sender, 0, 100); } /** * @dev Add authorized security reporter with reputation check */ function addAuthorizedReporter(address reporter) external onlyOwner { require(reporter != address(0), "AereSecurity: Invalid reporter address"); require(!authorizedReporters[reporter], "AereSecurity: Reporter already authorized"); authorizedReporters[reporter] = true; if (reputationScores[reporter] == 0) { reputationScores[reporter] = MIN_REPUTATION_TO_REPORT; } emit ReporterAuthorized(reporter, msg.sender); } /** * @dev Remove authorized security reporter */ function removeAuthorizedReporter(address reporter) external onlyOwner { require(reporter != msg.sender, "AereSecurity: Cannot remove self"); authorizedReporters[reporter] = false; emit ReporterRevoked(reporter, msg.sender); } /** * @dev Report security alert with enhanced validation */ function reportSecurityAlert( string memory alertType, ThreatLevel severity, string memory message ) external onlyAuthorizedReporter rateLimited whenNotPaused nonReentrant returns (uint256) { require(bytes(alertType).length > 0 && bytes(alertType).length <= 100, "AereSecurity: Invalid alert type"); require(bytes(message).length > 0 && bytes(message).length <= 1000, "AereSecurity: Invalid message"); alertCount++; uint256 alertId = alertCount; alerts[alertId] = SecurityAlert({ id: alertId, alertType: alertType, severity: severity, message: message, reporter: msg.sender, timestamp: block.timestamp, status: AlertStatus.Active, resolution: "" }); securityMetrics.totalAlerts++; if (severity == ThreatLevel.Critical) { securityMetrics.criticalAlerts++; securityMetrics.systemHealthy = false; } // Update reporter reputation (positive for reporting) _updateReputationSafe(msg.sender, reputationScores[msg.sender] + 1); emit SecurityAlertCreated(alertId, severity, alertType, msg.sender); return alertId; } /** * @dev Resolve security alert with enhanced validation */ function resolveAlert(uint256 alertId, string memory resolution) external onlyOwner nonReentrant { require(alertId > 0 && alertId <= alertCount, "AereSecurity: Alert does not exist"); require(alerts[alertId].status != AlertStatus.Resolved, "AereSecurity: Alert already resolved"); require(bytes(resolution).length > 0 && bytes(resolution).length <= 1000, "AereSecurity: Invalid resolution"); alerts[alertId].status = AlertStatus.Resolved; alerts[alertId].resolution = resolution; securityMetrics.resolvedAlerts++; // Update system health if all critical alerts resolved if (alerts[alertId].severity == ThreatLevel.Critical) { securityMetrics.criticalAlerts = securityMetrics.criticalAlerts > 0 ? securityMetrics.criticalAlerts - 1 : 0; if (securityMetrics.criticalAlerts == 0) { securityMetrics.systemHealthy = true; } } emit AlertResolved(alertId, resolution, msg.sender); } /** * @dev Detect and report threat with enhanced validation */ function detectThreat( address source, string memory threatType, ThreatLevel severity ) external onlyAuthorizedReporter rateLimited whenNotPaused nonReentrant { require(source != address(0), "AereSecurity: Invalid source address"); require(bytes(threatType).length > 0 && bytes(threatType).length <= 100, "AereSecurity: Invalid threat type"); // Update reputation score for the source (negative impact) if (reputationScores[source] > uint256(severity) + 1) { _updateReputationSafe(source, reputationScores[source] - (uint256(severity) + 1)); } else { _updateReputationSafe(source, 0); } // Create alert string memory message = string(abi.encodePacked("Threat detected from ", _addressToString(source))); this.reportSecurityAlert(threatType, severity, message); emit ThreatDetected(source, threatType, severity, msg.sender); } /** * @dev Update reputation score with bounds checking */ function updateReputation(address entity, uint256 score) external onlyOwner { require(entity != address(0), "AereSecurity: Invalid entity address"); require(score <= 100, "AereSecurity: Score too high"); uint256 oldScore = reputationScores[entity]; _updateReputationSafe(entity, score); emit ReputationUpdated(entity, oldScore, score); } /** * @dev Internal safe reputation update */ function _updateReputationSafe(address entity, uint256 score) internal { uint256 oldScore = reputationScores[entity]; reputationScores[entity] = score > 100 ? 100 : score; if (oldScore != reputationScores[entity]) { emit ReputationUpdated(entity, oldScore, reputationScores[entity]); } } /** * @dev Perform security scan (only owner, rate limited) */ function performSecurityScan() external onlyOwner { require(block.timestamp >= securityMetrics.lastScanTime + 1 hours, "AereSecurity: Scan rate limited"); securityMetrics.lastScanTime = block.timestamp; securityMetrics.systemHealthy = (securityMetrics.criticalAlerts == 0); } /** * @dev Emergency pause function */ function emergencyPause() external onlyOwner { _pause(); } /** * @dev Unpause function */ function unpause() external onlyOwner { _unpause(); } /** * @dev Get alert details with existence check */ function getAlert(uint256 alertId) external view returns (SecurityAlert memory) { require(alertId > 0 && alertId <= alertCount, "AereSecurity: Alert does not exist"); return alerts[alertId]; } /** * @dev Get security metrics */ function getSecurityMetrics() external view returns (SecurityMetrics memory) { return securityMetrics; } /** * @dev Get reputation score */ function getReputationScore(address entity) external view returns (uint256) { return reputationScores[entity]; } /** * @dev Check if system is healthy */ function isSystemHealthy() external view returns (bool) { return securityMetrics.systemHealthy && securityMetrics.criticalAlerts == 0 && !paused(); } /** * @dev Get active alerts count by severity */ function getActiveAlertsBySeverity(ThreatLevel severity) external view returns (uint256) { uint256 count = 0; for (uint256 i = 1; i <= alertCount; i++) { if (alerts[i].severity == severity && alerts[i].status == AlertStatus.Active) { count++; } } return count; } /** * @dev Check if address is authorized reporter */ function isAuthorizedReporter(address reporter) external view returns (bool) { return authorizedReporters[reporter] && reputationScores[reporter] >= MIN_REPUTATION_TO_REPORT; } /** * @dev Get reporter statistics */ function getReporterStats(address reporter) external view returns ( bool authorized, uint256 reputation, uint256 reportsInWindow, uint256 lastReport ) { return ( authorizedReporters[reporter], reputationScores[reporter], reportCounts[reporter], lastReportTime[reporter] ); } /** * @dev Convert address to string */ function _addressToString(address account) internal pure returns (string memory) { bytes32 value = bytes32(uint256(uint160(account))); bytes memory alphabet = "0123456789abcdef"; bytes memory str = new bytes(42); str[0] = '0'; str[1] = 'x'; for (uint256 i = 0; i < 20; i++) { str[2+i*2] = alphabet[uint8(value[i + 12] >> 4)]; str[3+i*2] = alphabet[uint8(value[i + 12] & 0x0f)]; } return string(str); } }