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

Failure when swapping from BNB to token on BSC chain #332

Open
nisilag opened this issue May 13, 2023 · 10 comments
Open

Failure when swapping from BNB to token on BSC chain #332

nisilag opened this issue May 13, 2023 · 10 comments
Labels
bug Something isn't working

Comments

@nisilag
Copy link

nisilag commented May 13, 2023

Describe the bug
Running the make_trade_output returns the following error and fails - KeyError: 'baseFeePerGas'

To Reproduce

from uniswap import Uniswap
from web3 import Web3
from web3.middleware import geth_poa_middleware
from eth_account import Account
import config
import random
import time

web3 = Web3(Web3.HTTPProvider(config.provider))
web3.middleware_onion.inject(geth_poa_middleware, layer=0)

private_key = "Place private key here"


account = Account.from_key(private_key)
address = Web3.to_checksum_address(account.address)

version = 2
uniswap = Uniswap(address=address, private_key=private_key, version=version, web3=web3)

bnb = Web3.to_checksum_address("0x242a1ff6ee06f2131b7924cacb74c7f9e3a5edc9")
token = Web3.to_checksum_address("token address")


swap_qty = int(1*10**18)
fee = int(0.0004*10**18)
uniswap.make_trade_output(bnb, token, swap_qty, fee=fee)
@nisilag nisilag added the bug Something isn't working label May 13, 2023
@liquid-8
Copy link
Member

Well, first things first, I haven't used BSC for 1y+, but the fee value seems extremely weird. Default values are 500, 3000, and 10000 (0.05%, 0.3%, and 1%, respectively). They might vote for other fee levels, obv. However, this value is still way too big. I would double-check.

Regarding your question, please provide a complete error message, as it is challenging to locate the problem.

@nisilag
Copy link
Author

nisilag commented May 13, 2023

thx for your input. I tried with 10000 which is the fee (1%) and it failed with the same error message. here's the full error

Approving 0x242a1fF6eE06f2131B7924Cacb74c7F9E3a5edc9...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File ". \AppData\Local\Programs\Python\Python311\Lib\site-packages\uniswap\decorators.py", line 37, in approved
    self.approve(token)
  File ". \AppData\Local\Programs\Python\Python311\Lib\site-packages\uniswap\uniswap.py", line 1409, in approve
    tx = self._build_and_send_tx(function)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ". \AppData\Local\Programs\Python\Python311\Lib\site-packages\uniswap\uniswap.py", line 1443, in _build_and_send_tx
    transaction = function.build_transaction(tx_params)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ". \AppData\Local\Programs\Python\Python311\Lib\site-packages\web3\contract\contract.py", line 510, in build_transaction
    return build_transaction_for_function(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ". \AppData\Local\Programs\Python\Python311\Lib\site-packages\web3\contract\utils.py", line 232, in build_transaction_for_function
    prepared_transaction = fill_transaction_defaults(w3, prepared_transaction)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "cytoolz\functoolz.pyx", line 249, in cytoolz.functoolz.curry.__call__
  File ". \AppData\Local\Programs\Python\Python311\Lib\site-packages\web3\_utils\transactions.py", line 128, in fill_transaction_defaults
    default_val = default_getter(w3, transaction)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ". \AppData\Local\Programs\Python\Python311\Lib\site-packages\web3\_utils\transactions.py", line 75, in <lambda>
    + (2 * w3.eth.get_block("latest")["baseFeePerGas"])
           ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File ". \AppData\Local\Programs\Python\Python311\Lib\site-packages\web3\datastructures.py", line 54, in __getitem__
    return self.__dict__[key]  # type: ignore
           ~~~~~~~~~~~~~^^^^^
KeyError: 'baseFeePerGas'

@nisilag
Copy link
Author

nisilag commented May 13, 2023

so I was able to debug this a bit more and it looks like a discrepancy between bsc and ethereum... the failure is in this command w3.eth.get_block("latest")["baseFeePerGas"]
when running these lines of code using a bsc provider I get the Keyerror but it doesn't generate an error (it returns a value) when using an ethereum provider

from web3 import Web3
import config # this has the provider information

web3 = Web3(Web3.HTTPProvider(config.provider))

web3.eth.get_block("latest")["baseFeePerGas"] # this generates the error on bsc but not on ethereum

@liquid-8
Copy link
Member

liquid-8 commented May 14, 2023

Seems like we need to make a fix or smth. In
_build_and_send_tx()
add smth like
transaction["gasPrice"] = self.w3.eth.generate_gas_price()
Should be fine IMO

Also, you might need to add the following after the middleware injection

    web3.eth.setGasPriceStrategy(fast_gas_price_strategy)
    web3.middleware_onion.add(middleware.time_based_cache_middleware)
    web3.middleware_onion.add(middleware.latest_block_based_cache_middleware)
    web3.middleware_onion.add(middleware.simple_cache_middleware)

Not sure tho

@nisilag
Copy link
Author

nisilag commented May 14, 2023

so I added it but am still getting the same error

    def _build_and_send_tx(
        self, function: ContractFunction, tx_params: Optional[TxParams] = None
    ) -> HexBytes:
        """Build and send a transaction."""
        if not tx_params:
            tx_params = self._get_tx_params()
        transaction = function.build_transaction(tx_params)

        # This is a test... needs to be removed. 5-14-2023
        ################################################################
        transaction["gasPrice"] = self.w3.eth.generate_gas_price()
        ################################################################

        if "gas" not in tx_params:
            # `use_estimate_gas` needs to be True for networks like Arbitrum (can't assume 250000 gas),
            # but it breaks tests for unknown reasons because estimate_gas takes forever on some tx's.
            # Maybe an issue with ganache? (got GC warnings once...)
            if self.use_estimate_gas:
                # The Uniswap V3 UI uses 20% margin for transactions
                transaction["gas"] = Wei(
                    int(self.w3.eth.estimate_gas(transaction) * 1.2)
                )
            else:
                transaction["gas"] = Wei(250_000)

        signed_txn = self.w3.eth.account.sign_transaction(
            transaction, private_key=self.private_key
        )
        # TODO: This needs to get more complicated if we want to support replacing a transaction
        # FIXME: This does not play nice if transactions are sent from other places using the same wallet.
        try:
            return self.w3.eth.send_raw_transaction(signed_txn.rawTransaction)
        finally:
            logger.debug(f"nonce: {tx_params['nonce']}")
            self.last_nonce = Nonce(tx_params["nonce"] + 1)

@nisilag
Copy link
Author

nisilag commented May 15, 2023

I was able to get past the error after I added that line above as you suggested and also the lines of code post middleware injection. Had to tweak things a bit in order to get a successful swap thro. One of the issues I ran into is the assumption that BNB (equivalent to ETH - i.e. native token) has an address of all zeros in BSC - but that's not the case. I had to get creative in my code to make it work.

@liquid-8
Copy link
Member

Nice to see you've managed to resolve this issue. Regarding native tokens, I prefer to use wrapped versions anywhere if possible. This approach allows us to avoid extra wrap/unwrap calls during swaps. That saves some gas, making transactions cheaper. Regardless of the used network, you can get the wrapped token contract with the self.router.functions.WETH call.

@nisilag
Copy link
Author

nisilag commented May 16, 2023

Anything to keep in mind when doing swaps on Optimism? I’m getting all kinds of errors when running this on Op. any advice, gotchas, minefields? I’ll collect my thoughts and post detailed errors etc tomorrow

@liquid-8
Copy link
Member

I do believe that most underwater stones regarding Optimism have been discussed already. Search here/in the discussion section. Also, I'd like to ask you to create a separate thread/issue if questions arise.

@vadimkalolo
Copy link

@liquid-8 @nisilag excuse me, i have extremely low knowledge in python. with eth network everything works fine, but now i'm tryting to make swap on bsc network and getting same error with 'baseFeePerGas'. could you tell where exectly and how i need to add those lines so that the exchange works on bsc?

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