-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathMultisigManager.sol
113 lines (95 loc) · 4.21 KB
/
MultisigManager.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.17;
import "./Base.sol";
import {Storage} from "./Storage.sol";
/*
Data Storage Schema
multisig.count = Starts at 0 and counts up by 1 after an addr is added.
multisig.index<address> = <index> + 1 of multisigAddress
multisig.item<index>.address = C-chain address used as primary key
multisig.item<index>.enabled = bool
*/
/// @title Multisig address creation and management for the protocol
contract MultisigManager is Base {
error MultisigAlreadyRegistered();
error MultisigNotFound();
error MultisigLimitReached();
error NoEnabledMultisigFound();
event DisabledMultisig(address indexed multisig, address actor);
event EnabledMultisig(address indexed multisig, address actor);
event RegisteredMultisig(address indexed multisig, address actor);
uint256 public constant MULTISIG_LIMIT = 10;
constructor(Storage storageAddress) Base(storageAddress) {
version = 1;
}
/// @notice Register a multisig. Defaults to disabled when first registered.
/// @param addr Address of the multisig that is being registered
function registerMultisig(address addr) external onlyGuardian {
int256 multisigIndex = getIndexOf(addr);
if (multisigIndex != -1) {
revert MultisigAlreadyRegistered();
}
uint256 index = getUint(keccak256("multisig.count"));
if (index >= MULTISIG_LIMIT) {
revert MultisigLimitReached();
}
setAddress(keccak256(abi.encodePacked("multisig.item", index, ".address")), addr);
// The index is stored 1 greater than the actual value. The 1 is subtracted in getIndexOf().
setUint(keccak256(abi.encodePacked("multisig.index", addr)), index + 1);
addUint(keccak256("multisig.count"), 1);
emit RegisteredMultisig(addr, msg.sender);
}
/// @notice Enabling a registered multisig
/// @param addr Address of the multisig that is being enabled
function enableMultisig(address addr) external onlyGuardian {
int256 multisigIndex = getIndexOf(addr);
if (multisigIndex == -1) {
revert MultisigNotFound();
}
setBool(keccak256(abi.encodePacked("multisig.item", multisigIndex, ".enabled")), true);
emit EnabledMultisig(addr, msg.sender);
}
/// @notice Disabling a registered multisig
/// @param addr Address of the multisig that is being disabled
/// @dev this will prevent the multisig from completing validations. The minipool will need to be manually reassigned to a new multisig
function disableMultisig(address addr) external guardianOrSpecificRegisteredContract("Ocyticus", msg.sender) {
int256 multisigIndex = getIndexOf(addr);
if (multisigIndex == -1) {
revert MultisigNotFound();
}
setBool(keccak256(abi.encodePacked("multisig.item", multisigIndex, ".enabled")), false);
emit DisabledMultisig(addr, msg.sender);
}
/// @notice Gets the next registered and enabled Multisig, revert if none found
/// @dev There will never be more than 10 total multisigs. If we grow beyond that we will redesign this contract.
function requireNextActiveMultisig() external view returns (address) {
uint256 total = getUint(keccak256("multisig.count"));
address addr;
bool enabled;
for (uint256 i = 0; i < total; i++) {
(addr, enabled) = getMultisig(i);
if (enabled) {
return addr;
}
}
revert NoEnabledMultisigFound();
}
/// @notice The index of a multisig. Returns -1 if the multisig is not found
/// @param addr Address of the multisig that is being searched for
/// @return The index for the given multisig
function getIndexOf(address addr) public view returns (int256) {
return int256(getUint(keccak256(abi.encodePacked("multisig.index", addr)))) - 1;
}
/// @notice Get the total count of the multisigs in the protocol
/// @return Count of all multisigs
function getCount() public view returns (uint256) {
return getUint(keccak256("multisig.count"));
}
/// @notice Gets the multisig information using the multisig's index
/// @param index Index of the multisig
/// @return addr and enabled. The address and the enabled status of the multisig
function getMultisig(uint256 index) public view returns (address addr, bool enabled) {
addr = getAddress(keccak256(abi.encodePacked("multisig.item", index, ".address")));
enabled = (addr != address(0)) && getBool(keccak256(abi.encodePacked("multisig.item", index, ".enabled")));
}
}