- The 1inch Aggregator sources liquidity from various DEXes to provide users with the best possible trading rates. It achieves this by splitting transactions across multiple DEXes, effectively minimizing slippage and maximizing trade efficiency.
- Key to its operation is the OneSplit smart contract, which automates the process of finding the best execution for a trade.
- Functionality: OneSplit smart contract is responsible for splitting orders into parts and routing them through the most efficient path. It calculates the expected return for a given trade, considering various factors like liquidity depth and token prices in real-time across different DEXes.
- Parts and Distribution: The concept of ‘parts’ in OneSplit plays a crucial role. It refers to how a trade is divided for execution across DEXes. The contract determines the optimal way to allocate these parts to different DEXes, which is reflected in the distribution array. The OneSplit contract holds a list of DEXes from where it choses where to trade.
- Execution of Trades: The standard
swapmethod in OneSplit handles multi-step trades, while theswapMultimethod allows for executing a sequence of distinct swaps in a single transaction.
OneSplit Flow
getExpectedReturn: Everything starts in here it receivesfromToken, destToken, amount, parts, flags you check the flags here. this will return and object like this:
parts input indicates how many parts the trade should be split into, and the distribution array shows the allocation of these parts across different DEXes. The returnAmount represents the expected return for the trade.
as you can see it returns an expected amount and a distribution array, this distribution array is a list of exchanges inside the contract where it can perform the swaps, in this example is suggesting to swap 1 part on exchange #0 and 4 parts on exchange #6, 5 parts in total.
To find the best distribution it has a _findBestDistribution function which receives the parts and a matrix of expected amounts and then returns the distribution. This Matrix is built calculating the expected return for each exchange and each accumulated parts. For example: matrix[i][j] is the expected return of using exchange i with j parts minus gas.
This matrix is build using an array of functions. Which could be tricky to understand:
_getAllReserves(flags) returns an array of functions, each function is a calculate function for a different protocol, for example, the array could be [calculateUniswap, calculateBancor, ... , calculateOasis].
_findBestDristribution: This function is responsible for finding the best distribution of the parts, it receives the parts and a matrix of expected amounts. it builds two arrays, answer and parent. First, the answer array stores the expected return of exchange and parts combinations. For example, answer[i][j] stores the best expected amount using j parts, which could be swapping j-k for one (or multiple) exchange and k for the exchange i. Second, the parent array stores the number of parts that are left to use in another exchange. The answer array is a matrix of int[n][s+1] and the parent array is a matrix of uint[n][s+1] where n is the number of exchanges and s is the number of parts.
j parts, and the expected return for the rest of the exchanges is -1e72 (a very low number) and the parent for the first exchange is 0.
The main part of the algorithm is here:
j parts and the parent for the first exchange is j. Then it loops through the rest of the exchanges and parts, checking if the expected return of using one exchange with j parts is greater than the expected return of using the previous exchange with j parts, if it is then it updates the answer and parent arrays with the new expected return and the new parent.
Finally, it returns the distribution and the expected return:
fromToken, destToken, amount, minReturn, distribution, flags. this function can be found here it gets all the swaps functions, differents for each router/protocol and then loops through the distribution matching the corresponding swap protocol with the amounts, here is a snippet of how it is performing the swap: