Skip to content

Commit 92f7d8b

Browse files
authored
Merge pull request #6 from TSxo/pause
feat: Pause
2 parents 7766d2f + 8c77ef6 commit 92f7d8b

23 files changed

Lines changed: 1070 additions & 198 deletions

README.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,33 @@ The smart contracts are located in the `src` directory.
1313
.
1414
├── auth
1515
│   ├── IOwned.sol
16-
│   ├── Owned.sol
17-
│   ── managed
18-
│   ├── AuthManaged.sol
19-
│   ├── AuthManager.sol
20-
│   ├── IAuthManaged.sol
21-
│   ── IAuthManager.sol
22-
│   └── IAuthority.sol
16+
│   ├── managed
17+
│   │   ├── AuthManaged.sol
18+
│   │   ├── AuthManager.sol
19+
│   │   ├── IAuthManaged.sol
20+
│   │   ├── IAuthManager.sol
21+
│   │   └── IAuthority.sol
22+
│   └── Owned.sol
2323
├── mixins
2424
│   ├── CallContext.sol
2525
│   └── Mutex.sol
26+
├── pause
27+
│   ├── IPausable.sol
28+
│   ├── managed
29+
│   │   ├── IPauseAuthority.sol
30+
│   │   ├── IPauseManaged.sol
31+
│   │   ├── IPauseManager.sol
32+
│   │   ├── PauseManaged.sol
33+
│   │   └── PauseManager.sol
34+
│   └── Pausable.sol
2635
└── proxy
2736
├── ERC1967
2837
│   └── ERC1967Logic.sol
2938
├── Proxy.sol
3039
└── UUPS
3140
├── UUPSImplementation.sol
3241
└── UUPSProxy.sol
42+
3343
```
3444

3545
## Purpose & License

src/auth/managed/AuthManaged.sol

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ abstract contract AuthManaged is IAuthManaged {
6060
// State
6161

6262
/// @dev keccak256(abi.encode(uint256(keccak256("libsol.storage.AuthManaged")) - 1)) & ~bytes32(uint256(0xff))
63-
bytes32 private constant MANAGED_SLOT = 0xba07b3ca0f769fbcf052f5eef32e58c07f3aeeec01c8167517b7043932526600;
63+
bytes32 private constant AUTH_MANAGED_SLOT = 0xba07b3ca0f769fbcf052f5eef32e58c07f3aeeec01c8167517b7043932526600;
6464

6565
/// @dev keccak256(bytes("AuthorityUpdated(address,address)"))
6666
bytes32 private constant AUTHORITY_UPDATED = 0xa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b76389980198;
@@ -106,7 +106,7 @@ abstract contract AuthManaged is IAuthManaged {
106106
/// @inheritdoc IAuthManaged
107107
function setAuthority(address newAuthority) public virtual {
108108
assembly ("memory-safe") {
109-
if iszero(eq(caller(), sload(MANAGED_SLOT))) {
109+
if iszero(eq(caller(), sload(AUTH_MANAGED_SLOT))) {
110110
mstore(0x00, 0x3583568e) // `AuthManaged__Unauthorized()`
111111
revert(0x1c, 0x04)
112112
}
@@ -118,7 +118,7 @@ abstract contract AuthManaged is IAuthManaged {
118118
/// @inheritdoc IAuthManaged
119119
function authority() public view virtual returns (address result) {
120120
assembly ("memory-safe") {
121-
result := sload(MANAGED_SLOT)
121+
result := sload(AUTH_MANAGED_SLOT)
122122
}
123123
}
124124

@@ -135,8 +135,8 @@ abstract contract AuthManaged is IAuthManaged {
135135
/// Emits an `AuthorityUpdated` event.
136136
function _setAuthority(address newAuthority) internal virtual {
137137
assembly ("memory-safe") {
138-
log3(0x00, 0x00, AUTHORITY_UPDATED, sload(MANAGED_SLOT), newAuthority)
139-
sstore(MANAGED_SLOT, newAuthority)
138+
log3(0x00, 0x00, AUTHORITY_UPDATED, sload(AUTH_MANAGED_SLOT), newAuthority)
139+
sstore(AUTH_MANAGED_SLOT, newAuthority)
140140
}
141141
}
142142

@@ -148,7 +148,7 @@ abstract contract AuthManaged is IAuthManaged {
148148
function _assertAuthorized(address user, bytes4 selector) internal view virtual {
149149
assembly ("memory-safe") {
150150
let ptr := mload(0x40)
151-
let manager := sload(MANAGED_SLOT)
151+
let manager := sload(AUTH_MANAGED_SLOT)
152152

153153
mstore(ptr, CAN_CALL)
154154
mstore(add(ptr, 0x04), user)

src/auth/managed/AuthManager.sol

Lines changed: 16 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,14 @@ import { IAuthority } from "./IAuthority.sol";
4242
/// users with at least one role matching the allowed roles (bits 0 to 253) in
4343
/// the function’s bitmask.
4444
///
45-
/// # Pausing
46-
///
47-
/// Target contracts can be paused. When paused, all functions with the `auth`
48-
/// modifier on that contract are blocked. Note, unmanaged functions (those
49-
/// without the `auth` modifier) remain callable.
50-
///
5145
/// # Owner
5246
///
5347
/// All the permissions managed by this system can be modified by the owner of
5448
/// this instance. It is expected that this account will be highly secured.
5549
///
56-
/// To determine the owner, this contract performs a self-staticcall to the
57-
/// `owner()` function - meaning any ERC-173 compliant contract is suitable.
50+
/// To determine the owner, this contract performs a staticcall to its own
51+
/// `owner()` function. This allows compatibility with any contract that adheres
52+
/// to the ERC-173 ownership standard.
5853
///
5954
/// # Upgrade Compatible
6055
///
@@ -69,32 +64,28 @@ import { IAuthority } from "./IAuthority.sol";
6964
/// - Solady.
7065
///
7166
/// Thank you.
72-
contract AuthManager is IAuthority, IAuthManager {
67+
abstract contract AuthManager is IAuthManager, IAuthority {
7368
// -------------------------------------------------------------------------
7469
// Type Declarations
7570

7671
/// @custom:storage-location erc7201:libsol.storage.AuthManager
7772
struct AuthManagerStorage {
7873
mapping(address => uint256) userRoles;
7974
mapping(address => mapping(bytes4 => uint256)) access;
80-
mapping(address => bool) paused;
8175
}
8276

8377
// -------------------------------------------------------------------------
8478
// State
8579

8680
/// @dev keccak256(abi.encode(uint256(keccak256("libsol.storage.AuthManager")) - 1)) & ~bytes32(uint256(0xff))
87-
bytes32 private constant MANAGER_SLOT = 0x938700b07e50a0d76711cd0ee77205e6b6a2709fd62fa43819e05a1a4baac400;
81+
bytes32 private constant AUTH_MANAGER_SLOT = 0x938700b07e50a0d76711cd0ee77205e6b6a2709fd62fa43819e05a1a4baac400;
8882

8983
/// @dev keccak256(bytes("UserRoleUpdated(address,uint8,bool)"))
9084
bytes32 private constant USER_ROLE_UPDATED = 0x4c9bdd0c8e073eb5eda2250b18d8e5121ff27b62064fbeeeed4869bb99bc5bf2;
9185

9286
/// @dev keccak256(bytes("AccessUpdated(address,bytes4,uint8,bool)"))
9387
bytes32 private constant ACCESS_UPDATED = 0xdb20781f7ac6b1c66139899bc76388269b478dbb402af50576a4c997b473d564;
9488

95-
/// @dev keccak256(bytes("Paused(address,bool)"))
96-
bytes32 private constant PAUSED = 0xe8699cf681560fd07de85543bd994263f4557bdc5179dd702f256d15fd083e1d;
97-
9889
/// @dev keccak256(bytes("AuthorityUpdated(address,address)"))
9990
bytes32 private constant AUTHORITY_UPDATED = 0xa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b76389980198;
10091

@@ -145,22 +136,6 @@ contract AuthManager is IAuthority, IAuthManager {
145136
_setAccess(target, selector, role, enabled);
146137
}
147138

148-
/// @inheritdoc IAuthManager
149-
function setPaused(address target, bool enabled) public virtual {
150-
_assertAuthManagerOwner();
151-
152-
assembly ("memory-safe") {
153-
mstore(0x00, target)
154-
mstore(0x20, add(MANAGER_SLOT, 2))
155-
let slot := keccak256(0x00, 0x40)
156-
157-
sstore(slot, enabled)
158-
159-
mstore(0x00, enabled)
160-
log2(0x00, 0x20, PAUSED, target)
161-
}
162-
}
163-
164139
/// @inheritdoc IAuthority
165140
function setAuthority(address target, address newAuthority) public virtual {
166141
_assertAuthManagerOwner();
@@ -181,24 +156,14 @@ contract AuthManager is IAuthority, IAuthManager {
181156
/// @inheritdoc IAuthority
182157
function canCall(address user, address target, bytes4 selector) public view virtual returns (bool result) {
183158
assembly ("memory-safe") {
184-
// Check whether the target contract is paused.
185-
mstore(0x00, target)
186-
mstore(0x20, add(MANAGER_SLOT, 2))
187-
let slot := keccak256(0x00, 0x40)
188-
189-
if sload(slot) {
190-
mstore(0x00, 0x00)
191-
return(0x00, 0x20)
192-
}
193-
194159
// Retrieve the target function's access rules.
195160
mstore(0x00, target)
196-
mstore(0x20, add(MANAGER_SLOT, 1))
161+
mstore(0x20, add(AUTH_MANAGER_SLOT, 1))
197162
let innerSlot := keccak256(0x00, 0x40)
198163

199164
mstore(0x00, selector)
200165
mstore(0x20, innerSlot)
201-
slot := keccak256(0x00, 0x40)
166+
let slot := keccak256(0x00, 0x40)
202167

203168
let accessMask := sload(slot)
204169

@@ -219,7 +184,7 @@ contract AuthManager is IAuthority, IAuthManager {
219184

220185
// Retrieve the user's active roles.
221186
mstore(0x00, user)
222-
mstore(0x20, MANAGER_SLOT)
187+
mstore(0x20, AUTH_MANAGER_SLOT)
223188
slot := keccak256(0x00, 0x40)
224189

225190
let roles := sload(slot)
@@ -233,7 +198,7 @@ contract AuthManager is IAuthority, IAuthManager {
233198
function userRoles(address user) public view virtual returns (uint256 result) {
234199
assembly ("memory-safe") {
235200
mstore(0x00, user)
236-
mstore(0x20, MANAGER_SLOT)
201+
mstore(0x20, AUTH_MANAGER_SLOT)
237202
let slot := keccak256(0x00, 0x40)
238203

239204
result := sload(slot)
@@ -244,7 +209,7 @@ contract AuthManager is IAuthority, IAuthManager {
244209
function hasRole(address user, uint8 role) public view virtual returns (bool result) {
245210
assembly ("memory-safe") {
246211
mstore(0x00, user)
247-
mstore(0x20, MANAGER_SLOT)
212+
mstore(0x20, AUTH_MANAGER_SLOT)
248213
let slot := keccak256(0x00, 0x40)
249214

250215
result := iszero(iszero(and(sload(slot), shl(role, 1))))
@@ -255,7 +220,7 @@ contract AuthManager is IAuthority, IAuthManager {
255220
function functionAccess(address target, bytes4 selector) public view virtual returns (uint256 result) {
256221
assembly ("memory-safe") {
257222
mstore(0x00, target)
258-
mstore(0x20, add(MANAGER_SLOT, 1))
223+
mstore(0x20, add(AUTH_MANAGER_SLOT, 1))
259224
let innerSlot := keccak256(0x00, 0x40)
260225

261226
mstore(0x00, selector)
@@ -268,7 +233,7 @@ contract AuthManager is IAuthority, IAuthManager {
268233
function roleHasAccess(address target, bytes4 selector, uint8 role) public view virtual returns (bool result) {
269234
assembly ("memory-safe") {
270235
mstore(0x00, target)
271-
mstore(0x20, add(MANAGER_SLOT, 1))
236+
mstore(0x20, add(AUTH_MANAGER_SLOT, 1))
272237
let innerSlot := keccak256(0x00, 0x40)
273238

274239
mstore(0x00, selector)
@@ -284,7 +249,7 @@ contract AuthManager is IAuthority, IAuthManager {
284249
function isFunctionClosed(address target, bytes4 selector) public view virtual returns (bool result) {
285250
assembly ("memory-safe") {
286251
mstore(0x00, target)
287-
mstore(0x20, add(MANAGER_SLOT, 1))
252+
mstore(0x20, add(AUTH_MANAGER_SLOT, 1))
288253
let innerSlot := keccak256(0x00, 0x40)
289254

290255
mstore(0x00, selector)
@@ -300,7 +265,7 @@ contract AuthManager is IAuthority, IAuthManager {
300265
function isFunctionPublic(address target, bytes4 selector) public view virtual returns (bool result) {
301266
assembly ("memory-safe") {
302267
mstore(0x00, target)
303-
mstore(0x20, add(MANAGER_SLOT, 1))
268+
mstore(0x20, add(AUTH_MANAGER_SLOT, 1))
304269
let innerSlot := keccak256(0x00, 0x40)
305270

306271
mstore(0x00, selector)
@@ -312,15 +277,6 @@ contract AuthManager is IAuthority, IAuthManager {
312277
}
313278
}
314279

315-
/// @inheritdoc IAuthManager
316-
function isPaused(address target) public view virtual returns (bool result) {
317-
assembly ("memory-safe") {
318-
mstore(0x00, target)
319-
mstore(0x20, add(MANAGER_SLOT, 2))
320-
result := sload(keccak256(0x00, 0x40))
321-
}
322-
}
323-
324280
// -------------------------------------------------------------------------
325281
// Functions - Internal
326282

@@ -337,7 +293,7 @@ contract AuthManager is IAuthority, IAuthManager {
337293
function _setUserRole(address user, uint8 role, bool enabled) internal virtual {
338294
assembly ("memory-safe") {
339295
mstore(0x00, user)
340-
mstore(0x20, MANAGER_SLOT)
296+
mstore(0x20, AUTH_MANAGER_SLOT)
341297
let slot := keccak256(0x00, 0x40)
342298

343299
switch enabled
@@ -363,7 +319,7 @@ contract AuthManager is IAuthority, IAuthManager {
363319
function _setAccess(address target, bytes4 selector, uint8 shift, bool enabled) internal virtual {
364320
assembly ("memory-safe") {
365321
mstore(0x00, target)
366-
mstore(0x20, add(MANAGER_SLOT, 1))
322+
mstore(0x20, add(AUTH_MANAGER_SLOT, 1))
367323
let innerSlot := keccak256(0x00, 0x40)
368324

369325
mstore(0x00, selector)

src/auth/managed/IAuthManaged.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ interface IAuthManaged {
3232
///
3333
/// @dev Requirements:
3434
/// - Only callable by the current Authority.
35+
///
36+
/// Emits an `AuthorityUpdated` event.
3537
function setAuthority(address newAuthority) external;
3638

3739
/// @notice Returns the current Authority.

src/auth/managed/IAuthManager.sol

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,11 @@ interface IAuthManager {
2626
/// @param enabled Whether the role was enabled.
2727
event AccessUpdated(address indexed target, bytes4 indexed selector, uint8 indexed role, bool enabled);
2828

29-
/// @notice Emitted when a target contract's paused status has been updated.
30-
///
31-
/// @param target The target contract.
32-
/// @param enabled Whether the target contract has been paused.
33-
event Paused(address indexed target, bool enabled);
34-
35-
/// @notice Emitted when a target contract's Authority is updated.
36-
///
37-
/// @param target The target contract.
38-
/// @param newAuthority The address of the new Authority.
39-
event AuthorityUpdated(address indexed target, address indexed newAuthority);
40-
4129
// -------------------------------------------------------------------------
4230
// Errors
4331

44-
/// @notice Raised when a caller does not have permission to invoke a
45-
/// target function.
32+
/// @notice Raised when a caller does not have permission to invoke a target
33+
/// function.
4634
error AuthManager__Unauthorized();
4735

4836
/// @notice Raised when attempting to set an invalid role.
@@ -102,17 +90,6 @@ interface IAuthManager {
10290
/// Emits an `AccessUpdated` event.
10391
function setRoleAccess(address target, bytes4 selector, uint8 role, bool enabled) external;
10492

105-
/// @notice Pauses or unpauses a target contract.
106-
///
107-
/// @param target The address of the target contract.
108-
/// @param enabled True to pause the contract, false to unpause it.
109-
///
110-
/// @dev Requirements:
111-
/// - Only callable by the owner.
112-
///
113-
/// Emits a `Paused` event.
114-
function setPaused(address target, bool enabled) external;
115-
11693
/// @notice Retrieves the role bitmask for a user.
11794
///
11895
/// @param user The address of the user.
@@ -165,11 +142,4 @@ interface IAuthManager {
165142
///
166143
/// @return result True if the function is public, false otherwise.
167144
function isFunctionPublic(address target, bytes4 selector) external view returns (bool result);
168-
169-
/// @notice Checks whether a target contract is paused.
170-
///
171-
/// @param target The address of the target contract.
172-
///
173-
/// @return result True if the target contract is paused, false otherwise.
174-
function isPaused(address target) external view returns (bool result);
175145
}

src/auth/managed/IAuthority.sol

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,20 @@ pragma solidity ^0.8.20;
66
///
77
/// @author TSxo
88
///
9-
/// @notice Interface for permissioning.
9+
/// @notice Defines the core functions required of an Authority.
1010
interface IAuthority {
11+
// -------------------------------------------------------------------------
12+
// Events
13+
14+
/// @notice Emitted when a target contract's Authority is updated.
15+
///
16+
/// @param target The target contract.
17+
/// @param newAuthority The address of the new Authority.
18+
event AuthorityUpdated(address indexed target, address indexed newAuthority);
19+
20+
// -------------------------------------------------------------------------
21+
// Functions
22+
1123
/// @notice Checks whether a caller is allowed to invoke a specific function
1224
/// on a target contract.
1325
///

0 commit comments

Comments
 (0)