Skip to content

Commit c8d3e0f

Browse files
committed
Fix AccessManager rules following #5014
1 parent bc75b11 commit c8d3e0f

File tree

1 file changed

+38
-29
lines changed

1 file changed

+38
-29
lines changed

certora/specs/AccessManager.spec

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -130,24 +130,35 @@ rule getAdminRestrictions(env e, bytes data) {
130130
assert restricted == false;
131131
assert roleId == 0;
132132
assert delay == 0;
133+
} else if (
134+
selector == to_bytes4(sig:labelRole(uint64,string).selector) ||
135+
selector == to_bytes4(sig:setRoleAdmin(uint64,uint64).selector) ||
136+
selector == to_bytes4(sig:setRoleGuardian(uint64,uint64).selector) ||
137+
selector == to_bytes4(sig:setGrantDelay(uint64,uint32).selector) ||
138+
selector == to_bytes4(sig:setTargetAdminDelay(address,uint32).selector)
139+
) {
140+
assert restricted == true;
141+
assert roleId == ADMIN_ROLE();
142+
assert delay == 0;
143+
} else if (
144+
selector == to_bytes4(sig:updateAuthority(address,address).selector) ||
145+
selector == to_bytes4(sig:setTargetClosed(address,bool).selector) ||
146+
selector == to_bytes4(sig:setTargetFunctionRole(address,bytes4[],uint64).selector)
147+
) {
148+
assert restricted == true;
149+
assert roleId == ADMIN_ROLE();
150+
assert delay == getTargetAdminDelay(e, getFirstArgumentAsAddress(data));
151+
} else if (
152+
selector == to_bytes4(sig:grantRole(uint64,address,uint32).selector) ||
153+
selector == to_bytes4(sig:revokeRole(uint64,address).selector)
154+
) {
155+
assert restricted == true;
156+
assert roleId == getRoleAdmin(getFirstArgumentAsUint64(data));
157+
assert delay == 0;
133158
} else {
134-
assert restricted ==
135-
isOnlyAuthorized(selector);
136-
137-
assert roleId == (
138-
(restricted && selector == to_bytes4(sig:grantRole(uint64,address,uint32).selector)) ||
139-
(restricted && selector == to_bytes4(sig:revokeRole(uint64,address).selector ))
140-
? getRoleAdmin(getFirstArgumentAsUint64(data))
141-
: ADMIN_ROLE()
142-
);
143-
144-
assert delay == (
145-
(restricted && selector == to_bytes4(sig:updateAuthority(address,address).selector )) ||
146-
(restricted && selector == to_bytes4(sig:setTargetClosed(address,bool).selector )) ||
147-
(restricted && selector == to_bytes4(sig:setTargetFunctionRole(address,bytes4[],uint64).selector))
148-
? getTargetAdminDelay(e, getFirstArgumentAsAddress(data))
149-
: 0
150-
);
159+
assert restricted == false;
160+
assert roleId == getTargetFunctionRole(currentContract, selector);
161+
assert delay == 0;
151162
}
152163
}
153164

@@ -213,29 +224,31 @@ rule canCallExtended(env e) {
213224
214225
bool immediate = canCallExtended_immediate(e, caller, target, data);
215226
uint32 delay = canCallExtended_delay(e, caller, target, data);
216-
bool enabled = getAdminRestrictions_restricted(e, data);
227+
bool restricted = getAdminRestrictions_restricted(e, data);
228+
bool closed = isTargetClosed(target);
217229
uint64 roleId = getAdminRestrictions_roleAdminId(e, data);
218230
uint32 operationDelay = getAdminRestrictions_executionDelay(e, data);
219231
bool inRole = hasRole_isMember(e, roleId, caller);
220232
uint32 executionDelay = hasRole_executionDelay(e, roleId, caller);
221233
222-
if (target == currentContract) {
234+
if (data.length < 4) {
235+
assert immediate == false;
236+
assert delay == 0;
237+
} else if (target == currentContract) {
223238
// Can only execute without delay in the specific cases:
224239
// - caller is the AccessManager and the executionId is set
225240
// or
226-
// - data matches an admin restricted function
227241
// - caller has the necessary role
228242
// - operation delay is not set
229243
// - execution delay is not set
230244
assert immediate <=> (
231245
(
232246
caller == currentContract &&
233-
data.length >= 4 &&
234247
executionId() == hashExecutionId(target, selector)
235248
) || (
236249
caller != currentContract &&
237-
enabled &&
238-
inRole &&
250+
inRole == true &&
251+
(restricted || !closed) &&
239252
operationDelay == 0 &&
240253
executionDelay == 0
241254
)
@@ -247,21 +260,17 @@ rule canCallExtended(env e) {
247260
248261
// Can only execute with delay in specific cases:
249262
// - caller is a third party
250-
// - data matches an admin restricted function
251263
// - caller has the necessary role
252264
// -operation delay or execution delay is set
253265
assert delay > 0 <=> (
254266
caller != currentContract &&
255-
enabled &&
256-
inRole &&
267+
inRole == true &&
268+
(restricted || !closed) &&
257269
(operationDelay > 0 || executionDelay > 0)
258270
);
259271
260272
// If there is a delay, then it must be the maximum of caller's execution delay and the operation delay
261273
assert delay > 0 => to_mathint(delay) == max(operationDelay, executionDelay);
262-
} else if (data.length < 4) {
263-
assert immediate == false;
264-
assert delay == 0;
265274
} else {
266275
// results are equivalent when targeting third party contracts
267276
assert immediate == canCall_immediate(e, caller, target, selector);

0 commit comments

Comments
 (0)