contract UpgradeabilityProxy {
  /**
   * @dev Storage slot with the address of the current implementation.
   * This is the keccak-256 hash of "www.invault.io.proxy.implementation", and is
   * validated in the constructor.
   */
  bytes32 private constant IMPLEMENTATION_SLOT = 0xbe2c1a60709d4c60c413b72a0999dd04a683092d060b4c9def249fa6bc842b2d;

  /**
   * @dev Contract constructor.
   * @param _implementation Address of the initial implementation.
   * It should include the signature and the parameters of the function to be called, as described in
   * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
   * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.
   */
  constructor(address _implementation) public {
    assert(IMPLEMENTATION_SLOT == keccak256("www.invault.io.proxy.implementation"));
    _setImplementation(_implementation);
  }

  /**
   * @dev Returns the current implementation.
   * @return Address of the current implementation
   */
  function _implementation() internal view returns (address impl) {
    bytes32 slot = IMPLEMENTATION_SLOT;
    assembly {
      impl := sload(slot)
    }
  }

  /**
   * @dev Upgrades the proxy to a new implementation.
   * @param newImplementation Address of the new implementation.
   */
  function _upgradeTo(address newImplementation) internal {
    _setImplementation(newImplementation);
  }

  /**
   * @dev 设置proxy的Impl地址
   * @param newImplementation Address of the new implementation.
   */
  function _setImplementation(address newImplementation) private {
    require(AddressUtils.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address");

    bytes32 slot = IMPLEMENTATION_SLOT;

    assembly {
      sstore(slot, newImplementation)
    }
  }
}
/**
 * @title UpgradeabilityProxy
 * @dev This contract implements a proxy that allows to change the
 * implementation address to which it will delegate.
 * Such a change is called an implementation upgrade.
 */
function _implementation() internal view returns (address impl) {
  bytes32 slot = IMPLEMENTATION_SLOT;
  assembly {
    impl := sload(slot)
  }
}

/**
 * @dev Returns the current implementation.
 * @return Address of the current implementation
 */