From 162dd6ce9e4a031fb6a1e13229994e0992ed042a Mon Sep 17 00:00:00 2001 From: Drew Date: Fri, 1 Jul 2022 17:52:56 +0000 Subject: [PATCH] Add native relayer payment for exactIn swaps --- contracts/contracts/CrossChainSwapV2.sol | 34 +++++++++++---------- contracts/contracts/CrossChainSwapV3.sol | 38 +++++++++++++----------- 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/contracts/contracts/CrossChainSwapV2.sol b/contracts/contracts/CrossChainSwapV2.sol index 4e25c32..e0591a5 100644 --- a/contracts/contracts/CrossChainSwapV2.sol +++ b/contracts/contracts/CrossChainSwapV2.sol @@ -96,30 +96,31 @@ contract CrossChainSwapV2 { "tokenOut must be wrapped native asset" ); - // pay relayer before attempting to do the swap - // reflect payment in second swap amount - IERC20 feeToken = IERC20(FEE_TOKEN_ADDRESS); - feeToken.safeTransfer(msg.sender, payload.relayerFee); - uint256 swapAmountLessFees = payload.swapAmount - payload.relayerFee; - // approve the router to spend tokens TransferHelper.safeApprove( uniPath[0], address(SWAP_ROUTER), - swapAmountLessFees + payload.swapAmount ); // try to execute the swap try SWAP_ROUTER.swapExactTokensForTokens( - swapAmountLessFees, + payload.swapAmount, payload.estimatedAmount, uniPath, address(this), payload.deadline ) returns (uint256[] memory amounts) { + // calculate how much to pay the relayer in the native token + uint256 nativeRelayerFee = amounts[1] * payload.relayerFee / payload.swapAmount; + uint256 nativeAmountOut = amounts[1] - nativeRelayerFee; + // unwrap native and send to recipient IWETH(WRAPPED_NATIVE).withdraw(amounts[1]); - payable(payload.recipientAddress).transfer(amounts[1]); + payable(payload.recipientAddress).transfer(nativeAmountOut); + + /// pay the relayer in the native token + payable(msg.sender).transfer(nativeRelayerFee); // used in UI to tell user they're getting // their desired token @@ -127,15 +128,19 @@ contract CrossChainSwapV2 { payload.recipientAddress, uniPath[1], msg.sender, - amounts[1], + nativeAmountOut, 1 ); return amounts; } catch { + // pay relayer in the feeToken since the swap failed + IERC20 feeToken = IERC20(FEE_TOKEN_ADDRESS); + feeToken.safeTransfer(msg.sender, payload.relayerFee); + // swap failed - return feeToken to recipient - IERC20(FEE_TOKEN_ADDRESS).safeTransfer( + feeToken.safeTransfer( payload.recipientAddress, - swapAmountLessFees + payload.swapAmount - payload.relayerFee ); // used in UI to tell user they're getting @@ -144,7 +149,7 @@ contract CrossChainSwapV2 { payload.recipientAddress, uniPath[0], msg.sender, - swapAmountLessFees, + payload.swapAmount - payload.relayerFee, 0 ); } @@ -176,8 +181,7 @@ contract CrossChainSwapV2 { "tokenOut must be wrapped native asset" ); - // pay relayer before attempting to do the swap - // reflect payment in second swap amount + // pay the relayer in feeToken so that user gets desired exact amount out IERC20 feeToken = IERC20(FEE_TOKEN_ADDRESS); feeToken.safeTransfer(msg.sender, payload.relayerFee); uint256 maxAmountInLessFees = payload.swapAmount - payload.relayerFee; diff --git a/contracts/contracts/CrossChainSwapV3.sol b/contracts/contracts/CrossChainSwapV3.sol index aa9421a..af5202b 100644 --- a/contracts/contracts/CrossChainSwapV3.sol +++ b/contracts/contracts/CrossChainSwapV3.sol @@ -93,19 +93,13 @@ contract CrossChainSwapV3 { require( payload.path[1]==WRAPPED_NATIVE, "tokenOut must be wrapped Native" - ); - - // pay relayer before attempting to do the swap - // reflect payment in second swap amount - IERC20 feeToken = IERC20(FEE_TOKEN_ADDRESS); - feeToken.safeTransfer(msg.sender, payload.relayerFee); - uint256 swapAmountLessFees = payload.swapAmount - payload.relayerFee; + ); // approve the router to spend tokens TransferHelper.safeApprove( payload.path[0], address(SWAP_ROUTER), - swapAmountLessFees + payload.swapAmount ); // set swap options with user params @@ -116,16 +110,23 @@ contract CrossChainSwapV3 { fee: payload.poolFee, recipient: address(this), deadline: payload.deadline, - amountIn: swapAmountLessFees, + amountIn: payload.swapAmount, amountOutMinimum: payload.estimatedAmount, sqrtPriceLimitX96: 0 }); // try to execute the swap try SWAP_ROUTER.exactInputSingle(params) returns (uint256 amountOut) { + // calculate how much to pay the relayer in the native token + uint256 nativeRelayerFee = amountOut * payload.relayerFee / payload.swapAmount; + uint256 nativeAmountOut = amountOut - nativeRelayerFee; + // unwrap native and send to recipient IWETH(WRAPPED_NATIVE).withdraw(amountOut); - payable(payload.recipientAddress).transfer(amountOut); + payable(payload.recipientAddress).transfer(nativeAmountOut); + + /// pay the relayer in the native token + payable(msg.sender).transfer(nativeRelayerFee); // used in UI to tell user they're getting // their desired token @@ -133,15 +134,19 @@ contract CrossChainSwapV3 { payload.recipientAddress, payload.path[1], msg.sender, - amountOut, + nativeAmountOut, 1 ); return amountOut; } catch { - // swap failed - return feeToken to recipient - IERC20(FEE_TOKEN_ADDRESS).safeTransfer( + // pay relayer in the feeToken since the swap failed + IERC20 feeToken = IERC20(FEE_TOKEN_ADDRESS); + feeToken.safeTransfer(msg.sender, payload.relayerFee); + + // swap failed - return feeToken (less relayer fees) to recipient + feeToken.safeTransfer( payload.recipientAddress, - swapAmountLessFees + payload.swapAmount - payload.relayerFee ); // used in UI to tell user they're getting @@ -150,7 +155,7 @@ contract CrossChainSwapV3 { payload.recipientAddress, payload.path[0], msg.sender, - swapAmountLessFees, + payload.swapAmount - payload.relayerFee, 0 ); } @@ -177,8 +182,7 @@ contract CrossChainSwapV3 { "tokenOut must be wrapped native asset" ); - // pay relayer before attempting to do the swap - // reflect payment in second swap amount + // pay the relayer in feeToken so that user gets desired exact amount out IERC20 feeToken = IERC20(FEE_TOKEN_ADDRESS); feeToken.safeTransfer(msg.sender, payload.relayerFee); uint256 maxAmountInLessFees = payload.swapAmount - payload.relayerFee;