packages/contracts-core/contracts/libs/Structures.sol
// 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();
}
}
}