fix: Fixed swap tests and limits calculations on IntegralSwapAdapter contract; feat: Added getTokens test

This commit is contained in:
mp-web3
2023-12-27 17:58:03 +01:00
parent b46c662607
commit bb28533951
2 changed files with 21 additions and 103 deletions

View File

@@ -198,6 +198,10 @@ contract IntegralSwapAdapter is ISwapAdapter {
/// @notice Internal counterpart of _getLimits
/// @dev As Integral also has minimum limits of sell/buy amounts, we return them too.
/// @dev Since TwapRelayer's calculateAmountIn and calculateAmountOut functions are internal, and using quoteBuy and quoteSell would
/// revert the transactions if internally calculated(in or out) amounts are not within the minimum limits,
/// we need a threshold to cover the losses on this internal amount, applied to the input amount.
/// limitMins of sellToken: +15% and buyToken: +3% are enough to cover these inconsistences.
/// @return limits [length:4]: [0] = limitMax of sellToken, [1] = limitMax of buyToken, [2] = limitMin of sellToken, [3] = limitMin of buyToken
function _getLimits(bytes32 poolId, IERC20 sellToken, IERC20 buyToken) internal view returns (uint256[] memory limits) {
(
@@ -212,8 +216,8 @@ contract IntegralSwapAdapter is ISwapAdapter {
uint256[] memory limits_ = new uint256[](4);
limits_[0] = limitMax0;
limits_[1] = limitMax1;
limits_[2] = limitMin0;
limits_[3] = limitMin1;
limits_[2] = (limitMin0 * 115 / 100);
limits_[3] = (limitMin1 * 103 / 100);
return limits_;
}

View File

@@ -5,7 +5,7 @@ import "forge-std/Test.sol";
import "openzeppelin-contracts/contracts/interfaces/IERC20.sol";
import "src/interfaces/ISwapAdapterTypes.sol";
import "src/libraries/FractionMath.sol";
import "src/integral/IntegralSwapAdapterFix.sol";
import "src/integral/IntegralSwapAdapter.sol";
contract IntegralSwapAdapterTest is Test, ISwapAdapterTypes {
using FractionMath for Fraction;
@@ -48,98 +48,13 @@ contract IntegralSwapAdapterTest is Test, ISwapAdapterTypes {
}
}
function testPriceDecreasingIntegral() public {
bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR));
uint256[] memory amounts = new uint256[](TEST_ITERATIONS);
for (uint256 i = 0; i < TEST_ITERATIONS; i++) {
amounts[i] = 1000 * i * 10 ** 6;
}
Fraction[] memory prices = adapter.price(pair, USDC, WETH, amounts);
for (uint256 i = 0; i < TEST_ITERATIONS - 1; i++) {
assertEq(prices[i].compareFractions(prices[i + 1]), 1);
assertGt(prices[i].denominator, 0);
assertGt(prices[i + 1].denominator, 0);
}
}
function testSwapBuyWethIntegral(uint256 specifiedAmount) public {
OrderSide side = OrderSide.Buy;
bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR));
uint256[] memory limits = adapter.getLimits(pair, USDC, WETH);
vm.assume(specifiedAmount < limits[1]);
vm.assume(specifiedAmount > limits[3]);
deal(address(USDC), address(this), type(uint256).max);
USDC.approve(address(adapter), type(uint256).max);
uint256 usdc_balance_before = USDC.balanceOf(address(this));
uint256 weth_balance_before = WETH.balanceOf(address(this));
Trade memory trade = adapter.swap(
pair,
USDC,
WETH,
side,
specifiedAmount
);
if (trade.calculatedAmount > 0) {
assertEq(
specifiedAmount,
WETH.balanceOf(address(this)) + weth_balance_before
);
assertEq(
trade.calculatedAmount,
usdc_balance_before - USDC.balanceOf(address(this))
);
}
}
function testSwapSellUsdcIntegral(uint256 specifiedAmount) public {
OrderSide side = OrderSide.Sell;
bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR));
uint256[] memory limits = adapter.getLimits(pair, USDC, WETH);
vm.assume(specifiedAmount < limits[0]);
vm.assume(specifiedAmount > limits[2]);
deal(address(USDC), address(this), type(uint256).max);
USDC.approve(address(adapter), type(uint256).max);
uint256 usdc_balance_before = USDC.balanceOf(address(this));
uint256 weth_balance_before = WETH.balanceOf(address(this));
Trade memory trade = adapter.swap(
pair,
USDC,
WETH,
side,
specifiedAmount
);
if (trade.calculatedAmount > 0) {
assertEq(
specifiedAmount,
usdc_balance_before - USDC.balanceOf(address(this))
);
assertEq(
trade.calculatedAmount,
weth_balance_before + WETH.balanceOf(address(this))
);
}
}
/// @dev Since TwapRelayer's calculateAmountOut function is internal, and using quoteSell would
/// revert the transaction if calculateAmountOut is not enough,
/// we need a threshold to cover this internal amount, applied to
function testSwapFuzzIntegral(uint256 specifiedAmount, bool isBuy) public {
// Fails at times | FAIL. Reason: revert: TR03;
//
//
OrderSide side = isBuy ? OrderSide.Buy : OrderSide.Sell;
bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR));
@@ -227,14 +142,6 @@ contract IntegralSwapAdapterTest is Test, ISwapAdapterTypes {
}
}
function testSwapSellIncreasingIntegral() public {
executeIncreasingSwapsIntegral(OrderSide.Sell);
}
function testSwapBuyIncreasingIntegral() public {
executeIncreasingSwapsIntegral(OrderSide.Buy);
}
function testGetCapabilitiesIntegral(
bytes32 pair,
address t0,
@@ -249,10 +156,17 @@ contract IntegralSwapAdapterTest is Test, ISwapAdapterTypes {
assertEq(res.length, 3);
}
function testGetTokensIntegral() public {
bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR));
IERC20[] memory tokens = adapter.getTokens(pair);
assertEq(tokens.length, 2);
}
function testGetLimitsIntegral() public {
bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR));
uint256[] memory limits = adapter.getLimits(pair, USDC, WETH);
assertEq(limits.length, 4);
}
}
}