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 /// @notice Internal counterpart of _getLimits
/// @dev As Integral also has minimum limits of sell/buy amounts, we return them too. /// @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 /// @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) { 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); uint256[] memory limits_ = new uint256[](4);
limits_[0] = limitMax0; limits_[0] = limitMax0;
limits_[1] = limitMax1; limits_[1] = limitMax1;
limits_[2] = limitMin0; limits_[2] = (limitMin0 * 115 / 100);
limits_[3] = limitMin1; limits_[3] = (limitMin1 * 103 / 100);
return limits_; return limits_;
} }

View File

@@ -5,7 +5,7 @@ import "forge-std/Test.sol";
import "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import "openzeppelin-contracts/contracts/interfaces/IERC20.sol";
import "src/interfaces/ISwapAdapterTypes.sol"; import "src/interfaces/ISwapAdapterTypes.sol";
import "src/libraries/FractionMath.sol"; import "src/libraries/FractionMath.sol";
import "src/integral/IntegralSwapAdapterFix.sol"; import "src/integral/IntegralSwapAdapter.sol";
contract IntegralSwapAdapterTest is Test, ISwapAdapterTypes { contract IntegralSwapAdapterTest is Test, ISwapAdapterTypes {
using FractionMath for Fraction; using FractionMath for Fraction;
@@ -48,98 +48,13 @@ contract IntegralSwapAdapterTest is Test, ISwapAdapterTypes {
} }
} }
function testPriceDecreasingIntegral() public { /// @dev Since TwapRelayer's calculateAmountOut function is internal, and using quoteSell would
bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR)); /// revert the transaction if calculateAmountOut is not enough,
uint256[] memory amounts = new uint256[](TEST_ITERATIONS); /// we need a threshold to cover this internal amount, applied to
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))
);
}
}
function testSwapFuzzIntegral(uint256 specifiedAmount, bool isBuy) public { function testSwapFuzzIntegral(uint256 specifiedAmount, bool isBuy) public {
// Fails at times | FAIL. Reason: revert: TR03;
//
//
OrderSide side = isBuy ? OrderSide.Buy : OrderSide.Sell; OrderSide side = isBuy ? OrderSide.Buy : OrderSide.Sell;
bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR)); 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( function testGetCapabilitiesIntegral(
bytes32 pair, bytes32 pair,
address t0, address t0,
@@ -249,6 +156,13 @@ contract IntegralSwapAdapterTest is Test, ISwapAdapterTypes {
assertEq(res.length, 3); 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 { function testGetLimitsIntegral() public {
bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR)); bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR));
uint256[] memory limits = adapter.getLimits(pair, USDC, WETH); uint256[] memory limits = adapter.getLimits(pair, USDC, WETH);