contract AdminUpgradeabilityProxy is UpgradeabilityProxy {
   /**
    * @dev Emitted when the administration has been transferred.
    * @param previousAdmin Address of the previous admin.
    * @param newAdmin Address of the new admin.
    */
   event AdminChanged(address previousAdmin, address newAdmin);

   /**
    * @dev Storage slot with the admin of the contract.
    * This is the keccak-256 hash of "org.zeppelinos.proxy.admin", and is
    * validated in the constructor.
    */
   bytes32
       private constant ADMIN_SLOT = 0x10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b;

   /**
    * @dev Modifier to check whether the `msg.sender` is the admin.
    * If it is, it will run the function. Otherwise, it will delegate the call
    * to the implementation.
    */
   modifier ifAdmin() {
       if (msg.sender == _admin()) {
           _;
       } else {
           _fallback();
       }
   }

   /**
    * @dev Contract constructor.
    * It sets the `msg.sender` as the proxy administrator.
    * @param implementationContract address of the initial implementation.
    */
   constructor(address implementationContract)
       public
       UpgradeabilityProxy(implementationContract)
   {
       assert(ADMIN_SLOT == keccak256("org.zeppelinos.proxy.admin"));

       _setAdmin(msg.sender);
   }

   /**
    * @return The address of the proxy admin.
    */
   function admin() external view returns (address) {
       return _admin();
   }

   /**
    * @return The address of the implementation.
    */
   function implementation() external view returns (address) {
       return _implementation();
   }

   /**
    * @dev Changes the admin of the proxy.
    * Only the current admin can call this function.
    * @param newAdmin Address to transfer proxy administration to.
    */
   function changeAdmin(address newAdmin) external ifAdmin {
       require(
           newAdmin != address(0),
           "Cannot change the admin of a proxy to the zero address"
       );
       emit AdminChanged(_admin(), newAdmin);
       _setAdmin(newAdmin);
   }

   /**
    * @dev Upgrade the backing implementation of the proxy.
    * Only the admin can call this function.
    * @param newImplementation Address of the new implementation.
    */
   function upgradeTo(address newImplementation) external ifAdmin {
       _upgradeTo(newImplementation);
   }

   /**
    * @dev Upgrade the backing implementation of the proxy and call a function
    * on the new implementation.
    * This is useful to initialize the proxied contract.
    * @param newImplementation Address of the new implementation.
    * @param data Data to send as msg.data in the low level call.
    * It should include the signature and the parameters of the function to be
    * called, as described in
    * https://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector-and-argument-encoding.
    */
   function upgradeToAndCall(address newImplementation, bytes calldata data)
       external
       payable
       ifAdmin
   {
       _upgradeTo(newImplementation);
       // prettier-ignore
       // solhint-disable-next-line avoid-low-level-calls
       (bool success,) = address(this).call{value: msg.value}(data);
       // solhint-disable-next-line reason-string
       require(success);
   }

   /**
    * @return adm The admin slot.
    */
   function _admin() internal view returns (address adm) {
       bytes32 slot = ADMIN_SLOT;

       assembly {
           adm := sload(slot)
       }
   }

   /**
    * @dev Sets the address of the proxy admin.
    * @param newAdmin Address of the new proxy admin.
    */
   function _setAdmin(address newAdmin) internal {
       bytes32 slot = ADMIN_SLOT;

       assembly {
           sstore(slot, newAdmin)
       }
   }

   /**
    * @dev Only fall back when the sender is not the admin.
    */
   function _willFallback() internal override {
       require(
           msg.sender != _admin(),
           "Cannot call fallback function from the proxy admin"
       );
       super._willFallback();
   }
}
/**
 * @notice This contract combines an upgradeability proxy with an authorization
 * mechanism for administrative tasks.
 * @dev Forked from https://github.com/zeppelinos/zos-lib/blob/8a16ef3ad17ec7430e3a9d2b5e3f39b8204f8c8d/contracts/upgradeability/AdminUpgradeabilityProxy.sol
 * Modifications:
 * 1. Reformat, conform to Solidity 0.6 syntax, and add error messages (5/13/20)
 * 2. Remove ifAdmin modifier from admin() and implementation() (5/13/20)
 */
function _setAdmin(address newAdmin) internal {
    bytes32 slot = ADMIN_SLOT;

    assembly {
        sstore(slot, newAdmin)
    }
}

/**
 * @dev Sets the address of the proxy admin.
 * @param newAdmin Address of the new proxy admin.
 */