Skip to content
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

Slippage limit does not seem to hold, or price impact is incorrect #338

Open
sitwano opened this issue Jun 24, 2023 · 4 comments
Open

Slippage limit does not seem to hold, or price impact is incorrect #338

sitwano opened this issue Jun 24, 2023 · 4 comments
Labels
bug Something isn't working

Comments

@sitwano
Copy link

sitwano commented Jun 24, 2023

Describe the bug
As title. I set the slippage to 0.05%, however looking at arbiscan I get a slippage that is up to 2%. For example, here is my recent swap: 0x26d30e23fab9edea1b16e324fa1364377b51b29026b21866619b6f32c93fc06e.
I suspected it was the slippage that was the problem, since the price impact function showed me 0.11%. Unless maybe the price impact was calculated incorrectly... not sure.

I use a loop to keep retying the swap (up to 10 times) if it fails. I get "execution reverted: Too little received" error 5-6 times before the 7th try was successful.

SWAP DETAILS on arbiscan:
1,380.729352 USDC
to
0.715545115632159099 ETH (1343.72 estimated value at time of swap)

Net loss from swap: 2.17%

To Reproduce
Not really sure how to reproduce this... I guess swap USDC for ETH on arbitrum with a 0.05% slippage and see what happens during times of high price movement.

Expected behavior
The max slippage limit should hold, so if the amount is exceeded, the transaction should revert.

@sitwano sitwano added the bug Something isn't working label Jun 24, 2023
@sitwano sitwano changed the title Slippage limit does not seem to hold Slippage limit does not seem to hold, or price impact is incorrect Jun 24, 2023
@ErikBjare
Copy link
Member

ErikBjare commented Jun 24, 2023

Thanks for reporting this and including a tx!

I'm a bit baffled by this. Could you share the exact code for the relevant calls?

Trying to think of a way to write a test for this. Probably doable within our current testing framework, but would be easier if we had finished implemented creating LP positions for V3.

@liquid-8
Copy link
Member

As far as I can see, it is neither a slippage nor price impact correctness issue. Let's take a look. I got the price impact for a liq pool. Now I'm going to swap tokens, so I'm calling a price fetching function to receive params for swap. Generally speaking, people could make some actions inter price-impact and price-fetching calls. In this case, the pool's liquidity state would be altered; hence my swap would make a different impact. This situation could occur on rare occasions on the main net. However, it has a much higher probability in L2 rollups due to their blocks producing time, which is significantly shorter. Likely, it's worth considering performing call batches while controlling if all calls are executed within the same block.

Still would like to see the exact code too.

@sitwano
Copy link
Author

sitwano commented Jul 6, 2023

Hi thank you very much for the response. The code i used is quite simple. Sorry, I can't seem to get the formatting right for the code below. As you can see, all I am trying to do is recalculate the maximum amount i can lose (impact + slippage + gas fee) and then try the swap. If swap fails, then I just repeat until successful.

`
def buy_safety_check(my_uniswap, quantity):

original, actual, minimum , impact = get_usdc_eth_rate(my_uniswap, quantity)

max_price_diff = original- minimum

if(original > 0):
    max_price_diff_perc = 100* max_price_diff/original
    
    my_gas_fee = get_gas_estimate(my_uniswap, eth, usdc)

    if((max_price_diff_perc >= 0.15) | (my_gas_fee > MAX_GAS_FEE)):
        return False, max_price_diff_perc, my_gas_fee
    else:
        return True, max_price_diff_perc, my_gas_fee
else:
    return False, max_price_diff_perc, my_gas_fee

while(attempt < MAX_SWAP_ATTEMPTS):

        try:

            safety_check, max_impact, gas_fee_estimate = buy_safety_check(my_uniswap, token_max_quantity)

            if(safety_check == True):    
                tx = my_uniswap.make_trade(usdc, swap_token, token_max_quantity_usdc, fee = default_swap_fee, slippage = default_slippage)
                my_tx = str(tx.hex())
                print("SWAP SUCCESSFUL: " + my_tx)
                return token_max_quantity_usdc/10**6, True, my_tx, max_impact, gas_fee_estimate
            else:
                msg = "Retrying buy order: bad exchange rate. Impact:" + str(max_impact) +"%"
                print(msg)
                sleep(60)
        
        except Exception as e:
            attempt = attempt + 1
            print(e)
            print("SWAP ERROR. RETRY...")
            sleep(10)`

@liquid-8
Copy link
Member

Sorry for the delay. From what I see, it's ok. The code should work as intended if get_usdc_eth_rate() is implemented correctly. I must note that both slippage and impact implementation are fine, as I use the same logic in production with zero issues, at least at L1 networks. Still tend to believe you were trapped in something like I described earlier. I'll try to wrap my head around it; however, I can't promise a quick solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants