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

Contract pausing #164

Merged
merged 74 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from 60 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
9042f78
Add Pausable helper contract
m-chrzan Sep 15, 2023
2f699e8
Add pause/unpause to Account
m-chrzan Sep 15, 2023
29c243a
Enabling pausing functions in Account
m-chrzan Sep 15, 2023
c54bb69
Add NatSpecs to Account
m-chrzan Sep 21, 2023
7cbe2da
Move isPaused logic to Pausable
m-chrzan Sep 21, 2023
4e4c883
Add NatSpecs to Pausable
m-chrzan Sep 21, 2023
7e1f8a0
Appease the linter
m-chrzan Sep 21, 2023
99e90f5
Update Account version
m-chrzan Sep 26, 2023
277a0d4
Create pauser with pause function
m-chrzan Oct 10, 2023
5e35998
Add unpause to Pauser
m-chrzan Oct 10, 2023
9d503d1
Specify exact revert message
m-chrzan Oct 10, 2023
5b49679
Make Pausable an abstract contract with IPausable functions
m-chrzan Oct 10, 2023
70fccbf
Add isPaused to Pausable interface
m-chrzan Oct 10, 2023
0a8dd61
Change pause/unpause permissions in Account
m-chrzan Oct 10, 2023
90fbb41
Add Pauser to MultiSig
m-chrzan Oct 11, 2023
2ddda5b
Allow a MultiSig signer to pause protocol contracts
m-chrzan Oct 11, 2023
d445957
Fix tests failing due to wrong proposal index
m-chrzan Oct 11, 2023
09c08e5
Go through Pauser contract
m-chrzan Oct 12, 2023
1b01ee0
Allow Governance to unpause contracts
m-chrzan Oct 12, 2023
12d1a5c
Appease the linter
m-chrzan Oct 12, 2023
1261dab
Document with NatSpecs
m-chrzan Oct 12, 2023
521a4b6
Add Pauser interface
m-chrzan Oct 13, 2023
f9176a7
Fix test
m-chrzan Oct 13, 2023
18c12dd
Add missing awaits
m-chrzan Oct 18, 2023
3aafc89
Reset network before Pauser test
m-chrzan Oct 18, 2023
c321be4
Store pause and pauser in assembly-accessible slots
m-chrzan Oct 24, 2023
51e1c8c
Appease the linter
m-chrzan Oct 24, 2023
6e69a9f
Remove timeout on GroupHealth test
m-chrzan Oct 27, 2023
f6ddbb2
Emit events on pause/unpause
m-chrzan Oct 30, 2023
45560d4
Add PauserSet event
m-chrzan Oct 30, 2023
eae36ec
Test _setPauser
m-chrzan Oct 30, 2023
60115f7
Remove unnecessary import
m-chrzan Nov 16, 2023
401b2e9
Disable proposal submission when MultiSig paused
m-chrzan Dec 18, 2023
455e7b9
Disable confirmProposal when paused
m-chrzan Dec 18, 2023
969b9e5
Disable scheduling and executing when paused
m-chrzan Dec 18, 2023
51f10b0
Make setPauser onlyOwner
m-chrzan Dec 31, 2023
6e12ff9
Add event tests
m-chrzan Jan 2, 2024
39031b9
Use actual owner from test deployment
m-chrzan Jan 2, 2024
21fc013
Make DefaultStrategy pausable
m-chrzan Jan 4, 2024
71f93b6
Add Pausable to GroupHealth
m-chrzan Jan 10, 2024
af666c1
Use named owner account in Manager test
m-chrzan Jan 10, 2024
2bc81a8
Add Pausable to Manager
m-chrzan Jan 10, 2024
25dd619
Add Pausable to RebasedStakedCelo
m-chrzan Jan 10, 2024
db32949
Use named owner in SpecificGroupStrategy test
m-chrzan Jan 10, 2024
c4fec4b
Add Pausable to SpecificGroupStrategy
m-chrzan Jan 10, 2024
b926580
Add Pausable to StakedCelo
m-chrzan Jan 11, 2024
0eb8ef3
Make ERC20 functions on StakedCelo pausable
m-chrzan Jan 16, 2024
14d7485
Make rstCELO ERC20 functions pausable
m-chrzan Jan 16, 2024
88a82fd
Fix Manager tests
m-chrzan Jan 18, 2024
92ceeed
Fix DefaultStrategy test
m-chrzan Jan 18, 2024
3b13532
Appease the linter
m-chrzan Jan 18, 2024
15f4a6d
Merge branch 'master' into m-chrzan/protocol-pause
m-chrzan Jan 22, 2024
a26abae
Merge branch 'master' into m-chrzan/protocol-pause
m-chrzan Feb 1, 2024
7d9e699
Bump version numbers
m-chrzan Feb 1, 2024
78ae33d
Tooling fix
pahor167 Feb 2, 2024
3a35586
multisig version
pahor167 Feb 2, 2024
8b9831b
Don't use core deployment for Vote tests
m-chrzan Feb 4, 2024
b570b24
Make Vote pausable
m-chrzan Feb 4, 2024
e345bfe
Appease the linter
m-chrzan Feb 4, 2024
637606c
Add missing deploy script
m-chrzan Feb 5, 2024
6baafe2
Update version number
m-chrzan Feb 5, 2024
a293d97
Fix typo
m-chrzan Feb 7, 2024
e7b74bb
Rename variables to avoid shadowed name
m-chrzan Feb 7, 2024
fb1a5f4
Merge branch 'master' into m-chrzan/protocol-pause
m-chrzan Feb 14, 2024
1905e56
Remove .only
m-chrzan Feb 14, 2024
c6f28e9
Move Pauser functionality to MultiSig
m-chrzan Feb 14, 2024
62395a5
Move AddressNotZero to common errors contract
m-chrzan Feb 16, 2024
cb61e49
Do not allow address 0 pauser
m-chrzan Feb 16, 2024
f8d935a
Use common error name instead of NullAddress
m-chrzan Feb 16, 2024
1ae5ef8
Remove unused imports and variables
m-chrzan Feb 16, 2024
9486e71
Let Governance pause contracts
m-chrzan Feb 20, 2024
f153bc0
Always set pauser to owner
m-chrzan Feb 20, 2024
d97b07d
Appease the linter
m-chrzan Feb 20, 2024
edd5496
Add test
m-chrzan Feb 21, 2024
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
28 changes: 19 additions & 9 deletions contracts/Account.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import "./Managed.sol";
import "./common/UUPSOwnableUpgradeable.sol";
import "./common/UsingRegistryUpgradeable.sol";
import "./interfaces/IAccount.sol";
import "./Pausable.sol";
m-chrzan marked this conversation as resolved.
Show resolved Hide resolved

/**
* @title A contract that facilitates voting on behalf of StakedCelo.sol.
* @notice This contract depends on the Manager to decide how to distribute votes and how to
* keep track of ownership of CELO voted via this contract.
*/
contract Account is UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Managed, IAccount {
contract Account is UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Managed, IAccount, Pausable {
/**
* @notice Used to keep track of a pending withdrawal. A similar data structure
* exists within LockedGold.sol, but it only keeps track of pending withdrawals
Expand Down Expand Up @@ -225,6 +226,14 @@ contract Account is UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Managed, I
}
}

/**
* @notice Sets that address permissioned to pause/unpause this contract.
* @param _pauser The address that can pause/unpause this contract.
*/
function setPauser(address _pauser) external onlyOwner {
m-chrzan marked this conversation as resolved.
Show resolved Hide resolved
_setPauser(_pauser);
}

/**
* @notice Deposits CELO sent via msg.value as unlocked CELO intended as
* votes for groups.
Expand All @@ -238,6 +247,7 @@ contract Account is UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Managed, I
external
payable
onlyManager
onlyWhenNotPaused
{
if (groups.length != votes.length) {
revert GroupsAndVotesArrayLengthsMismatch();
Expand Down Expand Up @@ -268,7 +278,7 @@ contract Account is UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Managed, I
uint256[] calldata fromVotes,
address[] calldata toGroups,
uint256[] calldata toVotes
) external onlyManager {
) external onlyManager onlyWhenNotPaused {
if (fromGroups.length != fromVotes.length || toGroups.length != toVotes.length) {
revert GroupsAndVotesArrayLengthsMismatch();
}
Expand Down Expand Up @@ -301,7 +311,7 @@ contract Account is UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Managed, I
address beneficiary,
address[] calldata groups,
uint256[] calldata withdrawals
) external onlyManager {
) external onlyManager onlyWhenNotPaused {
if (groups.length != withdrawals.length) {
revert GroupsAndVotesArrayLengthsMismatch();
}
Expand Down Expand Up @@ -355,7 +365,7 @@ contract Account is UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Managed, I
address lesserAfterActiveRevoke,
address greaterAfterActiveRevoke,
uint256 index
) external returns (uint256) {
) external onlyWhenNotPaused returns (uint256) {
uint256 withdrawalAmount = scheduledVotes[group].toWithdrawFor[beneficiary];
if (withdrawalAmount == 0) {
revert NoScheduledWithdrawal(beneficiary, group);
Expand Down Expand Up @@ -431,7 +441,7 @@ contract Account is UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Managed, I
address group,
address voteLesser,
address voteGreater
) external {
) external onlyWhenNotPaused {
IElection election = getElection();

// The amount of unlocked CELO for group that we want to lock and vote with.
Expand Down Expand Up @@ -491,7 +501,7 @@ contract Account is UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Managed, I
address beneficiary,
uint256 localPendingWithdrawalIndex,
uint256 lockedGoldPendingWithdrawalIndex
) external returns (uint256 amount) {
) external onlyWhenNotPaused returns (uint256 amount) {
(uint256 value, uint256 timestamp) = validatePendingWithdrawalRequest(
beneficiary,
localPendingWithdrawalIndex,
Expand Down Expand Up @@ -544,7 +554,7 @@ contract Account is UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Managed, I
uint256 yesVotes,
uint256 noVotes,
uint256 abstainVotes
) external onlyManager {
) external onlyManager onlyWhenNotPaused {
bool voteResult = getGovernance().votePartially(
proposalId,
index,
Expand Down Expand Up @@ -697,7 +707,7 @@ contract Account is UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Managed, I
uint256
)
{
return (1, 2, 0, 0);
return (1, 2, 1, 0);
}

/**
Expand Down Expand Up @@ -728,7 +738,7 @@ contract Account is UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Managed, I
address lesserAfterActiveRevoke,
address greaterAfterActiveRevoke,
uint256 index
) public {
) public onlyWhenNotPaused {
(, uint256 revokeAmount) = getAndUpdateToVoteAndToRevoke(group, 0, 0);

if (revokeAmount == 0) {
Expand Down
19 changes: 14 additions & 5 deletions contracts/DefaultStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ import "./interfaces/IGroupHealth.sol";
import "./interfaces/IManager.sol";
import "./interfaces/ISpecificGroupStrategy.sol";
import "./Managed.sol";
import "./Pausable.sol";

/**
* @title DefaultStrategy is responsible for handling any deposit/withdrawal
* for accounts without any specific strategy.
*/
contract DefaultStrategy is UUPSOwnableUpgradeable, Managed {
contract DefaultStrategy is UUPSOwnableUpgradeable, Managed, Pausable {
using EnumerableSet for EnumerableSet.AddressSet;
using AddressSortedLinkedList for SortedLinkedList.List;

Expand Down Expand Up @@ -218,6 +219,14 @@ contract DefaultStrategy is UUPSOwnableUpgradeable, Managed {
emit SortedFlagUpdated(sorted);
}

/**
* @notice Sets that address permissioned to pause/unpause this contract.
* @param _pauser The address that can pause/unpause this contract.
*/
function setPauser(address _pauser) external onlyOwner {
_setPauser(_pauser);
}

/**
* @notice Set this contract's dependencies in the StakedCelo system.
* @param _account The address of the Account contract.
Expand Down Expand Up @@ -285,7 +294,7 @@ contract DefaultStrategy is UUPSOwnableUpgradeable, Managed {
address group,
address lesserKey,
address greaterKey
) external {
) external onlyWhenNotPaused {
if (!unsortedGroups.contains(group)) {
revert NotUnsortedGroup();
}
Expand Down Expand Up @@ -347,7 +356,7 @@ contract DefaultStrategy is UUPSOwnableUpgradeable, Managed {
* @param fromGroup The from group.
* @param toGroup The to group.
*/
function rebalance(address fromGroup, address toGroup) external {
function rebalance(address fromGroup, address toGroup) external onlyWhenNotPaused {
if (!activeGroups.contains(fromGroup)) {
revert InvalidFromGroup(fromGroup);
}
Expand Down Expand Up @@ -461,7 +470,7 @@ contract DefaultStrategy is UUPSOwnableUpgradeable, Managed {
* @notice Deactivates an unhealthy group.
* @param group The group to deactivate if unhealthy.
*/
function deactivateUnhealthyGroup(address group) external {
function deactivateUnhealthyGroup(address group) external onlyWhenNotPaused {
if (groupHealth.isGroupValid(group)) {
revert HealthyGroup(group);
}
Expand Down Expand Up @@ -552,7 +561,7 @@ contract DefaultStrategy is UUPSOwnableUpgradeable, Managed {
uint256
)
{
return (1, 1, 0, 0);
return (1, 1, 1, 0);
}

/**
Expand Down
20 changes: 16 additions & 4 deletions contracts/GroupHealth.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

import "./common/UsingRegistryUpgradeable.sol";
import "./common/UUPSOwnableUpgradeable.sol";
import "./Pausable.sol";

/**
* @title GroupHealth stores and updates info about validator group health.
*/
contract GroupHealth is UUPSOwnableUpgradeable, UsingRegistryUpgradeable {
contract GroupHealth is UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Pausable {
using EnumerableSet for EnumerableSet.AddressSet;

/**
Expand Down Expand Up @@ -59,6 +60,14 @@ contract GroupHealth is UUPSOwnableUpgradeable, UsingRegistryUpgradeable {
__UsingRegistry_init(_registry);
}

/**
* @notice Sets that address permissioned to pause/unpause this contract.
* @param _pauser The address that can pause/unpause this contract.
*/
function setPauser(address _pauser) external onlyOwner {
_setPauser(_pauser);
}

/**
* @notice Returns the storage, major, minor, and patch version of the contract.
* @return Storage version of the contract.
Expand All @@ -76,14 +85,14 @@ contract GroupHealth is UUPSOwnableUpgradeable, UsingRegistryUpgradeable {
uint256
)
{
return (1, 1, 0, 1);
return (1, 1, 1, 0);
}

/**
* @notice Updates validator group health.
* @param group The group address.
*/
function updateGroupHealth(address group) public {
function updateGroupHealth(address group) public onlyWhenNotPaused {
IValidators validators = getValidators();

(bool valid, address[] memory members) = _isGroupPartiallyValid(validators, group);
Expand All @@ -104,7 +113,10 @@ contract GroupHealth is UUPSOwnableUpgradeable, UsingRegistryUpgradeable {
* This array needs to have same length as all (even not elected) members of validator group.
* Index of not elected member can be any uint256 number.
*/
function markGroupHealthy(address group, uint256[] calldata membersElectedIndex) public {
function markGroupHealthy(address group, uint256[] calldata membersElectedIndex)
public
onlyWhenNotPaused
{
if (isGroupValid[group] == true) {
revert GroupHealthy(group);
}
Expand Down
28 changes: 19 additions & 9 deletions contracts/Manager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ import "./interfaces/IVote.sol";
import "./interfaces/IGroupHealth.sol";
import "./interfaces/ISpecificGroupStrategy.sol";
import "./interfaces/IDefaultStrategy.sol";
import "./Pausable.sol";

/**
* @title Manages the StakedCelo system, by controlling the minting and burning
* of stCELO and implementing strategies for voting and unvoting of deposited or
* withdrawn CELO.
*/
contract Manager is UUPSOwnableUpgradeable, UsingRegistryUpgradeable {
contract Manager is UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Pausable {
using EnumerableSet for EnumerableSet.AddressSet;

/**
Expand Down Expand Up @@ -223,6 +224,14 @@ contract Manager is UUPSOwnableUpgradeable, UsingRegistryUpgradeable {
emit VoteContractSet(_vote);
}

/**
* @notice Sets that address permissioned to pause/unpause this contract.
* @param _pauser The address that can pause/unpause this contract.
*/
function setPauser(address _pauser) external onlyOwner {
_setPauser(_pauser);
}

/**
* @notice Used to withdraw CELO from the system, in exchange for burning
* stCELO.
Expand All @@ -233,7 +242,7 @@ contract Manager is UUPSOwnableUpgradeable, UsingRegistryUpgradeable {
* @dev The funds need to be withdrawn using calls to `Account.withdraw` and
* `Account.finishPendingWithdrawal`.
*/
function withdraw(uint256 stCeloAmount) external {
function withdraw(uint256 stCeloAmount) external onlyWhenNotPaused {
(
address[] memory groupsWithdrawn,
uint256[] memory withdrawalsPerGroup
Expand All @@ -248,7 +257,7 @@ contract Manager is UUPSOwnableUpgradeable, UsingRegistryUpgradeable {
* @param proposalId The ID of the proposal to revoke from.
* @param index The index of the proposal ID in `dequeued`.
*/
function revokeVotes(uint256 proposalId, uint256 index) external {
function revokeVotes(uint256 proposalId, uint256 index) external onlyWhenNotPaused {
IVote vote = IVote(voteContract);

(uint256 totalYesVotes, uint256 totalNoVotes, uint256 totalAbstainVotes) = vote.revokeVotes(
Expand All @@ -265,6 +274,7 @@ contract Manager is UUPSOwnableUpgradeable, UsingRegistryUpgradeable {
*/
function updateHistoryAndReturnLockedStCeloInVoting(address beneficiary)
external
onlyWhenNotPaused
returns (uint256)
{
IVote vote = IVote(voteContract);
Expand All @@ -277,7 +287,7 @@ contract Manager is UUPSOwnableUpgradeable, UsingRegistryUpgradeable {
* will be scheduled to be voted for with the Account contract.
* The CELO will be distributed based on address strategy.
*/
function deposit() external payable {
function deposit() external payable onlyWhenNotPaused {
uint256 stCeloAmount = toStakedCelo(msg.value);
(address[] memory finalGroups, uint256[] memory finalVotes) = distributeVotes(
msg.value,
Expand Down Expand Up @@ -327,7 +337,7 @@ contract Manager is UUPSOwnableUpgradeable, UsingRegistryUpgradeable {
uint256
)
{
return (1, 3, 0, 0);
return (1, 3, 1, 0);
}

/**
Expand All @@ -351,7 +361,7 @@ contract Manager is UUPSOwnableUpgradeable, UsingRegistryUpgradeable {
* !address(0) = voting for allowed validator group. Group needs to be in allowed
* @param newStrategy The from account.
*/
function changeStrategy(address newStrategy) public {
function changeStrategy(address newStrategy) public onlyWhenNotPaused {
if (
newStrategy != address(0) &&
(specificGroupStrategy.isBlockedGroup(newStrategy) ||
Expand Down Expand Up @@ -384,7 +394,7 @@ contract Manager is UUPSOwnableUpgradeable, UsingRegistryUpgradeable {
* @param fromGroup The from group.
* @param toGroup The to group.
*/
function rebalance(address fromGroup, address toGroup) public {
function rebalance(address fromGroup, address toGroup) public onlyWhenNotPaused {
if (!defaultStrategy.isActive(toGroup) && specificGroupStrategy.isBlockedGroup(toGroup)) {
// rebalancing to deactivated/non-existent group is not allowed
revert InvalidToGroup(toGroup);
Expand Down Expand Up @@ -427,7 +437,7 @@ contract Manager is UUPSOwnableUpgradeable, UsingRegistryUpgradeable {
* @param fromGroup The group to unschedule votes from.
* @param toGroup The group to schedule votes to.
*/
function rebalanceOverflow(address fromGroup, address toGroup) public {
function rebalanceOverflow(address fromGroup, address toGroup) public onlyWhenNotPaused {
if (!defaultStrategy.isActive(toGroup)) {
revert InvalidToGroup(toGroup);
}
Expand Down Expand Up @@ -491,7 +501,7 @@ contract Manager is UUPSOwnableUpgradeable, UsingRegistryUpgradeable {
uint256 yesVotes,
uint256 noVotes,
uint256 abstainVotes
) public {
) public onlyWhenNotPaused {
IVote vote = IVote(voteContract);

(
Expand Down
Loading
Loading