1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| /// @notice Swap `amount` of first element of `tokens` to the latest element of `destToken` /// @param tokens (IERC20[]) Addresses of token or `address(0)` for Ether /// @param amount (uint256) Amount for `fromToken` /// @param minReturn (uint256) Minimum expected return, else revert /// @param distribution (uint256[]) Array of weights for volume distribution returned by `getExpectedReturn` /// @param flags (uint256[]) Flags for enabling and disabling some features, default 0 /// @param referral (address) Address of referral /// @param feePercent (uint256) Fees percents normalized to 1e18, limited to 0.03e18 (3%) function swapWithReferralMulti( IERC20[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory distribution, uint256[] memory flags, address referral, uint256 feePercent ) public payable returns(uint256 returnAmount) { require(tokens.length >= 2 && amount > 0, "OneSplit: swap makes no sense"); require(flags.length == tokens.length - 1, "OneSplit: flags array length is invalid"); require((msg.value != 0) == tokens.first().isETH(), "OneSplit: msg.value should be used only for ETH swap"); require(feePercent <= 0.03e18, "OneSplit: feePercent out of range");
uint256 gasStart = gasleft();
Balances memory beforeBalances = _getFirstAndLastBalances(tokens, true);
// Transfer From if (amount == uint256(-1)) { amount = Math.min( tokens.first().balanceOf(msg.sender), tokens.first().allowance(msg.sender, address(this)) ); } tokens.first().universalTransferFromSenderToThis(amount); uint256 confirmed = tokens.first().universalBalanceOf(address(this)).sub(beforeBalances.ofFromToken);
// Swap tokens.first().universalApprove(address(oneSplitImpl), confirmed); oneSplitImpl.swapMulti.value(tokens.first().isETH() ? confirmed : 0)( tokens, confirmed, minReturn, distribution, flags );
Balances memory afterBalances = _getFirstAndLastBalances(tokens, false);
// Return returnAmount = afterBalances.ofDestToken.sub(beforeBalances.ofDestToken); require(returnAmount >= minReturn, "OneSplit: actual return amount is less than minReturn"); tokens.last().universalTransfer(referral, returnAmount.mul(feePercent).div(1e18)); tokens.last().universalTransfer(msg.sender, returnAmount.sub(returnAmount.mul(feePercent).div(1e18)));
emit Swapped( tokens.first(), tokens.last(), amount, returnAmount, minReturn, distribution, flags, referral, feePercent );
// Return remainder if (afterBalances.ofFromToken > beforeBalances.ofFromToken) { tokens.first().universalTransfer(msg.sender, afterBalances.ofFromToken.sub(beforeBalances.ofFromToken)); }
if ((flags[0] & (FLAG_ENABLE_CHI_BURN | FLAG_ENABLE_CHI_BURN_BY_ORIGIN)) > 0) { uint256 gasSpent = 21000 + gasStart - gasleft() + 16 * msg.data.length; _chiBurnOrSell( ((flags[0] & FLAG_ENABLE_CHI_BURN_BY_ORIGIN) > 0) ? tx.origin : msg.sender, (gasSpent + 14154) / 41947 ); } else if ((flags[0] & FLAG_ENABLE_REFERRAL_GAS_SPONSORSHIP) > 0) { uint256 gasSpent = 21000 + gasStart - gasleft() + 16 * msg.data.length; IReferralGasSponsor(referral).makeGasDiscount(gasSpent, returnAmount, msg.data); } }
|