Skip to content

Commit

Permalink
chore: removed univ3 quoter as it is querky in tests and expensive in…
Browse files Browse the repository at this point in the history
… gas
  • Loading branch information
sandybradley committed Jan 11, 2024
1 parent e6f5adb commit 77b1f83
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 63 deletions.
63 changes: 0 additions & 63 deletions src/MevEthRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import "./interfaces/IGyro.sol";
import "./interfaces/ICurveV2Pool.sol";
import "./interfaces/IMevEth.sol";
import "./interfaces/IRateProvider.sol";
import "./interfaces/IQuoterV2.sol";
import "./interfaces/IGyroECLPMath.sol";
import "./interfaces/IMevEthRouter.sol";
import "./interfaces/IUniswapV3SwapCallback.sol";
Expand Down Expand Up @@ -43,8 +42,6 @@ contract MevEthRouter is IUniswapV3SwapCallback, IMevEthRouter {
IVault internal constant BAL = IVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);
/// @dev Gyro ECLP Math lib
IGyroECLPMath internal constant gyroMath = IGyroECLPMath(0xF89A1713998593A441cdA571780F0900Dbef20f9);
/// @dev IQuoterV2 Uniswap swap quoter
IQuoterV2 internal constant quoter = IQuoterV2(0x61fFE014bA17989E743c5F6cB21bF9697530B21e);
/// @dev Sushiswap factory address
address internal constant SUSHI_FACTORY = 0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac;
/// @dev UniswapV2 factory address
Expand Down Expand Up @@ -445,20 +442,14 @@ contract MevEthRouter is IUniswapV3SwapCallback, IMevEthRouter {
view
returns (uint256 amountOut)
{
// uint256 scalingFactorTokenIn = _scalingFactor(!isDeposit);
// uint256 scalingFactorTokenOut = _scalingFactor(isDeposit);
uint256[] memory balances = new uint256[](2);
balances[0] = isDeposit ? reserveOut : reserveIn;
balances[1] = isDeposit ? reserveIn : reserveOut;

// uint256 feeAmount = amountIn * MevEthLibrary.getFee(5) / 1_000_000;
// amountIn = (amountIn - feeAmount) * _scalingFactor(!isDeposit) / 1 ether;
amountIn = (amountIn - amountIn * MevEthLibrary.getFee(5) / 1_000_000) * _scalingFactor(!isDeposit) / 1 ether;

// same selector workaround here
// bytes memory data = abi.encodeWithSelector(0x61ff4236, balances, amountIn, !isDeposit, params, derived, inv);
(, bytes memory returnData) = address(gyroMath).staticcall(abi.encodeWithSelector(0x61ff4236, balances, amountIn, !isDeposit, params, derived, inv));
// amountOut = gyroMath.calcOutGivenIn(balances, amountIn, !isDeposit, params, derived, inv) * 1 ether / scalingFactorTokenOut;
amountOut = abi.decode(returnData, (uint256)) * 1 ether / _scalingFactor(isDeposit);
}

Expand Down Expand Up @@ -549,23 +540,6 @@ contract MevEthRouter is IUniswapV3SwapCallback, IMevEthRouter {
);
}

// UniV3 adjustment
// Expensive in gas, so only used for high values and preferably called off-chain
if (index2[i] < 5 && index2[i] > 1 && amountsIn[index2[i]] > uniV3Caps[index2[i] - 2] / 2) {
// address tokenIn = isDeposit ? address(WETH09) : address(MEVETH);
// address tokenOut = isDeposit ? address(MEVETH) : address(WETH09);
amountsOut[index2[i]] = _swapUniV3Call(
isDeposit,
uint24(MevEthLibrary.getFee(index2[i])),
isDeposit ? address(WETH09) : address(MEVETH),
isDeposit ? address(MEVETH) : address(WETH09),
amountsIn[index2[i]]
);
if (amountsOut[index2[i]] == 0) {
amountsIn[index2[i]] = 0;
}
}

cumulativeAmount = cumulativeAmount + amountsIn[index2[i]];
if (cumulativeAmount == amountIn) break;
if (_isZero(amountsOutSingleEth[index2[_dec(i)]])) break;
Expand Down Expand Up @@ -706,9 +680,6 @@ contract MevEthRouter is IUniswapV3SwapCallback, IMevEthRouter {
virtual
returns (uint256 amountInActual, uint256 amountOut)
{
// bytes memory data = abi.encodePacked(tokenIn, tokenOut, fee);
// uint160 sqrtPriceLimitX96 = isReverse ? MAX_SQRT_RATIO - 1 : MIN_SQRT_RATIO + 1;

try IUniswapV3Pool(pair).swap(
to, !isReverse, int256(amountIn), isReverse ? MAX_SQRT_RATIO - 1 : MIN_SQRT_RATIO + 1, abi.encodePacked(tokenIn, tokenOut, fee)
) returns (int256 amount0, int256 amount1) {
Expand All @@ -719,36 +690,6 @@ contract MevEthRouter is IUniswapV3SwapCallback, IMevEthRouter {
}
}

function _swapUniV3Call(
bool isReverse,
uint24 fee,
address tokenIn,
address tokenOut,
uint256 amountIn
)
internal
view
virtual
returns (uint256 amountOut)
{
// uint160 sqrtPriceLimitX96 = isReverse ? MAX_SQRT_RATIO - 1 : MIN_SQRT_RATIO + 1;
IQuoterV2.QuoteExactInputSingleParams memory quoterParams = IQuoterV2.QuoteExactInputSingleParams({
tokenIn: tokenIn,
tokenOut: tokenOut,
amountIn: amountIn,
fee: fee,
sqrtPriceLimitX96: isReverse ? MAX_SQRT_RATIO - 1 : MIN_SQRT_RATIO + 1
});
// bytes memory input = abi.encodeWithSelector(quoter.quoteExactInputSingle.selector, quoterParams);
// (bool success, bytes memory data) = address(quoter).staticcall(input);
(bool success, bytes memory data) = address(quoter).staticcall(abi.encodeWithSelector(quoter.quoteExactInputSingle.selector, quoterParams));
if (!success) {
amountOut = 0;
} else {
(amountOut) = abi.decode(data, (uint256));
}
}

/// @dev Internal core swap. Requires the initial amount to have already been sent to the first pair (for v2 pairs).
/// @param useQueue Use queue or not for withdrawals
/// @param to Address of receiver
Expand All @@ -765,10 +706,8 @@ contract MevEthRouter is IUniswapV3SwapCallback, IMevEthRouter {
for (uint256 j; j < 2; j = _inc(j)) {
amountIn = swaps.pools[j].amountIn;
if (_isNonZero(amountIn)) {
// uint256 balBefore = ERC20(swaps.tokenOut).balanceOf(to);
_swapSingle(swaps.isDeposit, to, swaps.pools[j].pair, swaps.pools[j].amountOut); // single v2 swap
amounts[1] = amounts[1] + swaps.pools[j].amountOut;
// amounts[1] = amounts[1] + ERC20(swaps.tokenOut).balanceOf(to) - balBefore;
}
}
// V3 swaps
Expand Down Expand Up @@ -799,9 +738,7 @@ contract MevEthRouter is IUniswapV3SwapCallback, IMevEthRouter {
amountIn = swaps.pools[5].amountIn;
if (_isNonZero(amountIn)) {
IVault.SingleSwap memory singleSwap = IVault.SingleSwap(poolId, IVault.SwapKind.GIVEN_IN, swaps.tokenIn, swaps.tokenOut, amountIn, new bytes(0));

IVault.FundManagement memory fund = IVault.FundManagement(address(this), false, payable(to), false);
// todo: calc limit
if (swaps.tokenIn == address(WETH09)) {
WETH09.approve(address(BAL), amountIn);
} else {
Expand Down
67 changes: 67 additions & 0 deletions test/MevEthRouter2.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/// SPDX-License-Identifier: UNLICENSED

pragma solidity >=0.8.13 <0.9.0;

import "forge-std/Test.sol";
import { Vm } from "forge-std/Vm.sol";
import { MevEthRouter } from "../src/MevEthRouter.sol";
import { IUniswapV2Pair } from "../src/interfaces/IUniswapV2Pair.sol";
import { IWETH } from "../src/interfaces/IWETH.sol";
import { IMevEth } from "../src/interfaces/IMevEth.sol";
import { IMevEthRouter } from "../src/interfaces/IMevEthRouter.sol";
import { ERC20 } from "solmate/tokens/ERC20.sol";

/// @title MevEthRouter2Test use different fork for cross check
contract MevEthRouter2Test is DSTest {
using stdStorage for StdStorage;

string RPC_ETH_MAINNET = vm.envString("RPC_MAINNET");
uint256 FORK_ID;
StdStorage stdstore;
Vm internal constant vm = Vm(HEVM_ADDRESS);
MevEthRouter router;
address WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
IMevEth internal constant MEVETH = IMevEth(0x24Ae2dA0f361AA4BE46b48EB19C91e02c5e4f27E);

IWETH weth = IWETH(WETH);
uint256 minLiquidity = uint256(1000);

function setUp() public {
FORK_ID = vm.createSelectFork(RPC_ETH_MAINNET);
router = new MevEthRouter(0x617c8dE5BdE54ffbb8d92716CC947858cA38f582);
}

function writeTokenBalance(address who, address token, uint256 amt) internal {
stdstore.target(token).sig(ERC20(token).balanceOf.selector).with_key(who).checked_write(amt);
}

receive() external payable { }

/// @dev Fuzz test amountOut, Stake and redeem
function testStakeAndRedeem(uint80 amountIn) external {
vm.assume(amountIn > 0.1 ether);
vm.assume(amountIn < 100_000 ether);
vm.deal(address(this), amountIn);
// test getting swap route
bytes memory input = abi.encodeWithSelector(router.amountOutStake.selector, amountIn);
(, bytes memory data) = address(router).staticcall(input);
(uint256 amountOut, IMevEthRouter.Swap memory swaps) = abi.decode(data, (uint256, IMevEthRouter.Swap));
assertGt(amountOut, MEVETH.previewDeposit(amountIn) * 999 / 1000);
// test stake
uint256 shares = router.stakeEthForMevEth{ value: amountIn }(address(this), amountIn, amountOut * 99 / 100, block.timestamp, swaps);
assertGt(shares, amountOut * 99 / 100);
// test redeem route
bool useQueue;
if (amountIn > 15 ether) {
useQueue = true;
}
input = abi.encodeWithSelector(router.amountOutRedeem.selector, useQueue, shares);
(, data) = address(router).staticcall(input);
(amountOut, swaps) = abi.decode(data, (uint256, IMevEthRouter.Swap));
assertGt(amountOut, MEVETH.previewRedeem(shares) * 95 / 100);
// test redeem
ERC20(address(MEVETH)).approve(address(router), shares);
uint256 assets = router.redeemMevEthForEth(useQueue, address(this), shares, amountOut * 99 / 100, block.timestamp, swaps);
assertGt(assets, 0);
}
}

0 comments on commit 77b1f83

Please sign in to comment.