Skip to content

Commit

Permalink
Merge pull request #172 from lidofinance/fix/standalone-libs
Browse files Browse the repository at this point in the history
Audit fix: Move DualGovernanceStateTransitions lib to standalone file
  • Loading branch information
bulbozaur authored Nov 11, 2024
2 parents 476fcfe + 03396ef commit 8cf3bf9
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 112 deletions.
113 changes: 1 addition & 112 deletions contracts/libraries/DualGovernanceStateMachine.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";

import {Duration} from "../types/Duration.sol";
import {PercentD16} from "../types/PercentD16.sol";
import {Timestamp, Timestamps} from "../types/Timestamp.sol";

import {IEscrow} from "../interfaces/IEscrow.sol";
import {IDualGovernance} from "../interfaces/IDualGovernance.sol";
import {IDualGovernanceConfigProvider} from "../interfaces/IDualGovernanceConfigProvider.sol";

import {DualGovernanceConfig} from "./DualGovernanceConfig.sol";
import {DualGovernanceStateTransitions} from "./DualGovernanceStateTransitions.sol";

/// @notice Enum describing the state of the Dual Governance State Machine
/// @param Unset The initial (uninitialized) state of the Dual Governance State Machine. The state machine cannot
Expand Down Expand Up @@ -324,114 +324,3 @@ library DualGovernanceStateMachine {
emit NewSignallingEscrowDeployed(newSignallingEscrow);
}
}

/// @title Dual Governance State Transitions Library
/// @notice Library containing the transitions logic for the Dual Governance system
library DualGovernanceStateTransitions {
using DualGovernanceConfig for DualGovernanceConfig.Context;

/// @notice Returns the allowed state transition for the Dual Governance State Machine.
/// If no state transition is possible, `currentState` will be equal to `nextState`.
/// @param self The context of the Dual Governance State Machine.
/// @param config The configuration of the Dual Governance State Machine to use for determining
/// state transitions.
/// @return currentState The current state of the Dual Governance State Machine.
/// @return nextState The next state of the Dual Governance State Machine if a transition
/// is possible, otherwise it will be the same as `currentState`.
function getStateTransition(
DualGovernanceStateMachine.Context storage self,
DualGovernanceConfig.Context memory config
) internal view returns (State currentState, State nextState) {
currentState = self.state;
if (currentState == State.Normal) {
nextState = _fromNormalState(self, config);
} else if (currentState == State.VetoSignalling) {
nextState = _fromVetoSignallingState(self, config);
} else if (currentState == State.VetoSignallingDeactivation) {
nextState = _fromVetoSignallingDeactivationState(self, config);
} else if (currentState == State.VetoCooldown) {
nextState = _fromVetoCooldownState(self, config);
} else if (currentState == State.RageQuit) {
nextState = _fromRageQuitState(self, config);
} else {
assert(false);
}
}

// ---
// Private Methods
// ---

function _fromNormalState(
DualGovernanceStateMachine.Context storage self,
DualGovernanceConfig.Context memory config
) private view returns (State) {
return config.isFirstSealRageQuitSupportCrossed(self.signallingEscrow.getRageQuitSupport())
? State.VetoSignalling
: State.Normal;
}

function _fromVetoSignallingState(
DualGovernanceStateMachine.Context storage self,
DualGovernanceConfig.Context memory config
) private view returns (State) {
PercentD16 rageQuitSupport = self.signallingEscrow.getRageQuitSupport();

if (!config.isVetoSignallingDurationPassed(self.vetoSignallingActivatedAt, rageQuitSupport)) {
return State.VetoSignalling;
}

if (config.isSecondSealRageQuitSupportCrossed(rageQuitSupport)) {
return State.RageQuit;
}

return config.isVetoSignallingReactivationDurationPassed(
Timestamps.max(self.vetoSignallingReactivationTime, self.vetoSignallingActivatedAt)
) ? State.VetoSignallingDeactivation : State.VetoSignalling;
}

function _fromVetoSignallingDeactivationState(
DualGovernanceStateMachine.Context storage self,
DualGovernanceConfig.Context memory config
) private view returns (State) {
PercentD16 rageQuitSupport = self.signallingEscrow.getRageQuitSupport();

if (!config.isVetoSignallingDurationPassed(self.vetoSignallingActivatedAt, rageQuitSupport)) {
return State.VetoSignalling;
}

if (config.isSecondSealRageQuitSupportCrossed(rageQuitSupport)) {
return State.RageQuit;
}

if (config.isVetoSignallingDeactivationMaxDurationPassed(self.enteredAt)) {
return State.VetoCooldown;
}

return State.VetoSignallingDeactivation;
}

function _fromVetoCooldownState(
DualGovernanceStateMachine.Context storage self,
DualGovernanceConfig.Context memory config
) private view returns (State) {
if (!config.isVetoCooldownDurationPassed(self.enteredAt)) {
return State.VetoCooldown;
}
return config.isFirstSealRageQuitSupportCrossed(self.signallingEscrow.getRageQuitSupport())
? State.VetoSignalling
: State.Normal;
}

function _fromRageQuitState(
DualGovernanceStateMachine.Context storage self,
DualGovernanceConfig.Context memory config
) private view returns (State) {
if (!self.rageQuitEscrow.isRageQuitFinalized()) {
return State.RageQuit;
}
return config.isFirstSealRageQuitSupportCrossed(self.signallingEscrow.getRageQuitSupport())
? State.VetoSignalling
: State.VetoCooldown;
}
}
119 changes: 119 additions & 0 deletions contracts/libraries/DualGovernanceStateTransitions.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import {PercentD16} from "../types/PercentD16.sol";
import {Timestamps} from "../types/Timestamp.sol";

import {DualGovernanceConfig} from "./DualGovernanceConfig.sol";
import {State, DualGovernanceStateMachine} from "./DualGovernanceStateMachine.sol";

/// @title Dual Governance State Transitions Library
/// @notice Library containing the transitions logic for the Dual Governance system
library DualGovernanceStateTransitions {
using DualGovernanceConfig for DualGovernanceConfig.Context;

/// @notice Returns the allowed state transition for the Dual Governance State Machine.
/// If no state transition is possible, `currentState` will be equal to `nextState`.
/// @param self The context of the Dual Governance State Machine.
/// @param config The configuration of the Dual Governance State Machine to use for determining
/// state transitions.
/// @return currentState The current state of the Dual Governance State Machine.
/// @return nextState The next state of the Dual Governance State Machine if a transition
/// is possible, otherwise it will be the same as `currentState`.
function getStateTransition(
DualGovernanceStateMachine.Context storage self,
DualGovernanceConfig.Context memory config
) internal view returns (State currentState, State nextState) {
currentState = self.state;
if (currentState == State.Normal) {
nextState = _fromNormalState(self, config);
} else if (currentState == State.VetoSignalling) {
nextState = _fromVetoSignallingState(self, config);
} else if (currentState == State.VetoSignallingDeactivation) {
nextState = _fromVetoSignallingDeactivationState(self, config);
} else if (currentState == State.VetoCooldown) {
nextState = _fromVetoCooldownState(self, config);
} else if (currentState == State.RageQuit) {
nextState = _fromRageQuitState(self, config);
} else {
assert(false);
}
}

// ---
// Private Methods
// ---

function _fromNormalState(
DualGovernanceStateMachine.Context storage self,
DualGovernanceConfig.Context memory config
) private view returns (State) {
return config.isFirstSealRageQuitSupportCrossed(self.signallingEscrow.getRageQuitSupport())
? State.VetoSignalling
: State.Normal;
}

function _fromVetoSignallingState(
DualGovernanceStateMachine.Context storage self,
DualGovernanceConfig.Context memory config
) private view returns (State) {
PercentD16 rageQuitSupport = self.signallingEscrow.getRageQuitSupport();

if (!config.isVetoSignallingDurationPassed(self.vetoSignallingActivatedAt, rageQuitSupport)) {
return State.VetoSignalling;
}

if (config.isSecondSealRageQuitSupportCrossed(rageQuitSupport)) {
return State.RageQuit;
}

return config.isVetoSignallingReactivationDurationPassed(
Timestamps.max(self.vetoSignallingReactivationTime, self.vetoSignallingActivatedAt)
) ? State.VetoSignallingDeactivation : State.VetoSignalling;
}

function _fromVetoSignallingDeactivationState(
DualGovernanceStateMachine.Context storage self,
DualGovernanceConfig.Context memory config
) private view returns (State) {
PercentD16 rageQuitSupport = self.signallingEscrow.getRageQuitSupport();

if (!config.isVetoSignallingDurationPassed(self.vetoSignallingActivatedAt, rageQuitSupport)) {
return State.VetoSignalling;
}

if (config.isSecondSealRageQuitSupportCrossed(rageQuitSupport)) {
return State.RageQuit;
}

if (config.isVetoSignallingDeactivationMaxDurationPassed(self.enteredAt)) {
return State.VetoCooldown;
}

return State.VetoSignallingDeactivation;
}

function _fromVetoCooldownState(
DualGovernanceStateMachine.Context storage self,
DualGovernanceConfig.Context memory config
) private view returns (State) {
if (!config.isVetoCooldownDurationPassed(self.enteredAt)) {
return State.VetoCooldown;
}
return config.isFirstSealRageQuitSupportCrossed(self.signallingEscrow.getRageQuitSupport())
? State.VetoSignalling
: State.Normal;
}

function _fromRageQuitState(
DualGovernanceStateMachine.Context storage self,
DualGovernanceConfig.Context memory config
) private view returns (State) {
if (!self.rageQuitEscrow.isRageQuitFinalized()) {
return State.RageQuit;
}
return config.isFirstSealRageQuitSupportCrossed(self.signallingEscrow.getRageQuitSupport())
? State.VetoSignalling
: State.VetoCooldown;
}
}

0 comments on commit 8cf3bf9

Please sign in to comment.