function forwardEth(KyberNetworkProxyInterface _kyberNetworkProxy, IERC20 _srcToken, uint256 _minimumRate, address _destinationAddress, bytes memory _encodedFunctionCall) public payable {
    require(address(_srcToken) != address(0) && _minimumRate > 0 && _destinationAddress != address(0), "invalid parameter(s)");

    uint256 srcQuantity = address(_srcToken) == ETH_TOKEN_ADDRESS ? msg.value : _srcToken.allowance(msg.sender, address(this));

    if (address(_srcToken) != ETH_TOKEN_ADDRESS) {
      _srcToken.safeTransferFrom(msg.sender, address(this), srcQuantity);

      require(_srcToken.allowance(address(this), address(_kyberNetworkProxy)) == 0, "non-zero initial _kyberNetworkProxy allowance");
      require(_srcToken.approve(address(_kyberNetworkProxy), srcQuantity), "approving _kyberNetworkProxy failed");
    }

    uint256 amountDai = address(_srcToken) == ETH_TOKEN_ADDRESS ? _kyberNetworkProxy.swapEtherToToken.value(srcQuantity)(dai, _minimumRate) : _kyberNetworkProxy.swapTokenToToken(_srcToken, srcQuantity, dai, _minimumRate);
    require(amountDai >= srcQuantity.mul(_minimumRate).div(1e18), "_kyberNetworkProxy failed");

    require(dai.allowance(address(this), _destinationAddress) == 0, "non-zero initial destination allowance");
    require(dai.approve(_destinationAddress, amountDai), "approving destination failed");

    (bool success, ) = _destinationAddress.call(_encodedFunctionCall);
    require(success, "destination call failed");

    uint256 changeDai = dai.allowance(address(this), _destinationAddress);
    if (changeDai > 0) {
      dai.safeTransfer(msg.sender, changeDai);
      require(dai.approve(_destinationAddress, 0), "un-approving destination failed");
    }

    emit PaymentForwarded(msg.sender, _destinationAddress, address(_srcToken), amountDai.sub(changeDai), srcQuantity, changeDai, _encodedFunctionCall);
  }