Created
November 1, 2019 13:33
-
-
Save k06a/402807c686c504578adbc78301d85724 to your computer and use it in GitHub Desktop.
SplitKyber
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.5.0; | |
import "github.com/openzeppelin/openzeppelin-contracts/contracts/math/SafeMath.sol"; | |
import "github.com/openzeppelin/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; | |
import "github.com/openzeppelin/openzeppelin-contracts/contracts/token/ERC20/SafeERC20.sol"; | |
interface IKyberReserve { | |
function trade( | |
IERC20 srcToken, | |
uint srcAmount, | |
IERC20 destToken, | |
address destAddress, | |
uint conversionRate, | |
bool validate | |
) | |
external | |
payable | |
returns(bool); | |
function getConversionRate( | |
IERC20 src, | |
IERC20 dest, | |
uint srcQty, | |
uint blockNumber | |
) | |
external | |
view | |
returns(uint); | |
} | |
contract SplitKyber { | |
using SafeMath for uint256; | |
IKyberReserve[] public reserves; | |
function getConversionRate( | |
IERC20 src, | |
IERC20 dest, | |
uint srcQty, | |
uint parts | |
) | |
public | |
view | |
returns( | |
uint destQty, | |
uint[] memory distribution | |
) | |
{ | |
uint256[] memory rates = new uint256[](reserves.length); | |
uint256[] memory fullRates = new uint256[](reserves.length); | |
for (uint i = 0; i < rates.length; i++) { | |
rates[i] = reserves[i].getConversionRate(src, dest, srcQty.mul(i).div(parts), block.number); | |
fullRates[i] = rates[i]; | |
} | |
distribution = new uint256[](parts); | |
for (uint j = 0; j < parts; j++) { | |
// Find best part | |
uint256 bestIndex = 0; | |
for (uint i = 0; i < rates.length; i++) { | |
if (rates[i] > rates[bestIndex]) { | |
bestIndex = i; | |
} | |
} | |
// Add best part | |
destQty = destQty.add(rates[bestIndex]); | |
distribution[bestIndex]++; | |
uint256 srcAmount = srcQty; // Avoid CompilerError: Stack too deep | |
// Recalc part if needed | |
if (j + 1 < parts) { | |
uint256 newRate = reserves[bestIndex].getConversionRate( | |
src, dest, srcAmount.mul(distribution[bestIndex] + 1).div(parts), block.number | |
); | |
rates[bestIndex] = newRate.sub(fullRates[bestIndex]); | |
fullRates[bestIndex] = newRate; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment