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);     } }
 
 
  |