Skip to content

Commit

Permalink
Merge pull request #78 from lidofinance/fix/broken-tests
Browse files Browse the repository at this point in the history
Fix broken tests. Refactor test base classes.
  • Loading branch information
Psirex authored Aug 7, 2024
2 parents 1e544fe + 5c6f205 commit 9b92f73
Show file tree
Hide file tree
Showing 49 changed files with 2,727 additions and 2,558 deletions.
5 changes: 3 additions & 2 deletions contracts/DualGovernanceConfigProvider.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
pragma solidity 0.8.26;

import {Duration} from "./types/Duration.sol";
import {PercentD16} from "./types/PercentD16.sol";
import {DualGovernanceConfig} from "./libraries/DualGovernanceConfig.sol";

interface IDualGovernanceConfigProvider {
function getDualGovernanceConfig() external view returns (DualGovernanceConfig.Context memory config);
}

contract ImmutableDualGovernanceConfigProvider is IDualGovernanceConfigProvider {
uint256 public immutable FIRST_SEAL_RAGE_QUIT_SUPPORT;
uint256 public immutable SECOND_SEAL_RAGE_QUIT_SUPPORT;
PercentD16 public immutable FIRST_SEAL_RAGE_QUIT_SUPPORT;
PercentD16 public immutable SECOND_SEAL_RAGE_QUIT_SUPPORT;

Duration public immutable MIN_ASSETS_LOCK_DURATION;
Duration public immutable DYNAMIC_TIMELOCK_MIN_DURATION;
Expand Down
11 changes: 6 additions & 5 deletions contracts/Escrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";

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

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

Expand Down Expand Up @@ -376,17 +377,17 @@ contract Escrow is IEscrow {
return _escrowState.rageQuitExtensionDelayStartedAt;
}

function getRageQuitSupport() external view returns (uint256 rageQuitSupport) {
function getRageQuitSupport() external view returns (PercentD16) {
StETHAccounting memory stETHTotals = _accounting.stETHTotals;
UnstETHAccounting memory unstETHTotals = _accounting.unstETHTotals;

uint256 finalizedETH = unstETHTotals.finalizedETH.toUint256();
uint256 ufinalizedShares = (stETHTotals.lockedShares + unstETHTotals.unfinalizedShares).toUint256();

rageQuitSupport = (
10 ** 18 * (ST_ETH.getPooledEthByShares(ufinalizedShares) + finalizedETH)
/ (ST_ETH.totalSupply() + finalizedETH)
);
return PercentsD16.fromFraction({
numerator: ST_ETH.getPooledEthByShares(ufinalizedShares) + finalizedETH,
denominator: ST_ETH.totalSupply() + finalizedETH
});
}

function isRageQuitFinalized() external view returns (bool) {
Expand Down
3 changes: 2 additions & 1 deletion contracts/TimelockedGovernance.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import {IGovernance, ITimelock} from "./interfaces/ITimelock.sol";
import {ITimelock} from "./interfaces/ITimelock.sol";
import {IGovernance} from "./interfaces/IGovernance.sol";

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

Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/IDualGovernance.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import {IGovernance} from "./ITimelock.sol";
import {IGovernance} from "./IGovernance.sol";

interface IDualGovernance is IGovernance {
function activateNextState() external;
Expand Down
3 changes: 2 additions & 1 deletion contracts/interfaces/IEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
pragma solidity 0.8.26;

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

interface IEscrow {
function initialize(Duration minAssetsLockDuration) external;

function startRageQuit(Duration rageQuitExtraTimelock, Duration rageQuitWithdrawalsTimelock) external;

function isRageQuitFinalized() external view returns (bool);
function getRageQuitSupport() external view returns (uint256 rageQuitSupport);
function getRageQuitSupport() external view returns (PercentD16 rageQuitSupport);
function setMinAssetsLockDuration(Duration newMinAssetsLockDuration) external;
}
12 changes: 12 additions & 0 deletions contracts/interfaces/IGovernance.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

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

interface IGovernance {
function submitProposal(ExternalCall[] calldata calls) external returns (uint256 proposalId);
function scheduleProposal(uint256 proposalId) external;
function cancelAllPendingProposals() external;

function canScheduleProposal(uint256 proposalId) external view returns (bool);
}
18 changes: 0 additions & 18 deletions contracts/interfaces/IStETH.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,6 @@ pragma solidity 0.8.26;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IStETH is IERC20 {
function STAKING_CONTROL_ROLE() external view returns (bytes32);
function removeStakingLimit() external;
function getStakeLimitFullInfo()
external
view
returns (
bool isStakingPaused,
bool isStakingLimitSet,
uint256 currentStakeLimit,
uint256 maxStakeLimit,
uint256 maxStakeLimitGrowthBlocks,
uint256 prevStakeLimit,
uint256 prevStakeBlockNumber
);

function getTotalShares() external view returns (uint256);
function sharesOf(address account) external view returns (uint256);
function getSharesByPooledEth(uint256 ethAmount) external view returns (uint256);

function getPooledEthByShares(uint256 sharesAmount) external view returns (uint256);
Expand All @@ -31,5 +14,4 @@ interface IStETH is IERC20 {
address _recipient,
uint256 _sharesAmount
) external returns (uint256);
function submit(address referral) external payable returns (uint256);
}
10 changes: 1 addition & 9 deletions contracts/interfaces/ITimelock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,8 @@ pragma solidity 0.8.26;

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

import {Status as ProposalStatus} from "../libraries/ExecutableProposals.sol";
import {ExternalCall} from "../libraries/ExternalCalls.sol";

interface IGovernance {
function submitProposal(ExternalCall[] calldata calls) external returns (uint256 proposalId);
function scheduleProposal(uint256 proposalId) external;
function cancelAllPendingProposals() external;

function canScheduleProposal(uint256 proposalId) external view returns (bool);
}
import {Status as ProposalStatus} from "../libraries/ExecutableProposals.sol";

interface ITimelock {
struct Proposal {
Expand Down
18 changes: 0 additions & 18 deletions contracts/interfaces/IWithdrawalQueue.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,13 @@ interface IWithdrawalQueue is IERC721 {

function claimWithdrawals(uint256[] calldata requestIds, uint256[] calldata hints) external;

function getLastFinalizedRequestId() external view returns (uint256);

function transferFrom(address from, address to, uint256 requestId) external;

function getWithdrawalStatus(uint256[] calldata _requestIds)
external
view
returns (WithdrawalRequestStatus[] memory statuses);

function getLastRequestId() external view returns (uint256);

/// @notice Returns amount of ether available for claim for each provided request id
/// @param _requestIds array of request ids
/// @param _hints checkpoint hints. can be found with `findCheckpointHints(_requestIds, 1, getLastCheckpointIndex())`
Expand All @@ -46,22 +42,8 @@ interface IWithdrawalQueue is IERC721 {
) external view returns (uint256[] memory hintIds);
function getLastCheckpointIndex() external view returns (uint256);

function balanceOf(address owner) external view returns (uint256);

function requestWithdrawals(
uint256[] calldata _amounts,
address _owner
) external returns (uint256[] memory requestIds);

function setApprovalForAll(address _operator, bool _approved) external;

function requestWithdrawalsWstETH(
uint256[] calldata _amounts,
address _owner
) external returns (uint256[] memory requestIds);

function grantRole(bytes32 role, address account) external;
function pauseFor(uint256 duration) external;
function isPaused() external returns (bool);
function finalize(uint256 _lastRequestIdToBeFinalized, uint256 _maxShareRate) external payable;
}
2 changes: 1 addition & 1 deletion contracts/interfaces/IWstETH.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IWstETH is IERC20 {
function wrap(uint256 stETHAmount) external returns (uint256);

function unwrap(uint256 wstETHAmount) external returns (uint256);
function getStETHByWstETH(uint256 wstethAmount) external view returns (uint256);
}
22 changes: 12 additions & 10 deletions contracts/libraries/DualGovernanceConfig.sol
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

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

library DualGovernanceConfig {
struct Context {
uint256 firstSealRageQuitSupport;
uint256 secondSealRageQuitSupport;
PercentD16 firstSealRageQuitSupport;
PercentD16 secondSealRageQuitSupport;
Duration minAssetsLockDuration;
Duration dynamicTimelockMaxDuration;
Duration dynamicTimelockMinDuration;
Expand All @@ -22,14 +23,14 @@ library DualGovernanceConfig {

function isFirstSealRageQuitSupportCrossed(
Context memory self,
uint256 rageQuitSupport
PercentD16 rageQuitSupport
) internal pure returns (bool) {
return rageQuitSupport > self.firstSealRageQuitSupport;
}

function isSecondSealRageQuitSupportCrossed(
Context memory self,
uint256 rageQuitSupport
PercentD16 rageQuitSupport
) internal pure returns (bool) {
return rageQuitSupport > self.secondSealRageQuitSupport;
}
Expand All @@ -44,7 +45,7 @@ library DualGovernanceConfig {
function isDynamicTimelockDurationPassed(
Context memory self,
Timestamp vetoSignallingActivatedAt,
uint256 rageQuitSupport
PercentD16 rageQuitSupport
) internal view returns (bool) {
Duration dynamicTimelock = calcDynamicDelayDuration(self, rageQuitSupport);
return Timestamps.now() > dynamicTimelock.addTo(vetoSignallingActivatedAt);
Expand Down Expand Up @@ -73,10 +74,11 @@ library DualGovernanceConfig {

function calcDynamicDelayDuration(
Context memory self,
uint256 rageQuitSupport
PercentD16 rageQuitSupport
) internal pure returns (Duration duration_) {
uint256 firstSealRageQuitSupport = self.firstSealRageQuitSupport;
uint256 secondSealRageQuitSupport = self.secondSealRageQuitSupport;
PercentD16 firstSealRageQuitSupport = self.firstSealRageQuitSupport;
PercentD16 secondSealRageQuitSupport = self.secondSealRageQuitSupport;

Duration dynamicTimelockMinDuration = self.dynamicTimelockMinDuration;
Duration dynamicTimelockMaxDuration = self.dynamicTimelockMaxDuration;

Expand All @@ -90,9 +92,9 @@ library DualGovernanceConfig {

duration_ = dynamicTimelockMinDuration
+ Durations.from(
(rageQuitSupport - firstSealRageQuitSupport)
PercentD16.unwrap(rageQuitSupport - firstSealRageQuitSupport)
* (dynamicTimelockMaxDuration - dynamicTimelockMinDuration).toSeconds()
/ (secondSealRageQuitSupport - firstSealRageQuitSupport)
/ PercentD16.unwrap(secondSealRageQuitSupport - firstSealRageQuitSupport)
);
}

Expand Down
5 changes: 3 additions & 2 deletions contracts/libraries/DualGovernanceStateMachine.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
import {IEscrow} from "../interfaces/IEscrow.sol";

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

import {DualGovernanceConfig} from "./DualGovernanceConfig.sol";
Expand Down Expand Up @@ -200,7 +201,7 @@ library DualGovernanceStateTransitions {
DualGovernanceStateMachine.Context storage self,
DualGovernanceConfig.Context memory config
) private view returns (State) {
uint256 rageQuitSupport = self.signallingEscrow.getRageQuitSupport();
PercentD16 rageQuitSupport = self.signallingEscrow.getRageQuitSupport();

if (!config.isDynamicTimelockDurationPassed(self.vetoSignallingActivatedAt, rageQuitSupport)) {
return State.VetoSignalling;
Expand All @@ -219,7 +220,7 @@ library DualGovernanceStateTransitions {
DualGovernanceStateMachine.Context storage self,
DualGovernanceConfig.Context memory config
) private view returns (State) {
uint256 rageQuitSupport = self.signallingEscrow.getRageQuitSupport();
PercentD16 rageQuitSupport = self.signallingEscrow.getRageQuitSupport();

if (!config.isDynamicTimelockDurationPassed(self.vetoSignallingActivatedAt, rageQuitSupport)) {
return State.VetoSignalling;
Expand Down
19 changes: 9 additions & 10 deletions contracts/libraries/EmergencyProtection.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ library EmergencyProtection {
}

self.emergencyModeEndsAfter = self.emergencyModeDuration.addTo(now_);
self.emergencyProtectionEndsAfter = now_;

emit EmergencyModeActivated();
}
Expand All @@ -73,7 +72,7 @@ library EmergencyProtection {
// ---

function setEmergencyGovernance(Context storage self, address newEmergencyGovernance) internal {
if (self.emergencyGovernance == newEmergencyGovernance) {
if (newEmergencyGovernance == self.emergencyGovernance) {
return;
}
self.emergencyGovernance = newEmergencyGovernance;
Expand All @@ -82,18 +81,18 @@ library EmergencyProtection {

function setEmergencyProtectionEndDate(
Context storage self,
Timestamp emergencyProtectionEndDate,
Timestamp newEmergencyProtectionEndDate,
Duration maxEmergencyProtectionDuration
) internal {
if (emergencyProtectionEndDate > maxEmergencyProtectionDuration.addTo(Timestamps.now())) {
revert InvalidEmergencyProtectionEndDate(emergencyProtectionEndDate);
if (newEmergencyProtectionEndDate > maxEmergencyProtectionDuration.addTo(Timestamps.now())) {
revert InvalidEmergencyProtectionEndDate(newEmergencyProtectionEndDate);
}

if (self.emergencyProtectionEndsAfter == emergencyProtectionEndDate) {
if (newEmergencyProtectionEndDate == self.emergencyProtectionEndsAfter) {
return;
}
self.emergencyProtectionEndsAfter = emergencyProtectionEndDate;
emit EmergencyProtectionEndDateSet(emergencyProtectionEndDate);
self.emergencyProtectionEndsAfter = newEmergencyProtectionEndDate;
emit EmergencyProtectionEndDateSet(newEmergencyProtectionEndDate);
}

function setEmergencyModeDuration(
Expand All @@ -113,15 +112,15 @@ library EmergencyProtection {
}

function setEmergencyActivationCommittee(Context storage self, address newActivationCommittee) internal {
if (self.emergencyActivationCommittee == newActivationCommittee) {
if (newActivationCommittee == self.emergencyActivationCommittee) {
return;
}
self.emergencyActivationCommittee = newActivationCommittee;
emit EmergencyActivationCommitteeSet(newActivationCommittee);
}

function setEmergencyExecutionCommittee(Context storage self, address newExecutionCommittee) internal {
if (self.emergencyActivationCommittee == newExecutionCommittee) {
if (newExecutionCommittee == self.emergencyExecutionCommittee) {
return;
}
self.emergencyExecutionCommittee = newExecutionCommittee;
Expand Down
43 changes: 43 additions & 0 deletions contracts/types/PercentD16.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

type PercentD16 is uint256;

uint256 constant HUNDRED_PERCENTS_UINT256 = 100 * 10 ** 16;

error Overflow();

using {lt as <, gte as >=, gt as >, minus as -, plus as +} for PercentD16 global;

function lt(PercentD16 a, PercentD16 b) pure returns (bool) {
return PercentD16.unwrap(a) < PercentD16.unwrap(b);
}

function gt(PercentD16 a, PercentD16 b) pure returns (bool) {
return PercentD16.unwrap(a) > PercentD16.unwrap(b);
}

function gte(PercentD16 a, PercentD16 b) pure returns (bool) {
return PercentD16.unwrap(a) >= PercentD16.unwrap(b);
}

function minus(PercentD16 a, PercentD16 b) pure returns (PercentD16) {
if (b > a) {
revert Overflow();
}
return PercentD16.wrap(PercentD16.unwrap(a) - PercentD16.unwrap(b));
}

function plus(PercentD16 a, PercentD16 b) pure returns (PercentD16) {
return PercentD16.wrap(PercentD16.unwrap(a) + PercentD16.unwrap(b));
}

library PercentsD16 {
function fromBasisPoints(uint256 bpValue) internal pure returns (PercentD16) {
return PercentD16.wrap(HUNDRED_PERCENTS_UINT256 * bpValue / 100_00);
}

function fromFraction(uint256 numerator, uint256 denominator) internal pure returns (PercentD16) {
return PercentD16.wrap(HUNDRED_PERCENTS_UINT256 * numerator / denominator);
}
}
Loading

0 comments on commit 9b92f73

Please sign in to comment.