Once you are ok with the tokens to provide and the reward, you can go ahead and execute the swap.
In v2, all swaps are flash swaps. Flash Swaps are fairly complex to execute, but at the same time they hold the biggest potential for profit. This is because the user will receive their reward tokens before having to send the required tokens while, simultaneously, the caller can actually borrow all of the hub's liquidity for free. In that sense, this action can be seen both as a flash swap and a flash loan.
Flash Swaps can be divided into three parts:
Calling the pair
Receiving the reward and borrowed (if any) tokens, and doing something with them
Returning the needed and borrowed (if any) tokens
The caller in step one can be different from the contract in step 2 and 3, but for the purposes of this example, they will all be the same contract.
pragmasolidity >=0.8.7 <0.9.0;import'@openzeppelin/contracts/token/ERC20/IERC20.sol';import'@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';import'@mean-finance/dca-v2-core/contracts/interfaces/IDCAHub.sol';import'@mean-finance/dca-v2-core/contracts/interfaces/IDCAHubSwapCallee.sol';// In order to receive the reward + borrowed tokens in step 2, you need to implement IDCAHubSwapCalleecontractMyContractisIDCAHubSwapCallee {usingSafeERC20forIERC20; IDCAHub publicimmutable hub;constructor(IDCAHub_hub) { hub = _hub; }/// @notice Executes a flash swap/// @param _tokens The tokens involved in the next swap/// @param _pairsToSwap The pairs that you want to swap. Each element of the list points to the index of the token in the tokens array/// @param _rewardRecipient The address to send the reward to/// @param _callbackHandler Address to call for callback (and send the borrowed tokens to)/// @param _borrow How much to borrow of each of the tokens in tokens. The amount must match the position of the token in the tokens array/// @param _callbackData Bytes to send to the caller during the callback/// @param _oracleData Bytes to send to the oracle when executing a quote/// @return Information about the executed swap functionexecuteSwap( address[] calldata_tokens,PairIndexes[] calldata_pairsToSwap,address_rewardRecipient,address_callbackHandler,uint256[] calldata_borrow,bytescalldata_callbackData,bytescalldata_oracleData ) externalreturns (IDCAHub.SwapInfomemory) {// Step 1, calling the hub and executing the swapreturn hub.swap(_tokens, _pairsToSwap,address(this),address(this), _borrow, _data); }// solhint-disable-next-line func-name-mixedcasefunctionDCAHubSwapCall(address_sender,// The swap originator, in this case this same contractIDCAHub.TokenInSwap[] calldata_tokens,// How much did we get as reward & how much needs to be sent backuint256[] calldata_borrowed,// How much was borrowed from the tokens in `_tokens`bytescalldata_data// Whatever was sent to `executeSwap` ) external {// Step 2, do something with the reward and borrowed tokens ... // Step 3, return the borrowed and needed tokensfor (uint i; i < _tokens.length; i++) {uint256 _amountToReturn = _borrowed[i] + _tokens[i].toProvide;if (_amountToReturn >0) {IERC20(_tokens[i].token).safeTransfer(msg.sender, _amountToReturn); } } } }