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

priceToken1 and priceToken2 utility? #5

Closed
atrhacker opened this issue Jun 24, 2021 · 14 comments
Closed

priceToken1 and priceToken2 utility? #5

atrhacker opened this issue Jun 24, 2021 · 14 comments

Comments

@atrhacker
Copy link

Hi,

First of all, thank you for your work. really interesting to see how you approach this arbitrage matter.
By reading your code, everything is clear, except the following
priceToken1 (and by extension priceToken1Eth) and the same for priceToken2
What are they used for if you already determine the price of token based on the available reserve of the pair?
Moreover, why using an env var to store them while they are dynamic?
Finally, they are used to determine if the trade is gonna be profitable. But the trade is gonna be profitable is the difference is positive?

I guess I'm missing something, so don't hesitate to let me know your thoughts.
Thanks again and have a nice day,

Anselme

@6eer
Copy link
Owner

6eer commented Jun 24, 2021

To be honest I don't know if I do the math properly, I think I did but, who knows, could have made mistakes, to much units & ratios, so be aware but, said that, let started.

priceToken1 (and by extension priceToken1Eth) and the same for priceToken2
What are they used for if you already determine the price of token based on the available reserve of the pair?

priceToken is the price on usd of the tokens so, the units are usd/token, I mean, how many dolars per 1 token.
priceTokenEth its equal to priceToken * 1/priceEth, here priceToken is, again, usd/token, priceEth its usd/eth so 1/priceEth is eth/usd, then the product priceToken * 1/priceEth is usd/token * eth/usd = eth/token, the price of the token expressed on eth.

What are they used for if you already determine the price of token based on the available reserve of the pair?

If Im not wrong the price on a pool is the ratio reservesToken0/reservesToken1 but the units of this ratio are token0/token1, so following the same reasoning that with usd/token bellow, token0/token1 is the price of token1 expressed on token0, how much token0 do u need to buy 1 token1. So keep this in mind while moving to the next question (its related)

Finally, they are used to determine if the trade is gonna be profitable. But the trade is gonna be profitable is the difference is positive?

Its a bit confusing this but I will try to be clear, the variable difference is a ratio token0/token1 or token1/token0 depends on the trade direction, for our example suppose we are working with token0/token1, in this context this means how many token0 u receive for 1 token1, it can be less than 1 o higher, depends on the quantities that u are trading. Then this ratio its multiply by the amount of token1 u are trading, this is I named totalDiffrence and the units here are token0/token1 * token1 = token0. Now to know if the trade is profitable u multiply the amount of token0 that u gets by its price in eth (priceToken0Eth), so this is how many ether u will be doing with the trade, the only thing that u must subtract are the gas u will be using to execute the arbitrage, the unit of gas is eth, so if (totalDifference*priceToken1Eth)-gasCost > 0, there is indeed a profitable trade.

Moreover, why using an env var to store them while they are dynamic?

this is an arbitrary decision, probably in production u will be getting this prices from an exchange API or similar, but for simplicity I kept them there.

I hope I have been able to help you, otherwise let me know.

@atrhacker
Copy link
Author

atrhacker commented Jun 25, 2021

Thanks for your explanation.. it all makes sense until I try it out and each time I have an error..
'UniswapV2: K' error or 'ERC20: transfer amount exceeds balance'

...
Did it work for you on your local tesnet?
The only thing I modified was to remove the following reference

import 'sushiswap/contracts/uniswapv2/libraries/UniswapV2Library.sol';

it’s not used so not needed right?
Also when I deploy I made sure to pass the proper contract factory and router address in the constructor of the arbitrage contract.

very frustrating I have been trying to do a flashswap for days but I’m not able to make it work.

Thanks again a d have a nice day

@6eer
Copy link
Owner

6eer commented Jun 26, 2021

'UniswapV2: K' error or 'ERC20: transfer amount exceeds balance'

Hmm, I dont know why this happen.

The 'UniswapV2: K' error is trigger by the swap method on the uniswap pair contract, and its fired when u dont send back enough tokens to pay back the flashloan (in this case arbitrager.sol should be transferring back the tokens needed and in fact, in my local fork, do it properly).

The 'ERC20: transfer amount exceeds balance' its triggered by the transfer method in the erc20 tokens, in this case i suppose that the arbitrager contract it trying to transfer more tokens that it owns.

Regarding the first error, the amount tokens that are needed to pay back the flashloan depends on the amount u are withdrawing and the current reserves of both tokens in the pool, so, if u are working on a testnet & if

  1. a block is mined after u make the this calculation (currently this computation is made by the bots, off chain) but before of execute the trade &
  2. this block included a transaction that changed the reserves of the pool,

I suppose this makes the amount of tokens, that the bots previously computed, be wrong, im not sure, im just thinking. If this is the case, a possible solution i think it will be make this computation on chain in the arbitrager contract and not in the bots because it will be using the 'real/current' reserves amounts, I think I need to change this.

For the other error Im not sure whats happening, maybe its related to the first one, but really I dont know.

Did it work for you on your local testnet?

yeah, of course!

it’s not used so not needed right?

right! I forgot to clean up that.

very frustrating I have been trying to do a flashswap for days but I’m not able to make it work.

U tried the demos?

@atrhacker
Copy link
Author

I will try the demos today. However, I did not change anything on the solidity side.
The only difference is I'm trying this directly on polygon mainnet.
I think my issue is that before the transaction is mined and I send it, the pool is rebalanced.
Example:
I sent the transaction based on a price difference of Block 16165870 but the arbitrage transaction got mined on block 16169347.. it's pretty long..
Even I put the gas price a 1500 gwei (normally it's around 1 gwei for polygon)
In this case, that for sure that the arbitrage is no longer valid after such a period, especially if the pair is traded a lot..

I will try to fork a archive node on polygon and let you know.

I'm just wondering If there is actual arbitrage opportunity via this approach on any mainnet (polygon or eth), or is it only a proof of concept but not really replicable on prod..

@atrhacker
Copy link
Author

Well, I just tried it on a fork from polygon mainnet with archive on ganache and it worked like a charm without any edit (except the pairs used by your demo)

so it seems to be due to the fact that on production: difference between two dex will be very minor (on your pair the difference of price is very significant) and therefore you transaction has to be very quick... on this you cannot so much have control or any suggestion are welcome.

As you can see even I put a number of gas, significant, the transaction waited more than 200 block before getting mined:
Gas Limit: 600,000 Gas Used by Transaction: 193,587 (32.26%) Gas Price: 0.0000015 MATIC (1,500 Gwei)

Don't hesitate to suggest anything I should do differently. But again thanks for your feedbacks and work, as you mentioned it's still a very good exercise to get deep into several aspect of the eth blockchains

@alvarheras
Copy link

Hello @atrhacker @6eer

I don't know if the concept is really well served. On the one hand I have doubts to use the oracle of reading prices in the blocks. For me it is not very successful in this regard. It would be a good option if you already have the sdk price of uniswap and sushiswap in this case. Do not you think?

On the other hand the use of 2 transactions. You should only sign one and operate with the contract.

@atrhacker
Copy link
Author

atrhacker commented Jun 28, 2021

I think getting the price in USD is not really needed at the end. If you take the two pairs on each platform and make sure that there is a difference that's already a profit. (minus the gas cost of course)

after further deep testing I have come to the following findings on prod:
When you receive a block, it's very likely that the next block has been already mined.
In my various test and forked from the mainnet (using moralis free node with archive) I have the following example:
Pair with a small profit if arbitrage is done on block 16247625
Logic is done and transaction sent with 1500 gwei
transaction is mined on block 16247629 the arbitrage opportunity was already obsolete at block 16247627

Therefore, I believe that listening on the new block event is probably already too late (latency is too important), especially that in your backend logic we still query some stuff on-chain which can take time.
Maybe something can be done by directly listening to the transactions pools to have similar behaviors as front-running bot but even there I believe there is a strong chance that once the transaction is mined it's obsolete.

@6eer
Copy link
Owner

6eer commented Jun 28, 2021

@alvarheras

On the other hand the use of 2 transactions. You should only sign one and operate with the contract.

I think u are right

@atrhacker

I think getting the price in USD is not really needed at the end. If you take the two pairs on each platform and make sure that there is a difference that's already a profit. (minus the gas cost of course)

I agree, the only thing u need is the profit in eth, so u can subtract the gas cost.

Maybe something can be done by directly listening to the transactions pools to have similar behaviors as front-running bot but even there I believe there is a strong chance that once the transaction is mined it's obsolete.

This sounds good but is beyond my scope, I never talked with a transaction pool. A thing to keep in mind is, just because u cant know when a transaction, that erase the arbitrage opportunity, will appear neither the order/when your transaction will be mined, the pairs that present best arbitrage opportunities are the less traded, just because the coins or, the exchange involved, are not used too much. This maybe sounds kinda silly but I think it's a key issue or at least to take some time to research whats pairs to observe.

@alvarheras
Copy link

I think that through the sliding of the price you could try to force uniswap through the swapExactETHForTokens method or others of Exact to obtain a higher price than the one offered in its UI.

I understand that if the price slippage is 1% and it is offered to me for x ETH 200 DAI through the exchange method, I could try to receive an amount of 202.

I have seen how some arbitrage bots sometimes receive different prices than what the uniswap UI offers on their page.

I keep looking for information on how they calculate the amount of dynamics they exchange in some cases.

@interzone2
Copy link

interzone2 commented Aug 12, 2021

Hi, thanks for your contribution to this issue, it has helped me quite a bit.

I'd like to ask what you needed to alter to get this running on Polygon? We'd need two DEX's and two tokens common to both DEX's - which though? - There's Polywhale and Quickswap - would it work with those? And regards addresses we'd need to swap out everything in the original build as we are dealing with MATIC nothing ETH related? Any thoughts greatly appreciated!

I got the demo (of Uniswap Sushiswap) running on fork of ganache eth-mainnet hough no arb ops are reported at all.. so need to figure that out too..

Well, I just tried it on a fork from polygon mainnet with archive on ganache and it worked like a charm without any edit (except the pairs used by your demo)

so it seems to be due to the fact that on production: difference between two dex will be very minor (on your pair the difference of price is very significant) and therefore you transaction has to be very quick... on this you cannot so much have control or any suggestion are welcome.

As you can see even I put a number of gas, significant, the transaction waited more than 200 block before getting mined:
Gas Limit: 600,000 Gas Used by Transaction: 193,587 (32.26%) Gas Price: 0.0000015 MATIC (1,500 Gwei)

Don't hesitate to suggest anything I should do differently. But again thanks for your feedbacks and work, as you mentioned it's still a very good exercise to get deep into several aspect of the eth blockchains

@atrhacker
Copy link
Author

to get it running on polygon, you mainly need to change the address of the different router and factory contract to match those on polygon. it should work the same for quickswap as it's a clone of uniswap v2. (probably polywhale as well)
to find the contract address, you need to find their github or ask directly on their telegram or discord.
and yes every address should be the one which are on polygon.
Good luck.

But bottom lines is for me after a couple of days of monitoring even if I had some arbitrage opportunity, the bot never succeeded to be fast enough to fill the gaps.
There probably a more complex but more reliable approach based on the pool of pending transactions... but this is tricky... all the best.

@Centori
Copy link

Centori commented Aug 23, 2021

Hi,

Thanks for this write up.I am relatively new to the arbitrage flashloan bots.I was hoping you could explain in a bit more detail how to successfully code the steps for the prodcution ready bot below:

1.Its very important that you set up an appropriate value to amountOutMin on....

for safety reasons, if not you could be losing money. see Uniswap docs for more info. (This function is used in bot_normalswap.js and Arbitrager.sol).

You probably wanna embedded the logic available at Utils.sol on the bots scripts, avoiding the cost of deploy the Utils contract.

3.Use child process for each block.

4.Select the pools automatically based on, for example, the amount of arbitrage opportunities in the past.

Thanks.

@oussaki
Copy link

oussaki commented Dec 26, 2021

Any one alive here ? the owner of the repository is not responsive so i wanted to discuss something with people here

it's about calculating profitability

The owner said : "if (totalDifference*priceToken1Eth)-gasCost > 0, there is indeed a profitable trade."

i don't agree on this because when we're sending the transaction for swapping we are sending the calculated amountIn

and totalDifference = difference*Number(ethers.utils.formatUnits(amountIn, 18)) that is used to calculate the profit and i think this calculation is wrong.

because i managed to find some arbitrage opportunities with this but seems not being calculated properly.
I've been testing and improving this bot for more than 2 months now. i executed an arbitrage before without modifying the original script and i benefited a worth of 20$ but i paid like 90$ in fees , so i basically lost 79$ for that.

i could be wrong. @atrhacker @alvarheras @Centori @interzone2

@mohamedmamo
Copy link

Screenshot_11

Please help me with this line I don't understand what I should do and thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants