-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathDssLitePsmMom.sol
136 lines (119 loc) · 4.19 KB
/
DssLitePsmMom.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// SPDX-FileCopyrightText: © 2023 Dai Foundation <www.daifoundation.org>
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
pragma solidity ^0.8.16;
interface DssLitePsmLike {
function file(bytes32, uint256) external;
function HALTED() external view returns (uint256);
}
interface AuthorityLike {
function canCall(address, address, bytes4) external view returns (bool);
}
/**
* @title A mom for `DssLitePsm` instances.
* @notice Bypass governance delay to halt selling or buying gems in a `DssLitePsm` instance.
*/
contract DssLitePsmMom {
enum Flow {
SELL, // Only selling gems
BUY, // Only buying gems
BOTH // Both at the same time
}
/// @notice The owner of this contract.
address public owner;
/// @notice The authority to delegate authentication to.
address public authority;
/**
* @notice The owner of this contract was set.
* @param _owner The new owner.
*/
event SetOwner(address indexed _owner);
/**
* @notice The authority of this contract was set.
* @param _authority The new authority.
*/
event SetAuthority(address indexed _authority);
/**
* @notice A PSM inflow or outflow was halted.
* @param psm The PSM address.
* @param what The halted flow. ["tin", "tout"].
*/
event Halt(address indexed psm, Flow indexed what);
modifier onlyOwner() {
require(msg.sender == owner, "DssLitePsmMom/not-owner");
_;
}
modifier auth() {
require(isAuthorized(msg.sender, msg.sig), "DssLitePsmMom/not-authorized");
_;
}
/**
* @notice Returns whether or not the function identified by `sig` can be called by `src`.
* @param src The caller address.
* @param sig The selector of the function being called.
*/
function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
if (src == address(this)) {
return true;
} else if (src == owner) {
return true;
} else if (authority == address(0)) {
return false;
} else {
return AuthorityLike(authority).canCall(src, address(this), sig);
}
}
constructor() {
owner = msg.sender;
emit SetOwner(msg.sender);
}
/*//////////////////////////////////
Governance actions with delay
//////////////////////////////////*/
/**
* @notice Sets a new owner for this contract;
* @param owner_ The new owner address.
*/
function setOwner(address owner_) external onlyOwner {
owner = owner_;
emit SetOwner(owner_);
}
/**
* @notice Sets a new authority for this contract;
* @param authority_ The new authority address.
*/
function setAuthority(address authority_) external onlyOwner {
authority = authority_;
emit SetAuthority(authority_);
}
/*//////////////////////////////////
Governance actions without delay
//////////////////////////////////*/
/**
* @notice Halts either inflow or outflow of gems from the PSM.
* @param psm The PSM address.
* @param what The halted flow. [0 = sell gems, 1 = buy gems, 2 = both]
*/
function halt(address psm, Flow what) external auth {
uint256 halted = DssLitePsmLike(psm).HALTED();
if (what == Flow.SELL || what == Flow.BOTH) {
DssLitePsmLike(psm).file("tin", halted);
}
if (what == Flow.BUY || what == Flow.BOTH) {
DssLitePsmLike(psm).file("tout", halted);
}
emit Halt(psm, what);
}
}