diff --git a/CCTPRelayer/src/CCTPRelayer.sol b/CCTPRelayer/src/CCTPRelayer.sol index 539c34e..6f85985 100644 --- a/CCTPRelayer/src/CCTPRelayer.sol +++ b/CCTPRelayer/src/CCTPRelayer.sol @@ -131,66 +131,9 @@ contract CCTPRelayer is ICCTPRelayer, Initializable, UUPSUpgradeable, Ownable2St uint256 outputAmount; if (inputToken == address(0)) { - IERC20 token = IERC20(inputToken); - - // Native Token - if (inputAmount != msg.value) revert InsufficientNativeToken(); - - // Get the contract's balances previous to the swap - uint256 preInputBalance = address(this).balance - inputAmount; - uint256 preOutputBalance = usdc.balanceOf(address(this)); - - // Call the swap router and perform the swap - (bool success,) = swapRouter.call{value: inputAmount}(swapCalldata); - if (!success) revert SwapFailed(); - - // Get the contract's balances after the swap - uint256 postInputBalance = address(this).balance; - uint256 postOutputBalance = usdc.balanceOf(address(this)); - - // Check that the contract's native token balance has increased - if (preOutputBalance >= postOutputBalance) revert InsufficientSwapOutput(); - outputAmount = postOutputBalance - preOutputBalance; - - // Refund the remaining ETH - uint256 dust = postInputBalance - preInputBalance; - if (dust != 0) { - (bool ethSuccess,) = msg.sender.call{value: dust}(""); - if (!ethSuccess) revert ETHSendFailed(); - } + outputAmount = _swapNativeAndReturnDust(inputAmount, swapCalldata); } else { - IERC20 token = IERC20(inputToken); - - // Get the contract's balances previous to the swap - uint256 preInputBalance = token.balanceOf(address(this)); - uint256 preOutputBalance = usdc.balanceOf(address(this)); - - // Transfer input ERC20 tokens to the contract - token.transferFrom(msg.sender, address(this), inputAmount); - - // Approve the swap router to spend the input tokens - token.approve(swapRouter, inputAmount); - - // Call the swap router and perform the swap - (bool success,) = swapRouter.call(swapCalldata); - if (!success) revert SwapFailed(); - - // Get the contract's balances after the swap - uint256 postInputBalance = token.balanceOf(address(this)); - uint256 postOutputBalance = usdc.balanceOf(address(this)); - - // Check that the contract's output token balance has increased - if (preOutputBalance >= postOutputBalance) revert InsufficientSwapOutput(); - outputAmount = postOutputBalance - preOutputBalance; - - // Refund the remaining amount - uint256 dust = postInputBalance - preInputBalance; - if (dust != 0) { - token.transfer(msg.sender, dust); - - // Revoke Approval - token.approve(swapRouter, 0); - } + outputAmount = _swapAndReturnDust(inputToken, inputAmount, swapCalldata); } // Check that output amount is enough to cover the fee @@ -224,66 +167,9 @@ contract CCTPRelayer is ICCTPRelayer, Initializable, UUPSUpgradeable, Ownable2St uint256 outputAmount; if (inputToken == address(0)) { - // Native Token - if (inputAmount != msg.value) revert InsufficientNativeToken(); - - IERC20 token = IERC20(inputToken); - - // Get the contract's balances previous to the swap - uint256 preInputBalance = address(this).balance - inputAmount; - uint256 preOutputBalance = usdc.balanceOf(address(this)); - - // Call the swap router and perform the swap - (bool success,) = swapRouter.call{value: inputAmount}(swapCalldata); - if (!success) revert SwapFailed(); - - // Get the contract's balances after the swap - uint256 postInputBalance = address(this).balance; - uint256 postOutputBalance = usdc.balanceOf(address(this)); - - // Check that the contract's native token balance has increased - if (preOutputBalance >= postOutputBalance) revert InsufficientSwapOutput(); - outputAmount = postOutputBalance - preOutputBalance; - - // Refund the remaining ETH - uint256 dust = postInputBalance - preInputBalance; - if (dust != 0) { - (bool ethSuccess,) = msg.sender.call{value: dust}(""); - if (!ethSuccess) revert ETHSendFailed(); - } + outputAmount = _swapNativeAndReturnDust(inputAmount, swapCalldata); } else { - IERC20 token = IERC20(inputToken); - - // Get the contract's balances previous to the swap - uint256 preInputBalance = token.balanceOf(address(this)); - uint256 preOutputBalance = usdc.balanceOf(address(this)); - - // Transfer input ERC20 tokens to the contract - token.transferFrom(msg.sender, address(this), inputAmount); - - // Approve the swap router to spend the input tokens - token.approve(swapRouter, inputAmount); - - // Call the swap router and perform the swap - (bool success,) = swapRouter.call(swapCalldata); - if (!success) revert SwapFailed(); - - // Get the contract's balances after the swap - uint256 postInputBalance = token.balanceOf(address(this)); - uint256 postOutputBalance = usdc.balanceOf(address(this)); - - // Check that the contract's output token balance has increased - if (preOutputBalance >= postOutputBalance) revert InsufficientSwapOutput(); - outputAmount = postOutputBalance - preOutputBalance; - - // Refund the remaining amount - uint256 dust = postInputBalance - preInputBalance; - if (dust != 0) { - token.transfer(msg.sender, dust); - - // Revoke Approval - token.approve(swapRouter, 0); - } + outputAmount = _swapAndReturnDust(inputToken, inputAmount, swapCalldata); } // Check that output amount is enough to cover the fee @@ -335,4 +221,73 @@ contract CCTPRelayer is ICCTPRelayer, Initializable, UUPSUpgradeable, Ownable2St receive() external payable {} function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} + + function _swapAndReturnDust(address inputToken, uint256 inputAmount, bytes memory swapCalldata) + internal + returns (uint256 outputAmount) + { + IERC20 token = IERC20(inputToken); + + // Get the contract's balances previous to the swap + uint256 preInputBalance = token.balanceOf(address(this)); + uint256 preOutputBalance = usdc.balanceOf(address(this)); + + // Transfer input ERC20 tokens to the contract + token.transferFrom(msg.sender, address(this), inputAmount); + + // Approve the swap router to spend the input tokens + token.approve(swapRouter, inputAmount); + + // Call the swap router and perform the swap + (bool success,) = swapRouter.call(swapCalldata); + if (!success) revert SwapFailed(); + + // Get the contract's balances after the swap + uint256 postInputBalance = token.balanceOf(address(this)); + uint256 postOutputBalance = usdc.balanceOf(address(this)); + + // Check that the contract's output token balance has increased + if (preOutputBalance >= postOutputBalance) revert InsufficientSwapOutput(); + outputAmount = postOutputBalance - preOutputBalance; + + // Refund the remaining amount + uint256 dust = postInputBalance - preInputBalance; + if (dust != 0) { + token.transfer(msg.sender, dust); + + // Revoke Approval + token.approve(swapRouter, 0); + } + } + + function _swapNativeAndReturnDust(uint256 inputAmount, bytes memory swapCalldata) + internal + returns (uint256 outputAmount) + { + // Native Token + if (inputAmount != msg.value) revert InsufficientNativeToken(); + + // Get the contract's balances previous to the swap + uint256 preInputBalance = address(this).balance - inputAmount; + uint256 preOutputBalance = usdc.balanceOf(address(this)); + + // Call the swap router and perform the swap + (bool success,) = swapRouter.call{value: inputAmount}(swapCalldata); + if (!success) revert SwapFailed(); + + // Get the contract's balances after the swap + uint256 postInputBalance = address(this).balance; + uint256 postOutputBalance = usdc.balanceOf(address(this)); + + // Check that the contract's native token balance has increased + if (preOutputBalance >= postOutputBalance) revert InsufficientSwapOutput(); + outputAmount = postOutputBalance - preOutputBalance; + + // Refund the remaining ETH + uint256 dust = postInputBalance - preInputBalance; + if (dust != 0) { + (bool ethSuccess,) = msg.sender.call{value: dust}(""); + if (!ethSuccess) revert ETHSendFailed(); + } + } }