// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import { AgentNotActive, AgentNotFraudulent, AgentNotUnstaking, AgentNotActiveNorUnstaking, AgentUnknown } from "../libs/Errors.sol"; // Here we define common enums and structures to enable their easier reusing later. // ═══════════════════════════════ AGENT STATUS ════════════════════════════════ /// @dev Potential statuses for the off-chain bonded agent: /// - Unknown: never provided a bond => signature not valid /// - Active: has a bond in BondingManager => signature valid /// - Unstaking: has a bond in BondingManager, initiated the unstaking => signature not valid /// - Resting: used to have a bond in BondingManager, successfully unstaked => signature not valid /// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated => signature not valid /// - Slashed: proven to commit fraud, value in Merkle Tree was updated => signature not valid /// Unstaked agent could later be added back to THE SAME domain by staking a bond again. /// Honest agent: Unknown -> Active -> unstaking -> Resting -> Active ... /// Malicious agent: Unknown -> Active -> Fraudulent -> Slashed /// Malicious agent: Unknown -> Active -> Unstaking -> Fraudulent -> Slashed enum AgentFlag { Unknown, Active, Unstaking, Resting, Fraudulent, Slashed } /// @notice Struct for storing an agent in the BondingManager contract. struct AgentStatus { AgentFlag flag; uint32 domain; uint32 index; } // 184 bits available for tight packing using StructureUtils for AgentStatus global; /// @notice Potential statuses of an agent in terms of being in dispute /// - None: agent is not in dispute /// - Pending: agent is in unresolved dispute /// - Slashed: agent was in dispute that lead to agent being slashed /// Note: agent who won the dispute has their status reset to None enum DisputeFlag { None, Pending, Slashed } /// @notice Struct for storing dispute status of an agent. /// @param flag Dispute flag: None/Pending/Slashed. /// @param openedAt Timestamp when the latest agent dispute was opened (zero if not opened). /// @param resolvedAt Timestamp when the latest agent dispute was resolved (zero if not resolved). struct DisputeStatus { DisputeFlag flag; uint40 openedAt; uint40 resolvedAt; } // ════════════════════════════════ DESTINATION ════════════════════════════════ /// @notice Struct representing the status of Destination contract. /// @param snapRootTime Timestamp when latest snapshot root was accepted /// @param agentRootTime Timestamp when latest agent root was accepted /// @param notaryIndex Index of Notary who signed the latest agent root struct DestinationStatus { uint40 snapRootTime; uint40 agentRootTime; uint32 notaryIndex; } // ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════ /// @notice Potential statuses of the message in Execution Hub. /// - None: there hasn't been a valid attempt to execute the message yet /// - Failed: there was a valid attempt to execute the message, but recipient reverted /// - Success: there was a valid attempt to execute the message, and recipient did not revert /// Note: message can be executed until its status is Success enum MessageStatus { None, Failed, Success } library StructureUtils { /// @notice Checks that Agent is Active function verifyActive(AgentStatus memory status) internal pure { if (status.flag != AgentFlag.Active) { revert AgentNotActive(); } } /// @notice Checks that Agent is Unstaking function verifyUnstaking(AgentStatus memory status) internal pure { if (status.flag != AgentFlag.Unstaking) { revert AgentNotUnstaking(); } } /// @notice Checks that Agent is Active or Unstaking function verifyActiveUnstaking(AgentStatus memory status) internal pure { if (status.flag != AgentFlag.Active && status.flag != AgentFlag.Unstaking) { revert AgentNotActiveNorUnstaking(); } } /// @notice Checks that Agent is Fraudulent function verifyFraudulent(AgentStatus memory status) internal pure { if (status.flag != AgentFlag.Fraudulent) { revert AgentNotFraudulent(); } } /// @notice Checks that Agent is not Unknown function verifyKnown(AgentStatus memory status) internal pure { if (status.flag == AgentFlag.Unknown) { revert AgentUnknown(); } } }