Skip to content

Commit

Permalink
Merge pull request #233 from lidofinance/fix/max-assets-lock-duration
Browse files Browse the repository at this point in the history
Max assets lock duration sanity check
  • Loading branch information
bulbozaur authored Dec 6, 2024
2 parents 13736dd + 602235f commit 5aaab5b
Show file tree
Hide file tree
Showing 12 changed files with 163 additions and 68 deletions.
47 changes: 31 additions & 16 deletions contracts/DualGovernance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ contract DualGovernance is IDualGovernance {
error ProposalSubmissionBlocked();
error ProposalSchedulingBlocked(uint256 proposalId);
error ResealIsNotAllowedInNormalState();
error InvalidTiebreakerActivationTimeoutBounds();
error InvalidTiebreakerActivationTimeoutBounds(
Duration minTiebreakerActivationTimeout, Duration maxTiebreakerActivationTimeout
);

// ---
// Events
Expand All @@ -69,11 +71,13 @@ contract DualGovernance is IDualGovernance {
/// @param maxSealableWithdrawalBlockersCount The upper bound for the number of sealable withdrawal blockers allowed to be
/// registered in the Dual Governance. This parameter prevents filling the sealable withdrawal blockers
/// with so many items that tiebreaker calls would revert due to out-of-gas errors.
/// @param maxMinAssetsLockDuration The upper bound for the minimum duration of assets lock in the Escrow.
struct SanityCheckParams {
uint256 minWithdrawalsBatchSize;
Duration minTiebreakerActivationTimeout;
Duration maxTiebreakerActivationTimeout;
uint256 maxSealableWithdrawalBlockersCount;
Duration maxMinAssetsLockDuration;
}

/// @notice The lower bound for the time the Dual Governance must spend in the "locked" state
Expand All @@ -93,17 +97,21 @@ contract DualGovernance is IDualGovernance {
// External Dependencies
// ---

/// @notice The external dependencies of the Dual Governance system.
/// @notice Token addresses that used in the Dual Governance as signalling tokens.
/// @param stETH The address of the stETH token.
/// @param wstETH The address of the wstETH token.
/// @param withdrawalQueue The address of Lido's Withdrawal Queue and the unstETH token.
/// @param timelock The address of the Timelock contract.
/// @param resealManager The address of the Reseal Manager.
/// @param configProvider The address of the Dual Governance Config Provider.
struct ExternalDependencies {
struct SignallingTokens {
IStETH stETH;
IWstETH wstETH;
IWithdrawalQueue withdrawalQueue;
}

/// @notice Dependencies required by the Dual Governance contract.
/// @param timelock The address of the Timelock contract.
/// @param resealManager The address of the Reseal Manager.
/// @param configProvider The address of the Dual Governance Config Provider.
struct DualGovernanceComponents {
ITimelock timelock;
IResealManager resealManager;
IDualGovernanceConfigProvider configProvider;
Expand Down Expand Up @@ -136,29 +144,36 @@ contract DualGovernance is IDualGovernance {
// Constructor
// ---

constructor(ExternalDependencies memory dependencies, SanityCheckParams memory sanityCheckParams) {
constructor(
DualGovernanceComponents memory components,
SignallingTokens memory signallingTokens,
SanityCheckParams memory sanityCheckParams
) {
if (sanityCheckParams.minTiebreakerActivationTimeout > sanityCheckParams.maxTiebreakerActivationTimeout) {
revert InvalidTiebreakerActivationTimeoutBounds();
revert InvalidTiebreakerActivationTimeoutBounds(
sanityCheckParams.minTiebreakerActivationTimeout, sanityCheckParams.maxTiebreakerActivationTimeout
);
}

TIMELOCK = dependencies.timelock;
TIMELOCK = components.timelock;

MIN_TIEBREAKER_ACTIVATION_TIMEOUT = sanityCheckParams.minTiebreakerActivationTimeout;
MAX_TIEBREAKER_ACTIVATION_TIMEOUT = sanityCheckParams.maxTiebreakerActivationTimeout;
MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT = sanityCheckParams.maxSealableWithdrawalBlockersCount;

IEscrowBase escrowMasterCopy = new Escrow({
dualGovernance: this,
stETH: dependencies.stETH,
wstETH: dependencies.wstETH,
withdrawalQueue: dependencies.withdrawalQueue,
minWithdrawalsBatchSize: sanityCheckParams.minWithdrawalsBatchSize
stETH: signallingTokens.stETH,
wstETH: signallingTokens.wstETH,
withdrawalQueue: signallingTokens.withdrawalQueue,
minWithdrawalsBatchSize: sanityCheckParams.minWithdrawalsBatchSize,
maxMinAssetsLockDuration: sanityCheckParams.maxMinAssetsLockDuration
});

emit EscrowMasterCopyDeployed(escrowMasterCopy);

_stateMachine.initialize(dependencies.configProvider, escrowMasterCopy);
_resealer.setResealManager(address(dependencies.resealManager));
_stateMachine.initialize(components.configProvider, escrowMasterCopy);
_resealer.setResealManager(components.resealManager);
}

// ---
Expand Down Expand Up @@ -521,7 +536,7 @@ contract DualGovernance is IDualGovernance {

/// @notice Sets the address of the Reseal Manager.
/// @param newResealManager The address of the new Reseal Manager.
function setResealManager(address newResealManager) external {
function setResealManager(IResealManager newResealManager) external {
_checkCallerIsAdminExecutor();
_resealer.setResealManager(newResealManager);
}
Expand Down
9 changes: 7 additions & 2 deletions contracts/Escrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ contract Escrow is ISignallingEscrow, IRageQuitEscrow {
/// the `Escrow.requestNextWithdrawalsBatch(batchSize)` method.
uint256 public immutable MIN_WITHDRAWALS_BATCH_SIZE;

/// @notice The maximum duration that can be set as the minimum assets lock duration.
Duration public immutable MAX_MIN_ASSETS_LOCK_DURATION;

// ---
// Dependencies Immutables
// ---
Expand Down Expand Up @@ -109,7 +112,8 @@ contract Escrow is ISignallingEscrow, IRageQuitEscrow {
IWstETH wstETH,
IWithdrawalQueue withdrawalQueue,
IDualGovernance dualGovernance,
uint256 minWithdrawalsBatchSize
uint256 minWithdrawalsBatchSize,
Duration maxMinAssetsLockDuration
) {
ESCROW_MASTER_COPY = this;
DUAL_GOVERNANCE = dualGovernance;
Expand All @@ -119,6 +123,7 @@ contract Escrow is ISignallingEscrow, IRageQuitEscrow {
WITHDRAWAL_QUEUE = withdrawalQueue;

MIN_WITHDRAWALS_BATCH_SIZE = minWithdrawalsBatchSize;
MAX_MIN_ASSETS_LOCK_DURATION = maxMinAssetsLockDuration;
}

// ---
Expand Down Expand Up @@ -304,7 +309,7 @@ contract Escrow is ISignallingEscrow, IRageQuitEscrow {
/// @param newMinAssetsLockDuration The new minimum lock duration to be set.
function setMinAssetsLockDuration(Duration newMinAssetsLockDuration) external {
_checkCallerIsDualGovernance();
_escrowState.setMinAssetsLockDuration(newMinAssetsLockDuration);
_escrowState.setMinAssetsLockDuration(newMinAssetsLockDuration, MAX_MIN_ASSETS_LOCK_DURATION);
}

// ---
Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/IDualGovernance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ interface IDualGovernance is IGovernance, ITiebreaker {

function resealSealable(address sealable) external;
function setResealCommittee(address newResealCommittee) external;
function setResealManager(address newResealManager) external;
function setResealManager(IResealManager newResealManager) external;
function getResealManager() external view returns (IResealManager);
function getResealCommittee() external view returns (address);
}
12 changes: 10 additions & 2 deletions contracts/libraries/EscrowState.sol
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,16 @@ library EscrowState {
/// @notice Sets the minimum assets lock duration.
/// @param self The context of the Escrow State library.
/// @param newMinAssetsLockDuration The new minimum assets lock duration.
function setMinAssetsLockDuration(Context storage self, Duration newMinAssetsLockDuration) internal {
if (self.minAssetsLockDuration == newMinAssetsLockDuration) {
/// @param maxMinAssetsLockDuration Sanity check for max assets lock duration.
function setMinAssetsLockDuration(
Context storage self,
Duration newMinAssetsLockDuration,
Duration maxMinAssetsLockDuration
) internal {
if (
self.minAssetsLockDuration == newMinAssetsLockDuration
|| newMinAssetsLockDuration > maxMinAssetsLockDuration
) {
revert InvalidMinAssetsLockDuration(newMinAssetsLockDuration);
}
_setMinAssetsLockDuration(self, newMinAssetsLockDuration);
Expand Down
10 changes: 5 additions & 5 deletions contracts/libraries/Resealer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ library Resealer {
// ---
// Errors
// ---
error InvalidResealManager(address resealManager);
error InvalidResealManager(IResealManager resealManager);
error InvalidResealCommittee(address resealCommittee);
error CallerIsNotResealCommittee(address caller);

// ---
// Events
// ---
event ResealCommitteeSet(address resealCommittee);
event ResealManagerSet(address resealManager);
event ResealManagerSet(IResealManager resealManager);

// ---
// Data Types
Expand All @@ -35,11 +35,11 @@ library Resealer {
/// @dev Sets a new Reseal Manager contract address.
/// @param self The context struct containing the current state.
/// @param newResealManager The address of the new Reseal Manager.
function setResealManager(Context storage self, address newResealManager) internal {
if (newResealManager == address(self.resealManager) || newResealManager == address(0)) {
function setResealManager(Context storage self, IResealManager newResealManager) internal {
if (newResealManager == self.resealManager || address(newResealManager) == address(0)) {
revert InvalidResealManager(newResealManager);
}
self.resealManager = IResealManager(newResealManager);
self.resealManager = newResealManager;
emit ResealManagerSet(newResealManager);
}

Expand Down
2 changes: 2 additions & 0 deletions scripts/deploy/Config.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ uint256 constant DEFAULT_MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT = 255;
uint256 constant DEFAULT_FIRST_SEAL_RAGE_QUIT_SUPPORT = 3_00; // 3%
uint256 constant DEFAULT_SECOND_SEAL_RAGE_QUIT_SUPPORT = 15_00; // 15%
uint256 constant DEFAULT_MIN_ASSETS_LOCK_DURATION = 5 hours;
uint256 constant DEFAULT_MAX_MIN_ASSETS_LOCK_DURATION = 365 days;
uint256 constant DEFAULT_VETO_SIGNALLING_MIN_DURATION = 3 days;
uint256 constant DEFAULT_VETO_SIGNALLING_MAX_DURATION = 30 days;
uint256 constant DEFAULT_VETO_SIGNALLING_MIN_ACTIVE_DURATION = 5 hours;
Expand Down Expand Up @@ -80,6 +81,7 @@ struct DeployConfig {
PercentD16 FIRST_SEAL_RAGE_QUIT_SUPPORT;
PercentD16 SECOND_SEAL_RAGE_QUIT_SUPPORT;
Duration MIN_ASSETS_LOCK_DURATION;
Duration MAX_MIN_ASSETS_LOCK_DURATION;
Duration VETO_SIGNALLING_MIN_DURATION;
Duration VETO_SIGNALLING_MAX_DURATION;
Duration VETO_SIGNALLING_MIN_ACTIVE_DURATION;
Expand Down
13 changes: 8 additions & 5 deletions scripts/deploy/ContractsDeployment.sol
Original file line number Diff line number Diff line change
Expand Up @@ -216,19 +216,22 @@ library DGContractsDeployment {
LidoContracts memory lidoAddresses
) internal returns (DualGovernance) {
return new DualGovernance({
dependencies: DualGovernance.ExternalDependencies({
stETH: lidoAddresses.stETH,
wstETH: lidoAddresses.wstETH,
withdrawalQueue: lidoAddresses.withdrawalQueue,
components: DualGovernance.DualGovernanceComponents({
timelock: timelock,
resealManager: resealManager,
configProvider: configProvider
}),
signallingTokens: DualGovernance.SignallingTokens({
stETH: lidoAddresses.stETH,
wstETH: lidoAddresses.wstETH,
withdrawalQueue: lidoAddresses.withdrawalQueue
}),
sanityCheckParams: DualGovernance.SanityCheckParams({
minWithdrawalsBatchSize: dgDeployConfig.MIN_WITHDRAWALS_BATCH_SIZE,
minTiebreakerActivationTimeout: dgDeployConfig.MIN_TIEBREAKER_ACTIVATION_TIMEOUT,
maxTiebreakerActivationTimeout: dgDeployConfig.MAX_TIEBREAKER_ACTIVATION_TIMEOUT,
maxSealableWithdrawalBlockersCount: dgDeployConfig.MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT
maxSealableWithdrawalBlockersCount: dgDeployConfig.MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT,
maxMinAssetsLockDuration: dgDeployConfig.MAX_MIN_ASSETS_LOCK_DURATION
})
});
}
Expand Down
4 changes: 4 additions & 0 deletions scripts/deploy/JsonConfig.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
DEFAULT_FIRST_SEAL_RAGE_QUIT_SUPPORT,
DEFAULT_SECOND_SEAL_RAGE_QUIT_SUPPORT,
DEFAULT_MIN_ASSETS_LOCK_DURATION,
DEFAULT_MAX_MIN_ASSETS_LOCK_DURATION,
DEFAULT_VETO_SIGNALLING_MIN_DURATION,
DEFAULT_VETO_SIGNALLING_MAX_DURATION,
DEFAULT_VETO_SIGNALLING_MIN_ACTIVE_DURATION,
Expand Down Expand Up @@ -173,6 +174,9 @@ contract DGDeployJSONConfigProvider is Script {
MIN_ASSETS_LOCK_DURATION: Durations.from(
stdJson.readUintOr(jsonConfig, ".MIN_ASSETS_LOCK_DURATION", DEFAULT_MIN_ASSETS_LOCK_DURATION)
),
MAX_MIN_ASSETS_LOCK_DURATION: Durations.from(
stdJson.readUintOr(jsonConfig, ".MAX_MIN_ASSETS_LOCK_DURATION", DEFAULT_MAX_MIN_ASSETS_LOCK_DURATION)
),
VETO_SIGNALLING_MIN_DURATION: Durations.from(
stdJson.readUintOr(jsonConfig, ".VETO_SIGNALLING_MIN_DURATION", DEFAULT_VETO_SIGNALLING_MIN_DURATION)
),
Expand Down
Loading

0 comments on commit 5aaab5b

Please sign in to comment.