Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audit fix: Missing Code Documentation #161

Merged
merged 4 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions contracts/Executor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,17 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

import {IExternalExecutor} from "./interfaces/IExternalExecutor.sol";

/// @title Executor
/// @notice Allows the contract owner to execute external function calls on specified target contracts with
/// possible value transfers.
contract Executor is IExternalExecutor, Ownable {
constructor(address owner) Ownable(owner) {}

/// @notice Allows the contract owner to execute external function calls on target contracts, optionally transferring ether.
/// @param target The address of the target contract on which to execute the function call.
/// @param value The amount of ether (in wei) to send with the function call.
/// @param payload The calldata for the function call.
/// @return result The data returned from the function call.
function execute(
address target,
uint256 value,
Expand All @@ -18,5 +26,6 @@ contract Executor is IExternalExecutor, Ownable {
result = Address.functionCallWithValue(target, payload, value);
}

/// @notice Allows the contract to receive ether.
receive() external payable {}
}
45 changes: 45 additions & 0 deletions contracts/ImmutableDualGovernanceConfigProvider.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,65 @@ import {IDualGovernanceConfigProvider} from "./interfaces/IDualGovernanceConfigP

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

/// @title Immutable Dual Governance Config Provider
/// @notice Provides configuration values for the Dual Governance system in a gas-efficient way using immutable
/// variables to store values.
contract ImmutableDualGovernanceConfigProvider is IDualGovernanceConfigProvider {
using DualGovernanceConfig for DualGovernanceConfig.Context;

// ---
// Immutable Variables
// ---

/// @notice The percentage of the total stETH supply that must be exceeded in the Signalling Escrow to transition
/// Dual Governance from the Normal state to the VetoSignalling state.
PercentD16 public immutable FIRST_SEAL_RAGE_QUIT_SUPPORT;

/// @notice The percentage of the total stETH supply that must be exceeded in the Signalling Escrow to transition
/// Dual Governance into the RageQuit state.
PercentD16 public immutable SECOND_SEAL_RAGE_QUIT_SUPPORT;

/// @notice The minimum duration that assets must remain locked in the Signalling Escrow contract before unlocking
/// is permitted.
Duration public immutable MIN_ASSETS_LOCK_DURATION;

/// @notice The minimum duration of the VetoSignalling state.
Duration public immutable VETO_SIGNALLING_MIN_DURATION;

/// @notice The maximum duration of the VetoSignalling state.
Duration public immutable VETO_SIGNALLING_MAX_DURATION;

/// @notice The minimum duration of the VetoSignalling state before it can be exited. Once in the VetoSignalling
/// state, it cannot be exited sooner than `vetoSignallingMinActiveDuration`.
Duration public immutable VETO_SIGNALLING_MIN_ACTIVE_DURATION;

/// @notice The maximum duration of the VetoSignallingDeactivation state.
Duration public immutable VETO_SIGNALLING_DEACTIVATION_MAX_DURATION;

/// @notice The duration of the VetoCooldown state.
Duration public immutable VETO_COOLDOWN_DURATION;

/// @notice The duration of the Rage Quit Extension Period.
Duration public immutable RAGE_QUIT_EXTENSION_PERIOD_DURATION;

/// @notice The minimum delay for ETH withdrawals after the Rage Quit process completes.
Duration public immutable RAGE_QUIT_ETH_WITHDRAWALS_MIN_DELAY;

/// @notice The maximum delay for ETH withdrawals after the Rage Quit process completes.
Duration public immutable RAGE_QUIT_ETH_WITHDRAWALS_MAX_DELAY;

/// @notice The incremental growth of the ETH withdrawal delay with each "continuous" Rage Quit (a Rage Quit is
/// considered continuous if, between two Rage Quits, Dual Governance has not re-entered
/// the Normal state).
Duration public immutable RAGE_QUIT_ETH_WITHDRAWALS_DELAY_GROWTH;

// ---
// Constructor
// ---

/// @notice Initializes the Dual Governance Configuration Provider with parameters, validating that key configuration
/// values are within logical ranges to prevent malfunction of the Dual Governance system.
/// @param dualGovernanceConfig The configuration struct containing all governance parameters.
constructor(DualGovernanceConfig.Context memory dualGovernanceConfig) {
dualGovernanceConfig.validate();

Expand All @@ -49,6 +88,12 @@ contract ImmutableDualGovernanceConfigProvider is IDualGovernanceConfigProvider
RAGE_QUIT_ETH_WITHDRAWALS_DELAY_GROWTH = dualGovernanceConfig.rageQuitEthWithdrawalsDelayGrowth;
}

// ---
// Getters
// ---

/// @notice Returns the entire configuration for the Dual Governance system.
/// @return config A `DualGovernanceConfig.Context` struct containing all governance parameters.
function getDualGovernanceConfig() external view returns (DualGovernanceConfig.Context memory config) {
config.firstSealRageQuitSupport = FIRST_SEAL_RAGE_QUIT_SUPPORT;
config.secondSealRageQuitSupport = SECOND_SEAL_RAGE_QUIT_SUPPORT;
Expand Down
27 changes: 23 additions & 4 deletions contracts/ResealManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,37 @@ import {ISealable} from "./interfaces/ISealable.sol";
import {ITimelock} from "./interfaces/ITimelock.sol";
import {IResealManager} from "./interfaces/IResealManager.sol";

/// @title ResealManager
/// @dev Allows to extend pause of temporarily paused contracts to permanent pause or resume it.
/// @title Reseal Manager
/// @notice Allows to extend pause of temporarily paused contracts to permanent pause or resume it.
contract ResealManager is IResealManager {
// ---
// Errors
// ---

error SealableWrongPauseState();
error CallerIsNotGovernance(address caller);

// ---
// Immutables & Constants
// ---

uint256 public constant PAUSE_INFINITELY = type(uint256).max;
ITimelock public immutable EMERGENCY_PROTECTED_TIMELOCK;

// ---
// Constructor
// ---

/// @notice Initializes the ResealManager contract.
/// @param emergencyProtectedTimelock The address of the EmergencyProtectedTimelock contract.
constructor(ITimelock emergencyProtectedTimelock) {
EMERGENCY_PROTECTED_TIMELOCK = ITimelock(emergencyProtectedTimelock);
}

// ---
// Main Functionality
// ---

/// @notice Extends the pause of the specified sealable contract.
/// @dev Works only if conditions are met:
/// - ResealManager has PAUSE_ROLE for target contract;
Expand All @@ -40,7 +56,7 @@ contract ResealManager is IResealManager {
Address.functionCall(sealable, abi.encodeWithSelector(ISealable.pauseFor.selector, PAUSE_INFINITELY));
}

/// @notice Resumes the specified sealable contract if it is scheduled to resume in the future.
/// @notice Resumes the specified sealable contract if it is paused.
/// @dev Works only if conditions are met:
/// - ResealManager has RESUME_ROLE for target contract;
/// - Contract are paused until timestamp after current timestamp;
Expand All @@ -56,8 +72,11 @@ contract ResealManager is IResealManager {
Address.functionCall(sealable, abi.encodeWithSelector(ISealable.resume.selector));
}

// ---
// Internal methods
// ---

/// @notice Ensures that the function can only be called by the governance address.
/// @dev Reverts if the sender is not the governance address.
function _checkCallerIsGovernance() internal view {
address governance = EMERGENCY_PROTECTED_TIMELOCK.getGovernance();
if (msg.sender != governance) {
Expand Down
42 changes: 29 additions & 13 deletions contracts/TimelockedGovernance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,38 @@ import {IGovernance} from "./interfaces/IGovernance.sol";

import {ExternalCall} from "./libraries/ExternalCalls.sol";

/// @title TimelockedGovernance
/// @dev A contract that serves as the interface for submitting and scheduling the execution of governance proposals.
/// @title Timelocked Governance
/// @notice A contract that serves as the interface for submitting and scheduling the execution of governance proposals.
contract TimelockedGovernance is IGovernance {
// ---
// Errors
// ---

error CallerIsNotGovernance(address caller);

// ---
// Immutable Variables
// ---

address public immutable GOVERNANCE;
ITimelock public immutable TIMELOCK;

/// @dev Initializes the TimelockedGovernance contract.
// ---
// Main Functionality
// ---

/// @notice Initializes the TimelockedGovernance contract.
/// @param governance The address of the governance contract.
/// @param timelock The address of the timelock contract.
constructor(address governance, ITimelock timelock) {
GOVERNANCE = governance;
TIMELOCK = timelock;
}

/// @dev Submits a proposal to the timelock.
/// @notice Submits a proposal to the timelock.
/// @param calls An array of ExternalCall structs representing the calls to be executed in the proposal.
/// @param metadata A string containing additional information about the proposal.
/// @return proposalId The ID of the submitted proposal.
/// @return proposalId The id of the submitted proposal.
function submitProposal(
ExternalCall[] calldata calls,
string calldata metadata
Expand All @@ -34,33 +46,37 @@ contract TimelockedGovernance is IGovernance {
return TIMELOCK.submit(TIMELOCK.getAdminExecutor(), calls, metadata);
}

/// @dev Schedules a submitted proposal.
/// @param proposalId The ID of the proposal to be scheduled.
/// @notice Schedules a submitted proposal.
/// @param proposalId The id of the proposal to be scheduled.
function scheduleProposal(uint256 proposalId) external {
TIMELOCK.schedule(proposalId);
}

/// @dev Executes a scheduled proposal.
/// @param proposalId The ID of the proposal to be executed.
/// @notice Executes a scheduled proposal.
/// @param proposalId The id of the proposal to be executed.
function executeProposal(uint256 proposalId) external {
TIMELOCK.execute(proposalId);
}

/// @dev Checks if a proposal can be scheduled.
/// @param proposalId The ID of the proposal to check.
/// @notice Checks if a proposal can be scheduled.
/// @param proposalId The id of the proposal to check.
/// @return A boolean indicating whether the proposal can be scheduled.
function canScheduleProposal(uint256 proposalId) external view returns (bool) {
return TIMELOCK.canSchedule(proposalId);
}

/// @dev Cancels all pending proposals that have not been executed.
/// @notice Cancels all pending proposals that have not been executed.
function cancelAllPendingProposals() external returns (bool) {
_checkCallerIsGovernance();
TIMELOCK.cancelAllNonExecutedProposals();
return true;
}

/// @dev Checks if the msg.sender is the governance address.
// ---
// Internal Methods
// ---

/// @notice Checks if the msg.sender is the governance address.
function _checkCallerIsGovernance() internal view {
if (msg.sender != GOVERNANCE) {
revert CallerIsNotGovernance(msg.sender);
Expand Down
Loading