// File: src/utils/Owned.sol



// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15

pragma solidity ^0.8.15;

// https://docs.synthetix.io/contracts/source/contracts/owned
contract Owned {
  address public owner;
  address public nominatedOwner;

  constructor(address _owner) {
    require(_owner != address(0), "Owner address cannot be 0");
    owner = _owner;
    emit OwnerChanged(address(0), _owner);
  }

  function nominateNewOwner(address _owner) external virtual onlyOwner {
    nominatedOwner = _owner;
    emit OwnerNominated(_owner);
  }

  function acceptOwnership() external virtual {
    require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership");
    emit OwnerChanged(owner, nominatedOwner);
    owner = nominatedOwner;
    nominatedOwner = address(0);
  }

  modifier onlyOwner() {
    _onlyOwner();
    _;
  }

  function _onlyOwner() private view {
    require(msg.sender == owner, "Only the contract owner may perform this action");
  }

  event OwnerNominated(address newOwner);
  event OwnerChanged(address oldOwner, address newOwner);
}

// File: src/vault/AdminProxy.sol



// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15

pragma solidity ^0.8.15;

import {Owned} from "../utils/Owned.sol";

/**
 * @title   AdminProxy
 * @author  RedVeil
 * @notice  Ownes contracts in the vault ecosystem to allow for easy ownership changes.
 *
 * AdminProxy is controlled by VaultController. VaultController executes management functions on other contracts through `execute()`
 */
contract AdminProxy is Owned {
    constructor(address _owner) Owned(_owner) {}

    error UnderlyingError(bytes revertReason);

    /// @notice Execute arbitrary management functions.
    function execute(
        address target,
        bytes calldata callData
    ) external onlyOwner returns (bool success, bytes memory returnData) {
        (success, returnData) = target.call(callData);
        if (!success) revert UnderlyingError(returnData);
    }
}