@@ -8,17 +8,32 @@ pragma solidity 0.5.17;
88contract Registry {
99 enum ContractStatus {New, Approved, Disabled}
1010
11- // Governance role is to enable recovery from key compromise by rekeying other roles.
11+ // Governance role is to enable recovery from key compromise by rekeying
12+ // other roles. Also, it can disable operator contract panic buttons
13+ // permanently.
1214 address internal governance;
1315
1416 // Registry Keeper maintains approved operator contracts. Each operator
1517 // contract must be approved before it can be authorized by a staker or
1618 // used by a service contract.
1719 address internal registryKeeper;
1820
19- // The Panic Button can disable malicious or malfunctioning contracts
20- // that have been previously approved by the Registry Keeper.
21- address internal panicButton;
21+ // Each operator contract has a Panic Button which can disable malicious
22+ // or malfunctioning contract that have been previously approved by the
23+ // Registry Keeper.
24+ //
25+ // New operator contract added to the registry has a default panic button
26+ // value assigned (defaultPanicButton). Panic button for each operator
27+ // contract can be later updated by Governance to individual value.
28+ //
29+ // It is possible to disable panic button for individual contract by
30+ // setting the panic button to zero address. In such case, operator contract
31+ // can not be disabled and is permanently approved in the registry.
32+ mapping (address => address ) public panicButtons;
33+
34+ // Default panic button for each new operator contract added to the
35+ // registry. Can be later updated for each contract.
36+ address internal defaultPanicButton;
2237
2338 // Each service contract has a Operator Contract Upgrader whose purpose
2439 // is to manage operator contracts for that specific service contract.
@@ -34,7 +49,12 @@ contract Registry {
3449
3550 event GovernanceUpdated ();
3651 event RegistryKeeperUpdated ();
37- event PanicButtonUpdated ();
52+ event DefaultPanicButtonUpdated ();
53+ event OperatorContractPanicButtonDisabled (address operatorContract );
54+ event OperatorContractPanicButtonUpdated (
55+ address operatorContract ,
56+ address panicButton
57+ );
3858 event OperatorContractUpgraderUpdated (
3959 address serviceContract ,
4060 address upgrader
@@ -50,15 +70,33 @@ contract Registry {
5070 _;
5171 }
5272
53- modifier onlyPanicButton () {
73+ modifier onlyPanicButton (address _operatorContract ) {
74+ address panicButton = panicButtons[_operatorContract];
75+ require (panicButton != address (0 ), "Panic button disabled " );
5476 require (panicButton == msg .sender , "Not authorized " );
5577 _;
5678 }
5779
80+ modifier onlyForNewContract (address _operatorContract ) {
81+ require (
82+ isNewOperatorContract (_operatorContract),
83+ "Not a new operator contract "
84+ );
85+ _;
86+ }
87+
88+ modifier onlyForApprovedContract (address _operatorContract ) {
89+ require (
90+ isApprovedOperatorContract (_operatorContract),
91+ "Not an approved operator contract "
92+ );
93+ _;
94+ }
95+
5896 constructor () public {
5997 governance = msg .sender ;
6098 registryKeeper = msg .sender ;
61- panicButton = msg .sender ;
99+ defaultPanicButton = msg .sender ;
62100 }
63101
64102 function setGovernance (address _governance ) public onlyGovernance {
@@ -71,9 +109,45 @@ contract Registry {
71109 emit RegistryKeeperUpdated ();
72110 }
73111
74- function setPanicButton (address _panicButton ) public onlyGovernance {
75- panicButton = _panicButton;
76- emit PanicButtonUpdated ();
112+ function setDefaultPanicButton (address _panicButton ) public onlyGovernance {
113+ defaultPanicButton = _panicButton;
114+ emit DefaultPanicButtonUpdated ();
115+ }
116+
117+ function setOperatorContractPanicButton (
118+ address _operatorContract ,
119+ address _panicButton
120+ ) public onlyForApprovedContract (_operatorContract) onlyGovernance {
121+ require (
122+ panicButtons[_operatorContract] != address (0 ),
123+ "Disabled panic button cannot be updated "
124+ );
125+ require (
126+ _panicButton != address (0 ),
127+ "Panic button must be non-zero address "
128+ );
129+
130+ panicButtons[_operatorContract] = _panicButton;
131+
132+ emit OperatorContractPanicButtonUpdated (
133+ _operatorContract,
134+ _panicButton
135+ );
136+ }
137+
138+ function disableOperatorContractPanicButton (address _operatorContract )
139+ public
140+ onlyForApprovedContract (_operatorContract)
141+ onlyGovernance
142+ {
143+ require (
144+ panicButtons[_operatorContract] != address (0 ),
145+ "Panic button already disabled "
146+ );
147+
148+ panicButtons[_operatorContract] = address (0 );
149+
150+ emit OperatorContractPanicButtonDisabled (_operatorContract);
77151 }
78152
79153 function setOperatorContractUpgrader (
@@ -89,26 +163,19 @@ contract Registry {
89163
90164 function approveOperatorContract (address operatorContract )
91165 public
166+ onlyForNewContract (operatorContract)
92167 onlyRegistryKeeper
93168 {
94- require (
95- isNewOperatorContract (operatorContract),
96- "Only new operator contracts can be approved "
97- );
98-
99169 operatorContracts[operatorContract] = ContractStatus.Approved;
170+ panicButtons[operatorContract] = defaultPanicButton;
100171 emit OperatorContractApproved (operatorContract);
101172 }
102173
103174 function disableOperatorContract (address operatorContract )
104175 public
105- onlyPanicButton
176+ onlyForApprovedContract (operatorContract)
177+ onlyPanicButton (operatorContract)
106178 {
107- require (
108- isApprovedOperatorContract (operatorContract),
109- "Only approved operator contracts can be disabled "
110- );
111-
112179 operatorContracts[operatorContract] = ContractStatus.Disabled;
113180 emit OperatorContractDisabled (operatorContract);
114181 }
0 commit comments