forked from lidofinance/dual-governance
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request lidofinance#21 from lidofinance/feature/tiebreaker
Tiebraker and Emergency execution committees
- Loading branch information
Showing
29 changed files
with
1,192 additions
and
415 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.23; | ||
|
||
import {Address} from "@openzeppelin/contracts/utils/Address.sol"; | ||
import {ISealable} from "./interfaces/ISealable.sol"; | ||
|
||
interface IEmergencyProtectedTimelock { | ||
function getGovernance() external view returns (address); | ||
} | ||
|
||
contract ResealManager { | ||
error SealableWrongPauseState(); | ||
error SenderIsNotGovernance(); | ||
error NotAllowed(); | ||
|
||
uint256 public constant PAUSE_INFINITELY = type(uint256).max; | ||
address public immutable EMERGENCY_PROTECTED_TIMELOCK; | ||
|
||
constructor(address emergencyProtectedTimelock) { | ||
EMERGENCY_PROTECTED_TIMELOCK = emergencyProtectedTimelock; | ||
} | ||
|
||
function reseal(address[] memory sealables) public onlyGovernance { | ||
for (uint256 i = 0; i < sealables.length; ++i) { | ||
uint256 sealableResumeSinceTimestamp = ISealable(sealables[i]).getResumeSinceTimestamp(); | ||
if (sealableResumeSinceTimestamp < block.timestamp || sealableResumeSinceTimestamp == PAUSE_INFINITELY) { | ||
revert SealableWrongPauseState(); | ||
} | ||
Address.functionCall(sealables[i], abi.encodeWithSelector(ISealable.resume.selector)); | ||
Address.functionCall(sealables[i], abi.encodeWithSelector(ISealable.pauseFor.selector, PAUSE_INFINITELY)); | ||
} | ||
} | ||
|
||
function resume(address sealable) public onlyGovernance { | ||
uint256 sealableResumeSinceTimestamp = ISealable(sealable).getResumeSinceTimestamp(); | ||
if (sealableResumeSinceTimestamp < block.timestamp) { | ||
revert SealableWrongPauseState(); | ||
} | ||
Address.functionCall(sealable, abi.encodeWithSelector(ISealable.resume.selector)); | ||
} | ||
|
||
modifier onlyGovernance() { | ||
address governance = IEmergencyProtectedTimelock(EMERGENCY_PROTECTED_TIMELOCK).getGovernance(); | ||
if (msg.sender != governance) { | ||
revert SenderIsNotGovernance(); | ||
} | ||
_; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.23; | ||
|
||
import {Address} from "@openzeppelin/contracts/utils/Address.sol"; | ||
import {HashConsensus} from "./HashConsensus.sol"; | ||
|
||
interface IEmergencyProtectedTimelock { | ||
function emergencyActivate() external; | ||
} | ||
|
||
contract EmergencyActivationCommittee is HashConsensus { | ||
address public immutable EMERGENCY_PROTECTED_TIMELOCK; | ||
|
||
bytes32 private constant EMERGENCY_ACTIVATION_HASH = keccak256("EMERGENCY_ACTIVATE"); | ||
|
||
constructor( | ||
address owner, | ||
address[] memory committeeMembers, | ||
uint256 executionQuorum, | ||
address emergencyProtectedTimelock | ||
) HashConsensus(owner, committeeMembers, executionQuorum, 0) { | ||
EMERGENCY_PROTECTED_TIMELOCK = emergencyProtectedTimelock; | ||
} | ||
|
||
function approveEmergencyActivate() public onlyMember { | ||
_vote(EMERGENCY_ACTIVATION_HASH, true); | ||
} | ||
|
||
function getEmergencyActivateState() | ||
public | ||
view | ||
returns (uint256 support, uint256 execuitionQuorum, bool isExecuted) | ||
{ | ||
return _getHashState(EMERGENCY_ACTIVATION_HASH); | ||
} | ||
|
||
function executeEmergencyActivate() external { | ||
_markUsed(EMERGENCY_ACTIVATION_HASH); | ||
Address.functionCall( | ||
EMERGENCY_PROTECTED_TIMELOCK, abi.encodeWithSelector(IEmergencyProtectedTimelock.emergencyActivate.selector) | ||
); | ||
} | ||
} |
Oops, something went wrong.