-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test: btt tests for swap exact amount in #149
Conversation
│ └── it should revert | ||
├── when returned tokenOut is less than minAmountOut | ||
│ └── it should revert | ||
└── when preconditions are met |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ooops, realized I'm not triggering BPool_SpotPriceBeforeAboveTokenRatio
. Looking into it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the reason behind that check and the MAX_{IN,OUT}_RATIO
ones sure looks like could be fun properties 👀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think the rationale is avoiding fat fingers, meaning buying more than 50% of the available tokens, or selling more than 50% of the pool balance
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to find parameters to trigger this particular error and wasn't able to: https://www.desmos.com/calculator/onhfxbfljk
@drgorillamd you think it would be possible to formally prove this is unreachable?
I did notice that there is one testcase for swapExactAmountOut
, will look into it when testing that method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to be clear, we're not planning on removing the check even if we find it unreachable, but we can then skip the test, or add a comment in the test explaining the current behaviour
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to find parameters to trigger this particular error and wasn't able to: https://www.desmos.com/calculator/onhfxbfljk
@drgorillamd you think it would be possible to formally prove this is unreachable?
I did notice that there is one testcase for
swapExactAmountOut
, will look into it when testing that method
Quickly tried with Halmos but there are some loops hiding in bnum, so I'll try with Kontrol instead (Echidna seemds to find some cases tho, for small token amount in esp, will double-check tomorrow along Kontrol tho)
├── when spot price before swap exceeds maxPrice | ||
│ └── it should revert | ||
├── when spot price after swap exceeds maxPrice | ||
│ └── it should revert |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't there an intermediary step? if spot price before exceeds spot price after? 🤔
i do think this error is unreachable, but perhaps with smock we can have a chance of getting to it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think we should make the spot price check after the returned tokenOut (to keep consistency with order of reverts)
mhhh for the zero variable hence division by zero, if they happen in the tested method i'd include them, if they happen in an underlying one i'd leave them for the specific test |
│ └── it should revert | ||
├── when token out is not bound | ||
│ └── it should revert | ||
├── when token in exceeds max allowed ratio |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*token amount in
│ └── it should revert | ||
├── when spot price after swap exceeds maxPrice | ||
│ └── it should revert | ||
├── when returned tokenOut is less than minAmountOut |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when calculated token amount out is less than min
├── when spot price after swap exceeds maxPrice | ||
│ └── it should revert | ||
├── when spot price before swap exceeds token ratio after swap | ||
│ └── it should revert |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing BPool_SpotPriceAfterBelowSpotPriceBefore
revert (also unreachable but perhaps mockable)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mathematically it seems unreachable, and in order to mock it I should:
- make
calcSpotPrice
virtual - manually override it in the mocking for
BPool
to force an external call - insert a mock for the call with the second set of parameters to return a value lower than for the first one. Thankfully the parameters are different in each invocation, so a regular
mockCall
can take care of it and we wouldn't have to make a custom override counting calls.
Adding a skipped test to be explicit about it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looking good, let's see how it goes after merging #148
// overriding `calcSpotPrice` in a mock: | ||
// P_{sb} = \frac{\frac{b_i}{w_i}}{\frac{b_o}{w_o}} | ||
// P_{sa} = \frac{\frac{b_i + a_i}{w_i}}{\frac{b_o - a_o}{w_o}} | ||
// ...and both a_i (amount in) and a_o (amount out) are uints |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@drgorillamd another proving candidate?
@@ -818,230 +818,6 @@ contract BPool_Unit_GetSpotPriceSansFee is BasePoolTest { | |||
} | |||
} | |||
|
|||
contract BPool_Unit_SwapExactAmountIn is SwapExactAmountInUtils { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw I plan on taking care of the BCoWPool.verify
tests, which rely on SwapExactAmountInUtils
next, so we can get rid of the abstract contract as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually i saw today that many of the Utils.sol methods are unused, so we should make a cleaning after getting the final coverage
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
making a list in BAL-155
function test_RevertWhen_SpotPriceBeforeSwapExceedsTokenRatioAfterSwap() external { | ||
// it should revert | ||
vm.expectRevert(IBPool.BPool_TokenAmountOutBelowMinOut.selector); | ||
bPool.swapExactAmountIn(tokenIn, tokenAmountIn, tokenOut, expectedAmountOut + 1, spotPriceAfterSwap); | ||
vm.skip(true); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this one appears to be reachable in current tests
test/unit/BPool.t.sol
Outdated
@@ -818,195 +818,6 @@ contract BPool_Unit_GetSpotPriceSansFee is BasePoolTest { | |||
} | |||
} | |||
|
|||
contract BPool_Unit_ExitPool is BasePoolTest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think this is not the test you should be erasing in this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
~~ 😨 ~~ hold on, I'm not seeing this in the diff 👀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahh perhaps was on the "merging dev" commit
// it should revert | ||
vm.skip(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
have a set of values that triggers this :)
// it should revert | |
vm.skip(true); | |
uint256 tokenAmountIn_ = 30e18; | |
uint256 balanceTokenIn_ = 36830000000000000000000000000000; | |
uint256 weightTokenIn_ = 1e18; | |
uint256 balanceTokenOut_ = 18100000000000000000000000000000; | |
uint256 weightTokenOut_ = 1e18; | |
uint256 swapFee_ = 0.019e18; | |
vm.mockCall(tokenIn, abi.encodePacked(IERC20.balanceOf.selector), abi.encode(uint256(balanceTokenIn_))); | |
vm.mockCall(tokenOut, abi.encodePacked(IERC20.balanceOf.selector), abi.encode(uint256(balanceTokenOut_))); | |
bPool.set__records(tokenIn, IBPool.Record({bound: true, index: 0, denorm: weightTokenIn_})); | |
bPool.set__records(tokenOut, IBPool.Record({bound: true, index: 1, denorm: weightTokenOut_})); | |
bPool.set__swapFee(swapFee_); | |
// it should revert | |
vm.expectRevert(IBPool.BPool_SpotPriceBeforeAboveTokenRatio.selector); | |
bPool.swapExactAmountIn(tokenIn, tokenAmountIn_, tokenOut, 0, type(uint256).max); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how did you generate this? a fuzz run?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i used the fuzzer of legacy swapExactAmountIn
tests to generate a counterproof, to hit the specific revert a combination of testFail
and vm.expectRevert
can be used
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rocking it pal! 👏
the user not having enough
tokenIn
would revert on_pullUnderlying
, perhaps it's better test modularization to not test that flow here, but with_pullUnderlying
? tree has less branches this way, but it's less descriptive of domain cases and isn't consistent with what I just did onexitPool
do you think it's worthwhile to test the cases where
tokenIn.balanceOf(pool) == 0
?tokenOut.balanceOf(pool) == 0
? combined withtokenAmountIn == 0
it could cause a division by zero incalcOutGivenIn
closes BAL-142