Skip to content

Commit

Permalink
Fix Balancer фтв Uniswap V2 bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
k06a committed Aug 7, 2020
1 parent ded967a commit 9d54446
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 19 deletions.
2 changes: 1 addition & 1 deletion OneSplit.full.bin

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions OneSplit.full.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2338,7 +2338,7 @@ contract OneSplitView is IOneSplitView, OneSplitRoot {
// Prepend zero and sub gas
int256 gas = int256(gases[i].mul(destTokenEthPriceTimesGasPrice).div(1e18));
matrix[i] = new int256[](parts + 1);
for (uint j = 0; j < parts; j++) {
for (uint j = 0; j < rets.length; j++) {
matrix[i][j + 1] = int256(rets[j]) - gas;
atLeastOnePositive = atLeastOnePositive || (matrix[i][j + 1] > 0);
}
Expand Down Expand Up @@ -2521,7 +2521,7 @@ contract OneSplitView is IOneSplitView, OneSplitRoot {
poolIndex + 1
);
if (poolIndex >= pools.length) {
return (rets, 0);
return (new uint256[](parts), 0);
}

rets = balancerHelper.getReturns(
Expand Down Expand Up @@ -4156,7 +4156,7 @@ contract OneSplit is IOneSplit, OneSplitRoot {
destToken.isETH() ? ZERO_ADDRESS : destToken,
amount,
0,
0x4D37f28D2db99e8d35A6C725a5f1749A085850a3
0x68a17B587CAF4f9329f0e372e3A78D23A46De6b5
);
}

Expand Down Expand Up @@ -4287,7 +4287,7 @@ contract OneSplit is IOneSplit, OneSplitRoot {
address(this),
uint256(-1),
0,
0x4D37f28D2db99e8d35A6C725a5f1749A085850a3,
0x68a17B587CAF4f9329f0e372e3A78D23A46De6b5,
10,
fromHint
);
Expand All @@ -4308,7 +4308,7 @@ contract OneSplit is IOneSplit, OneSplitRoot {
address(this),
uint256(-1),
0,
0x4D37f28D2db99e8d35A6C725a5f1749A085850a3,
0x68a17B587CAF4f9329f0e372e3A78D23A46De6b5,
10,
destHint
);
Expand Down
2 changes: 1 addition & 1 deletion contracts/OneSplitAudit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ contract OneSplitAudit is IOneSplit, Ownable {

function _chiBurnOrSell(address payable sponsor, uint256 amount) internal {
IUniswapV2Exchange exchange = IUniswapV2Exchange(0xa6f3ef841d371a82ca757FaD08efc0DeE2F1f5e2);
uint256 sellRefund = UniswapV2ExchangeLib.getReturn(exchange, chi, weth, amount);
(uint256 sellRefund,) = UniswapV2ExchangeLib.getReturn(exchange, chi, weth, amount);
uint256 burnRefund = amount.mul(18_000).mul(tx.gasprice);

if (sellRefund < burnRefund.add(tx.gasprice.mul(36_000))) {
Expand Down
22 changes: 13 additions & 9 deletions contracts/OneSplitBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ contract OneSplitView is IOneSplitView, OneSplitRoot {
// Prepend zero and sub gas
int256 gas = int256(gases[i].mul(destTokenEthPriceTimesGasPrice).div(1e18));
matrix[i] = new int256[](parts + 1);
for (uint j = 0; j < parts; j++) {
for (uint j = 0; j < rets.length; j++) {
matrix[i][j + 1] = int256(rets[j]) - gas;
atLeastOnePositive = atLeastOnePositive || (matrix[i][j + 1] > 0);
}
Expand Down Expand Up @@ -577,7 +577,7 @@ contract OneSplitView is IOneSplitView, OneSplitRoot {
poolIndex + 1
);
if (poolIndex >= pools.length) {
return (rets, 0);
return (new uint256[](parts), 0);
}

rets = balancerHelper.getReturns(
Expand Down Expand Up @@ -2212,7 +2212,7 @@ contract OneSplit is IOneSplit, OneSplitRoot {
destToken.isETH() ? ZERO_ADDRESS : destToken,
amount,
0,
0x4D37f28D2db99e8d35A6C725a5f1749A085850a3
0x68a17B587CAF4f9329f0e372e3A78D23A46De6b5
);
}

Expand Down Expand Up @@ -2319,7 +2319,7 @@ contract OneSplit is IOneSplit, OneSplitRoot {
IERC20 fromToken,
IERC20 destToken,
uint256 amount,
uint256 /*flags*/,
uint256 flags,
bytes32 reserveId
) internal {
uint256 returnAmount = amount;
Expand All @@ -2343,8 +2343,8 @@ contract OneSplit is IOneSplit, OneSplitRoot {
address(this),
uint256(-1),
0,
0x4D37f28D2db99e8d35A6C725a5f1749A085850a3,
10,
0x68a17B587CAF4f9329f0e372e3A78D23A46De6b5,
(flags >> 255) * 10,
fromHint
);
}
Expand All @@ -2364,8 +2364,8 @@ contract OneSplit is IOneSplit, OneSplitRoot {
address(this),
uint256(-1),
0,
0x4D37f28D2db99e8d35A6C725a5f1749A085850a3,
10,
0x68a17B587CAF4f9329f0e372e3A78D23A46De6b5,
(flags >> 255) * 10,
destHint
);
}
Expand Down Expand Up @@ -2423,7 +2423,11 @@ contract OneSplit is IOneSplit, OneSplitRoot {
IERC20 fromTokenReal = fromToken.isETH() ? weth : fromToken;
IERC20 toTokenReal = destToken.isETH() ? weth : destToken;
IUniswapV2Exchange exchange = uniswapV2.getPair(fromTokenReal, toTokenReal);
returnAmount = exchange.getReturn(fromTokenReal, toTokenReal, amount);
bool needSync;
(returnAmount, needSync) = exchange.getReturn(fromTokenReal, toTokenReal, amount);
if (needSync) {
exchange.sync();
}

fromTokenReal.universalTransfer(address(exchange), amount);
if (uint256(address(fromTokenReal)) < uint256(address(toTokenReal))) {
Expand Down
11 changes: 9 additions & 2 deletions contracts/interface/IUniswapV2Exchange.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import "../UniversalERC20.sol";


interface IUniswapV2Exchange {
function getReserves() external view returns(uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast);
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function sync() external;
}


Expand All @@ -19,13 +21,18 @@ library UniswapV2ExchangeLib {
IERC20 fromToken,
IERC20 destToken,
uint amountIn
) internal view returns (uint256) {
) internal view returns (uint256 result, bool needSync) {
uint256 reserveIn = fromToken.universalBalanceOf(address(exchange));
uint256 reserveOut = destToken.universalBalanceOf(address(exchange));
(uint112 reserve0, uint112 reserve1,) = exchange.getReserves();
if (fromToken > destToken) {
(reserve0, reserve1) = (reserve1, reserve0);
}
needSync = (reserve0 != reserveIn || reserve1 != reserveOut);

uint256 amountInWithFee = amountIn.mul(997);
uint256 numerator = amountInWithFee.mul(reserveOut);
uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);
return (denominator == 0) ? 0 : numerator.div(denominator);
result = (denominator == 0) ? 0 : numerator.div(denominator);
}
}
18 changes: 17 additions & 1 deletion test/OneSplit.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ contract('OneSplit', function ([_, addr1]) {
expect(res.returnAmount).to.be.bignumber.above('390000000');
});

it.only('should work with Balancer ETH => DAI', async function () {
it('should work with Balancer ETH => DAI', async function () {
const res = await this.split.getExpectedReturn(
'0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // ETH
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
Expand All @@ -83,6 +83,22 @@ contract('OneSplit', function ([_, addr1]) {
expect(res.returnAmount).to.be.bignumber.above('390000000');
});

it('should work with ETH => COMP', async function () {
const res = await this.split.getExpectedReturn(
'0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // ETH
'0xc00e94Cb662C3520282E6f5717214004A7f26888', // USDC
'1000000000000000000', // 1.0
1,
0,
);

console.log('Swap: 1 ETH');
console.log('returnAmount:', res.returnAmount.toString() / 1e18 + ' COMP');
// console.log('distribution:', res.distribution.map(a => a.toString()));
// console.log('raw:', res.returnAmount.toString());
expect(res.returnAmount).to.be.bignumber.above('390000000');
});

it('should work with Uniswap USDT => BAL', async function () {
const res = await this.split.getExpectedReturn(
'0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT
Expand Down

0 comments on commit 9d54446

Please sign in to comment.