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

Fix broken tests. Refactor test base classes. #78

Merged
merged 2 commits into from
Aug 7, 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
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