contract OwnedUpgradeabilityProxy is UpgradeabilityProxy {

    /// @dev Event to show ownership has been transferred
    /// @param previousOwner representing the address of the previous owner
    /// @param newOwner representing the address of the new owner
    event ProxyOwnershipTransferred(address previousOwner, address newOwner);

    /// @dev Storage slot of the owner of the contract
    /// This is the keccak-256 hash of "io.laborx.proxy.implementation"
    bytes32 private constant PROXY_OWNER_SLOT = 0x9f0cb10b07044a26ed5e46aa863117e6277a419ad770761a6659221f518998bd;

    /// @dev the constructor sets the original owner of the contract to the sender account.
    constructor(address _logic, bytes memory _data) public UpgradeabilityProxy(_logic, _data) {
        _setUpgradeabilityOwner(msg.sender);
    }

    /// @dev Throws if called by any account other than the owner.
    modifier onlyProxyOwner() {
        require(msg.sender == proxyOwner(), "PROXY_OWNER_ONLY");
        _;
    }

    /// @notice Tells the address of the owner
    /// @return the address of the owner
    function proxyOwner() public view returns (address owner) {
        bytes32 slot = PROXY_OWNER_SLOT;
        assembly {
            owner := sload(slot)
        }
    }

    /// @notice Allows the current owner to transfer control of the contract to a newOwner.
    /// @param newOwner The address to transfer ownership to.
    function transferProxyOwnership(address newOwner) external onlyProxyOwner {
        require(newOwner != address(0), "PROXY_INVALID_NEW_OWNER");
        emit ProxyOwnershipTransferred(proxyOwner(), newOwner);
        _setUpgradeabilityOwner(newOwner);
    }

    /// @notice Allows the proxy owner to upgrade the current version of the proxy.
    /// @param implementation representing the address of the new implementation to be set.
    function upgradeTo(address implementation) public onlyProxyOwner {
        _upgradeTo(implementation);
    }

    /// @notice Allows the proxy owner to upgrade the current version of the proxy and call the new implementation
    ///     to initialize whatever is needed through a low level call.
    /// @param implementation representing the address of the new implementation to be set.
    /// @param data represents the msg.data to bet sent in the low level call. This parameter may include the function
    ///     signature of the implementation to be called with the needed payload
    function upgradeToAndCall(address implementation, bytes data) external payable onlyProxyOwner {
        upgradeTo(implementation);
        require(this.call.value(msg.value)(data), "PROXY_FAILED_CALL");
    }

    /// @dev Sets the address of the owner
    function _setUpgradeabilityOwner(address newProxyOwner) internal {
        bytes32 slot = PROXY_OWNER_SLOT;
        assembly {
            sstore(slot, newProxyOwner)
        }
    }
}
/// @title OwnedUpgradeabilityProxy
/// @dev This contract combines an upgradeability proxy with basic authorization control functionalities
function upgradeTo(address implementation) public onlyProxyOwner {
    _upgradeTo(implementation);
}

/// @notice Allows the proxy owner to upgrade the current version of the proxy.
/// @param implementation representing the address of the new implementation to be set.