contract UpgradeabilityProxy is Proxy {
  /**
   * @dev This event will be emitted every time the implementation gets upgraded
   * @param implementation representing the address of the upgraded implementation
   */
  event Upgraded(address indexed implementation, string version);

  // Storage position of the address of the current implementation
  bytes32 private constant implementationPosition = keccak256("cpc.app.proxy.implementation");
  
   //Version name of the current implementation
  string internal _version;

  /**
   * @dev Constructor function
   */
  constructor() public {}
  
  
  /**
    * @dev Tells the version name of the current implementation
    * @return string representing the name of the current version
    */
    function version() public view returns (string) {
        return _version;
    }

  /**
   * @dev Tells the address of the current implementation
   * @return address of the current implementation
   */
  function implementation() public view returns (address impl) {
    bytes32 position = implementationPosition;
    assembly {
      impl := sload(position)
    }
  }

  /**
   * @dev Sets the address of the current implementation
   * @param _newImplementation address representing the new implementation to be set
   */
  function _setImplementation(address _newImplementation) internal {
    bytes32 position = implementationPosition;
    assembly {
      sstore(position, _newImplementation)
    }
  }

  /**
   * @dev Upgrades the implementation address
   * @param _newImplementation representing the address of the new implementation to be set
   */
  function _upgradeTo(address _newImplementation, string _newVersion) internal {
    address currentImplementation = implementation();
    require(currentImplementation != _newImplementation);
    _setImplementation(_newImplementation);
    _version = _newVersion;
    emit Upgraded( _newImplementation, _newVersion);
  }
}
/**
 * @title UpgradeabilityProxy
 * @dev This contract represents a proxy where the implementation address to which it will delegate can be upgraded
 */
function implementation() public view returns (address impl) {
  bytes32 position = implementationPosition;
  assembly {
    impl := sload(position)
  }
}

/**
 * @dev Tells the address of the current implementation
 * @return address of the current implementation
 */