abstract contract Proxy {
  using AddressUtils for address;

  /**
   * @notice delegate all calls to implementation contract
   * @dev reverts if implementation address contains no code, for compatibility with metamorphic contracts
   * @dev memory location in use by assembly may be unsafe in other contexts
   */
  fallback () virtual external payable {
    address implementation = _getImplementation();

    require(
      implementation.isContract(),
      'Proxy: implementation must be contract'
    );

    assembly {
      calldatacopy(0, 0, calldatasize())
      let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
      returndatacopy(0, 0, returndatasize())

      switch result
      case 0 { revert(0, returndatasize()) }
      default { return (0, returndatasize()) }
    }
  }

  /**
   * @notice get logic implementation address
   * @return implementation address
   */
  function _getImplementation () virtual internal returns (address);
}
/**
 * @title Base proxy contract
 */
/**
 * @notice delegate all calls to implementation contract
 * @dev reverts if implementation address contains no code, for compatibility with metamorphic contracts
 * @dev memory location in use by assembly may be unsafe in other contexts
 */