123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- import "helpers/helpers.spec"
- import "methods/IOwnable.spec"
- methods {
- restricted()
- }
- /*
- ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
- │ Function correctness: transferOwnership changes ownership │
- └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- */
- rule transferOwnership(env e) {
- require nonpayable(e);
- address newOwner;
- address current = owner();
- transferOwnership@withrevert(e, newOwner);
- bool success = !lastReverted;
- assert success <=> (e.msg.sender == current && newOwner != 0), "unauthorized caller or invalid arg";
- assert success => owner() == newOwner, "current owner changed";
- }
- /*
- ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
- │ Function correctness: renounceOwnership removes the owner │
- └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- */
- rule renounceOwnership(env e) {
- require nonpayable(e);
- address current = owner();
- renounceOwnership@withrevert(e);
- bool success = !lastReverted;
- assert success <=> e.msg.sender == current, "unauthorized caller";
- assert success => owner() == 0, "owner not cleared";
- }
- /*
- ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
- │ Access control: only current owner can call restricted functions │
- └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- */
- rule onlyCurrentOwnerCanCallOnlyOwner(env e) {
- require nonpayable(e);
- address current = owner();
- calldataarg args;
- restricted@withrevert(e, args);
- assert !lastReverted <=> e.msg.sender == current, "access control failed";
- }
- /*
- ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
- │ Rule: ownership can only change in specific ways │
- └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- */
- rule onlyOwnerOrPendingOwnerCanChangeOwnership(env e) {
- address oldCurrent = owner();
- method f; calldataarg args;
- f(e, args);
- address newCurrent = owner();
- // If owner changes, must be either transferOwnership or renounceOwnership
- assert oldCurrent != newCurrent => (
- (e.msg.sender == oldCurrent && newCurrent != 0 && f.selector == transferOwnership(address).selector) ||
- (e.msg.sender == oldCurrent && newCurrent == 0 && f.selector == renounceOwnership().selector)
- );
- }
|