145 lines
4.5 KiB
Solidity
145 lines
4.5 KiB
Solidity
|
// SPDX-License-Identifier: MIT
|
||
|
|
||
|
pragma solidity >=0.8.9;
|
||
|
|
||
|
import "./SwapBase.sol";
|
||
|
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
|
||
|
|
||
|
contract TransferSwapV2 is SwapBase {
|
||
|
using SafeERC20Upgradeable for IERC20Upgradeable;
|
||
|
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;
|
||
|
|
||
|
function transferWithSwapV2Native(
|
||
|
address _receiver,
|
||
|
uint256 _amountIn,
|
||
|
uint64 _dstChainId,
|
||
|
SwapInfoV2 calldata _srcSwap,
|
||
|
SwapInfoDest calldata _dstSwap,
|
||
|
uint32 _maxBridgeSlippage
|
||
|
) external payable {
|
||
|
uint256 _fee = _deriveFeeAndPerformChecksNative(
|
||
|
_amountIn,
|
||
|
_dstChainId,
|
||
|
_dstSwap.integrator,
|
||
|
_srcSwap.path[0]
|
||
|
);
|
||
|
|
||
|
_swapAndSendMessageV2(
|
||
|
_receiver,
|
||
|
_amountIn,
|
||
|
_dstChainId,
|
||
|
_srcSwap,
|
||
|
_dstSwap,
|
||
|
_maxBridgeSlippage,
|
||
|
_fee,
|
||
|
_srcSwap.path[_srcSwap.path.length - 1]
|
||
|
);
|
||
|
}
|
||
|
|
||
|
function transferWithSwapV2(
|
||
|
address _receiver,
|
||
|
uint256 _amountIn,
|
||
|
uint64 _dstChainId,
|
||
|
SwapInfoV2 calldata _srcSwap,
|
||
|
SwapInfoDest calldata _dstSwap,
|
||
|
uint32 _maxBridgeSlippage
|
||
|
) external payable {
|
||
|
uint256 _fee = _deriveFeeAndPerformChecks(
|
||
|
_amountIn,
|
||
|
_dstChainId,
|
||
|
_dstSwap.integrator,
|
||
|
_srcSwap.path[0]
|
||
|
);
|
||
|
|
||
|
_swapAndSendMessageV2(
|
||
|
_receiver,
|
||
|
_amountIn,
|
||
|
_dstChainId,
|
||
|
_srcSwap,
|
||
|
_dstSwap,
|
||
|
_maxBridgeSlippage,
|
||
|
_fee,
|
||
|
_srcSwap.path[_srcSwap.path.length - 1]
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @notice Sends a cross-chain transfer via the liquidity pool-based bridge and sends a message specifying a wanted swap action on the
|
||
|
destination chain via the message bus
|
||
|
* @param _receiver the app contract that implements the MessageReceiver abstract contract
|
||
|
* NOTE not to be confused with the receiver field in SwapInfoV2 which is an EOA address of a user
|
||
|
* @param _amountIn the input amount that the user wants to swap and/or bridge
|
||
|
* @param _dstChainId destination chain ID
|
||
|
* @param _srcSwap a struct containing swap related requirements
|
||
|
* @param _dstSwap a struct containing swap related requirements
|
||
|
* @param _maxBridgeSlippage the max acceptable slippage at bridge, given as percentage in point (pip). Eg. 5000 means 0.5%.
|
||
|
* Must be greater than minimalMaxSlippage. Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount or the
|
||
|
* transfer can be refunded.
|
||
|
* @param _fee the fee to pay to MessageBus.
|
||
|
*/
|
||
|
function _swapAndSendMessageV2(
|
||
|
address _receiver,
|
||
|
uint256 _amountIn,
|
||
|
uint64 _dstChainId,
|
||
|
SwapInfoV2 calldata _srcSwap,
|
||
|
SwapInfoDest calldata _dstSwap,
|
||
|
uint32 _maxBridgeSlippage,
|
||
|
uint256 _fee,
|
||
|
address _outputToken
|
||
|
) private {
|
||
|
BaseCrossChainParams memory _baseParams = BaseCrossChainParams(
|
||
|
_srcSwap.path[0],
|
||
|
_amountIn,
|
||
|
_dstChainId,
|
||
|
_retrieveDstTokenAddress(_dstSwap),
|
||
|
_dstSwap.amountOutMinimum,
|
||
|
msg.sender,
|
||
|
_dstSwap.integrator,
|
||
|
_srcSwap.dex
|
||
|
);
|
||
|
|
||
|
require(_srcSwap.path.length > 1, "empty swap path");
|
||
|
|
||
|
(bool success, uint256 srcAmtOut) = _trySwapV2(_srcSwap, _amountIn);
|
||
|
|
||
|
bytes32 id = _sendMessage(
|
||
|
_receiver,
|
||
|
uint64(_baseParams.dstChainID),
|
||
|
_dstSwap,
|
||
|
_maxBridgeSlippage,
|
||
|
_beforeSwapAndSendMessage(),
|
||
|
_fee,
|
||
|
_outputToken,
|
||
|
srcAmtOut,
|
||
|
success
|
||
|
);
|
||
|
|
||
|
emit CrossChainRequestSent(id, _baseParams);
|
||
|
}
|
||
|
|
||
|
function _trySwapV2(SwapInfoV2 memory _swap, uint256 _amount)
|
||
|
internal
|
||
|
returns (bool ok, uint256 amountOut)
|
||
|
{
|
||
|
if (!availableRouters.contains(_swap.dex)) {
|
||
|
return (false, 0);
|
||
|
}
|
||
|
|
||
|
SmartApprove.smartApprove(_swap.path[0], _amount, _swap.dex);
|
||
|
|
||
|
try
|
||
|
IUniswapV2Router02(_swap.dex).swapExactTokensForTokens(
|
||
|
_amount,
|
||
|
_swap.amountOutMinimum,
|
||
|
_swap.path,
|
||
|
address(this),
|
||
|
_swap.deadline
|
||
|
)
|
||
|
returns (uint256[] memory amounts) {
|
||
|
return (true, amounts[amounts.length - 1]);
|
||
|
} catch {
|
||
|
return (false, 0);
|
||
|
}
|
||
|
}
|
||
|
}
|