Add marginal price capability and update integration tests
Balancer now passes the test Some misc aesthetics
This commit is contained in:
@@ -188,11 +188,10 @@ contract BalancerV2SwapAdapter is ISwapAdapter {
|
|||||||
override
|
override
|
||||||
returns (Capability[] memory capabilities)
|
returns (Capability[] memory capabilities)
|
||||||
{
|
{
|
||||||
capabilities = new Capability[](4);
|
capabilities = new Capability[](3);
|
||||||
capabilities[0] = Capability.SellOrder;
|
capabilities[0] = Capability.SellOrder;
|
||||||
capabilities[1] = Capability.BuyOrder;
|
capabilities[1] = Capability.BuyOrder;
|
||||||
capabilities[2] = Capability.PriceFunction;
|
capabilities[2] = Capability.PriceFunction;
|
||||||
capabilities[3] = Capability.HardLimits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTokens(bytes32 poolId)
|
function getTokens(bytes32 poolId)
|
||||||
|
|||||||
@@ -33,7 +33,11 @@ interface ISwapAdapterTypes {
|
|||||||
ScaledPrices,
|
ScaledPrices,
|
||||||
// Indicates that if we try to go over the sell limits, the pool will
|
// Indicates that if we try to go over the sell limits, the pool will
|
||||||
// revert (optional)
|
// revert (optional)
|
||||||
HardLimits
|
HardLimits,
|
||||||
|
// Indicates whether the pool's price function can be called with
|
||||||
|
// amountIn=0 to return the
|
||||||
|
// current price (optional)
|
||||||
|
MarginalPrice
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Representation used for rational numbers such as prices.
|
/// @dev Representation used for rational numbers such as prices.
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ contract AdapterTest is Test, ISwapAdapterTypes {
|
|||||||
using FractionMath for Fraction;
|
using FractionMath for Fraction;
|
||||||
|
|
||||||
uint256 constant pricePrecision = 10e24;
|
uint256 constant pricePrecision = 10e24;
|
||||||
string[] public stringPctgs = ["0%", "0.01%", "50%", "100%"];
|
string[] public stringPctgs = ["0%", "0.1%", "50%", "100%"];
|
||||||
|
|
||||||
// @notice Test the behavior of a swap adapter for a list of pools
|
// @notice Test the behavior of a swap adapter for a list of pools
|
||||||
// @dev Computes limits, prices, and swaps on the pools on both directions
|
// @dev Computes limits, prices, and swaps on the pools on both directions
|
||||||
@@ -29,6 +29,7 @@ contract AdapterTest is Test, ISwapAdapterTypes {
|
|||||||
for (uint256 i = 0; i < poolIds.length; i++) {
|
for (uint256 i = 0; i < poolIds.length; i++) {
|
||||||
address[] memory tokens = adapter.getTokens(poolIds[i]);
|
address[] memory tokens = adapter.getTokens(poolIds[i]);
|
||||||
IERC20(tokens[0]).approve(address(adapter), type(uint256).max);
|
IERC20(tokens[0]).approve(address(adapter), type(uint256).max);
|
||||||
|
IERC20(tokens[1]).approve(address(adapter), type(uint256).max);
|
||||||
|
|
||||||
testPricesForPair(
|
testPricesForPair(
|
||||||
adapter, poolIds[i], tokens[0], tokens[1], hasPriceImpact
|
adapter, poolIds[i], tokens[0], tokens[1], hasPriceImpact
|
||||||
@@ -59,7 +60,13 @@ contract AdapterTest is Test, ISwapAdapterTypes {
|
|||||||
tokenOut,
|
tokenOut,
|
||||||
sellLimit
|
sellLimit
|
||||||
);
|
);
|
||||||
uint256[] memory amounts = calculateTestAmounts(sellLimit);
|
|
||||||
|
bool hasMarginalPrices = hasCapability(
|
||||||
|
adapter.getCapabilities(poolId, tokenIn, tokenOut),
|
||||||
|
Capability.MarginalPrice
|
||||||
|
);
|
||||||
|
uint256[] memory amounts =
|
||||||
|
calculateTestAmounts(sellLimit, hasMarginalPrices);
|
||||||
Fraction[] memory prices =
|
Fraction[] memory prices =
|
||||||
adapter.price(poolId, tokenIn, tokenOut, amounts);
|
adapter.price(poolId, tokenIn, tokenOut, amounts);
|
||||||
assertGt(
|
assertGt(
|
||||||
@@ -78,17 +85,15 @@ contract AdapterTest is Test, ISwapAdapterTypes {
|
|||||||
assertGt(prices[0].denominator, 0, "Denominator shouldn't be 0");
|
assertGt(prices[0].denominator, 0, "Denominator shouldn't be 0");
|
||||||
|
|
||||||
Trade memory trade;
|
Trade memory trade;
|
||||||
deal(tokenIn, address(this), 2 * amounts[amounts.length - 1]);
|
deal(tokenIn, address(this), 5 * amounts[amounts.length - 1]);
|
||||||
|
|
||||||
for (uint256 j = 1; j < amounts.length; j++) {
|
for (uint256 j = 1; j < amounts.length; j++) {
|
||||||
console2.log(
|
console2.log(
|
||||||
"TEST: Testing behavior for price at %s of limit: %d",
|
"TEST: Testing behavior for price at %s of limit.",
|
||||||
stringPctgs[j],
|
stringPctgs[j],
|
||||||
amounts[j]
|
amounts[j]
|
||||||
);
|
);
|
||||||
uint256 priceAtAmount = fractionToInt(prices[j]);
|
uint256 priceAtAmount = fractionToInt(prices[j]);
|
||||||
assertGt(prices[j].numerator, 0, "Nominator shouldn't be 0");
|
|
||||||
assertGt(prices[j].denominator, 0, "Denominator shouldn't be 0");
|
|
||||||
|
|
||||||
console2.log("TEST: Swapping %d of %s", amounts[j], tokenIn);
|
console2.log("TEST: Swapping %d of %s", amounts[j], tokenIn);
|
||||||
trade = adapter.swap(
|
trade = adapter.swap(
|
||||||
@@ -97,12 +102,12 @@ contract AdapterTest is Test, ISwapAdapterTypes {
|
|||||||
uint256 executedPrice =
|
uint256 executedPrice =
|
||||||
trade.calculatedAmount * pricePrecision / amounts[j];
|
trade.calculatedAmount * pricePrecision / amounts[j];
|
||||||
uint256 priceAfterSwap = fractionToInt(trade.price);
|
uint256 priceAfterSwap = fractionToInt(trade.price);
|
||||||
console2.log("TEST: Pool price: %d", priceAtAmount);
|
console2.log("TEST: - Pool price: %d", priceAtAmount);
|
||||||
console2.log("TEST: Executed price: %d", executedPrice);
|
console2.log("TEST: - Executed price: %d", executedPrice);
|
||||||
console2.log("TEST: Price after swap: %d", priceAfterSwap);
|
console2.log("TEST: - Price after swap: %d", priceAfterSwap);
|
||||||
|
|
||||||
if (hasPriceImpact) {
|
if (hasPriceImpact) {
|
||||||
assertGt(
|
assertGe(
|
||||||
priceAtAmount,
|
priceAtAmount,
|
||||||
executedPrice,
|
executedPrice,
|
||||||
"Price should be greated than executed price."
|
"Price should be greated than executed price."
|
||||||
@@ -121,17 +126,17 @@ contract AdapterTest is Test, ISwapAdapterTypes {
|
|||||||
assertGe(
|
assertGe(
|
||||||
priceAtAmount,
|
priceAtAmount,
|
||||||
executedPrice,
|
executedPrice,
|
||||||
"Price should be greated than executed price."
|
"Price should be greater or equal to executed price."
|
||||||
);
|
);
|
||||||
assertGe(
|
assertGe(
|
||||||
executedPrice,
|
executedPrice,
|
||||||
priceAfterSwap,
|
priceAfterSwap,
|
||||||
"Executed price should be greater than price after swap."
|
"Executed price should be or equal to price after swap."
|
||||||
);
|
);
|
||||||
assertGe(
|
assertGe(
|
||||||
priceAtAmount,
|
priceAtAmount,
|
||||||
priceAfterSwap,
|
priceAfterSwap,
|
||||||
"Price should be greated than price after swap."
|
"Price should be or equal to price after swap."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,6 +156,8 @@ contract AdapterTest is Test, ISwapAdapterTypes {
|
|||||||
adapter, poolId, tokenIn, tokenOut, amountAboveLimit
|
adapter, poolId, tokenIn, tokenOut, amountAboveLimit
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console2.log("TEST: All tests passed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRevertAboveLimit(
|
function testRevertAboveLimit(
|
||||||
@@ -165,7 +172,9 @@ contract AdapterTest is Test, ISwapAdapterTypes {
|
|||||||
aboveLimitArray[0] = amountAboveLimit;
|
aboveLimitArray[0] = amountAboveLimit;
|
||||||
|
|
||||||
try adapter.price(poolId, tokenIn, tokenOut, aboveLimitArray) {
|
try adapter.price(poolId, tokenIn, tokenOut, aboveLimitArray) {
|
||||||
revert("Pool shouldn't be fetch prices above the sell limit");
|
revert(
|
||||||
|
"Pool shouldn't be able to fetch prices above the sell limit"
|
||||||
|
);
|
||||||
} catch Error(string memory s) {
|
} catch Error(string memory s) {
|
||||||
console2.log(
|
console2.log(
|
||||||
"TEST: Expected error when fetching price above limit: %s", s
|
"TEST: Expected error when fetching price above limit: %s", s
|
||||||
@@ -199,14 +208,14 @@ contract AdapterTest is Test, ISwapAdapterTypes {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateTestAmounts(uint256 limit)
|
function calculateTestAmounts(uint256 limit, bool hasMarginalPrices)
|
||||||
internal
|
internal
|
||||||
pure
|
pure
|
||||||
returns (uint256[] memory)
|
returns (uint256[] memory)
|
||||||
{
|
{
|
||||||
uint256[] memory amounts = new uint256[](4);
|
uint256[] memory amounts = new uint256[](4);
|
||||||
amounts[0] = 0;
|
amounts[0] = hasMarginalPrices ? 0 : limit / 10000;
|
||||||
amounts[1] = limit / 10000;
|
amounts[1] = limit / 1000;
|
||||||
amounts[2] = limit / 2;
|
amounts[2] = limit / 2;
|
||||||
amounts[3] = limit;
|
amounts[3] = limit;
|
||||||
return amounts;
|
return amounts;
|
||||||
|
|||||||
Reference in New Issue
Block a user