smartcontractkit / full-blockchain-solidity-course-py

Ultimate Solidity, Blockchain, and Smart Contract - Beginner to Expert Full Course | Python Edition
MIT License
10.83k stars 2.91k forks source link

ValueError: Gas estimation failed: 'execution reverted: VM Exception while processing transaction: revert'. This transaction will likely revert. If you wish to broadcast, you must set the gas limit manually. #1423

Open supercede opened 2 years ago

supercede commented 2 years ago
def test_funding_and_withdrawal():
    account = get_account()
    print(f"account ==> {account}")
    fund_me = deploy_fundme()
    print(f"fund_me ==> {fund_me}")
    entrance_fee = fund_me.getEntranceFee()
    print(f"entrance_fee ==> {entrance_fee}")

    tx = fund_me.fund({"from": account, "value": entrance_fee})
    tx.wait(1)
    assert fund_me.fundersMap(account.address) == entrance_fee

    tx2 = fund_me.withdraw({"from": account})
    tx2.wait(1)
    assert fund_me.fundersMap(account.address) == 0
brownie test -k  test_only_owner_can_withdraw --network ganache-local -s
Brownie v1.18.1 - Python development framework for Ethereum

============================================================================================ test session starts ============================================================================================
platform linux -- Python 3.8.10, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 -- /home/d3st1ny/.local/pipx/venvs/eth-brownie/bin/python
cachedir: .pytest_cache
hypothesis profile 'brownie-verbose' -> verbosity=2, deadline=None, max_examples=50, stateful_step_count=10, report_multiple_bugs=False, database=DirectoryBasedExampleDatabase(PosixPath('/home/d3st1ny/.brownie/hypothesis'))
rootdir: /home/d3st1ny/projects/web3/brownie_fund_me
plugins: eth-brownie-1.18.1, forked-1.4.0, hypothesis-6.27.3, web3-5.27.0, xdist-1.34.0
collected 2 items / 1 deselected / 1 selected                                                                                                                                                               

tests/test_fund_me.py::test_only_owner_can_withdraw RUNNING
mnemonic: 'ensure weather acoustic oyster time release stock memory pink sudden regular photo'
bad actor ==> 0x848ec101C82F747CFa4B75262A28C055bF965FC4
using development environment
using mock aggregator at 0x3194cBDC3dbcd3E11a07892e7bA5c3394048Cc87
Contract deployed to 0xe692Cf21B12e0B2717C4bF647F9768Fa58861c8b
priceeeeeeee 2000000000000000000000
tests/test_fund_me.py::test_only_owner_can_withdraw FAILED

================================================================================================= FAILURES ==================================================================================================
_______________________________________________________________________________________ test_only_owner_can_withdraw ________________________________________________________________________________________

    def test_only_owner_can_withdraw():
        if network.show_active() not in LOCAL_ENVIRONMENTS:
            pytest.skip("This test only runs in local environments")
        bad_actor = accounts.add()
        print(f"bad actor ==> {bad_actor}")
        fund_me = deploy_fundme()
        print(f"priceeeeeeee {fund_me.getPrice()}")
        with pytest.raises(exceptions.VirtualMachineError):
>           fund_me.withdraw({"from": bad_actor})
E           ValueError: Gas estimation failed: 'execution reverted: VM Exception while processing transaction: revert'. This transaction will likely revert. If you wish to broadcast, you must set the gas limit manually.

tests/test_fund_me.py:32: ValueError
tests/test_fund_me.py::test_only_owner_can_withdraw ========================================================================================== short test summary info ==========================================================================================
FAILED tests/test_fund_me.py::test_only_owner_can_withdraw - ValueError: Gas estimation failed: 'execution reverted: VM Exception while processing transaction: revert'. This transaction will likely reve...
====================================================================================== 1 failed, 1 deselected in 0.32s ======================================================================================

The error message turns into: ValueError: Execution reverted during call: 'VM Exception while processing transaction: revert'. This transaction will likely revert. If you wish to broadcast, includeallow_revert:Trueas a transaction parameter.

Other useful files:

DECIMALS = 8 # Price feed aggregator usually returns 8 decimals STARTING_PRICE = 200000000000 # 2000 + 8 decimals LOCAL_ENVIRONMENTS = ["development", "ganache-local"] FORKED_LOCAL_ENVIRONMENTS = ["mainnet-fork", "mainnet-fork-dev"]

def get_account(): if ( network.show_active() in LOCAL_ENVIRONMENTS or network.show_active() in FORKED_LOCAL_ENVIRONMENTS ): return accounts[0] else: return accounts.add(config["wallets"]["from_key"])

def deploy_mocks(): if len(MockV3Aggregator) <= 0: print("deploying mock aggregator") mock_aggregator = MockV3Aggregator.deploy( DECIMALS, STARTING_PRICE, {"from": get_account()} ) print(f"deployed mock aggregator to address {mock_aggregator.address}")


- deploy.py (works fine)

from brownie import FundMe, config, network, MockV3Aggregator from scripts.helpers import get_account, deploy_mocks, LOCAL_ENVIRONMENTS

def deploy_fundme(): account = get_account() if network.show_active() not in LOCAL_ENVIRONMENTS:

    print(f"using {network.show_active()} environment")

    price_feed_address = config["networks"][network.show_active()][
        "eth_usd_price_feed"
    ]
else:
    print("using development environment")
    deploy_mocks()

    price_feed_address = MockV3Aggregator[-1].address
    print(f"using mock aggregator at {price_feed_address}")

fund_me = FundMe.deploy(
    price_feed_address,
    {"from": account},
    publish_source=config["networks"][network.show_active()].get("verify"),
)
print(f"Contract deployed to {fund_me.address}")
return fund_me

def main(): deploy_fundme()


- fund_and_withdraw.py (works fine)

from brownie import FundMe, accounts

def fund(): fund_me = FundMe[-1] account = accounts[0] entrance_fee = fund_me.getEntranceFee() print("The current entrance fee is {entrance_fee}") fund_me.fund({"from": account, "value": entrance_fee})

def withdraw(): fund_me = FundMe[-1] account = accounts[0]

fund_me.withdraw({"from": account})

def main(): fund() withdraw()

kthibault77 commented 2 years ago

Hi, I got the same issue and thanks to your post, I could manage a quick fix, which is however not completely satisfactory. I invite you to read the issue I posted today (it doesn't contain the quick fix, as I hadn't found it yet): https://github.com/smartcontractkit/full-blockchain-solidity-course-py/issues/1442

Quick fix

As you noted, when you fix the gas_limit parameter you then get the following error.

ValueError: Execution reverted during call: 'VM Exception while processing transaction: revert'. This transaction will likely revert. If you wish to broadcast, include allow_revert:True as a transaction parameter.

If you try to add the parameter allow_revert: true you'll have the following error: fund_me.withdraw({"from": bad_actor,"gas_limit":12000000,"allow_revert":True})

ValueError: sender doesn't have enough funds to send tx. The upfront cost is: 240000000000000000 and the sender's account only has: 0

Which is not surprising, because for some reason when you use the method accounts.add() to create the bad_actor, it generates an empty account with a balance of 0. I looked it up but don't know how to change that. Therefore, if you fix the gas_price to 0, the code should work. In other words the following line should solve your issue: fund_me.withdraw({"from": bad_actor,"gas_price":0,"gas_limit":12000000,"allow_revert":True})

Alternatively you can also replace bad_actor, by any other account in the accounts list (except account[0] the actual owner), for example, this line will also work: fund_me.withdraw({"from": accounts[3],"gas_limit":12000000,"allow_revert":True})

_Note that the gaslimit has been fixed at 1200000 because above that, the test fails in the development network with the following message (this is linked to the default configuration of the development network) :

ValueError: Exceeds block gas limit

Exploring the problem

With regards to the sender's account only has: 0 error, it might be a property of the method accounts.add() that the account created has a balance of 0 or a property of the network on which it is created, I am not sure. It might be possible to redefine this in the network config, but I didn't find any way to do it.

My gut feeling is that the primary issue is linked to the default network config.
https://eth-brownie.readthedocs.io/en/stable/config.html#config I believe that our ganache-local network has the default properties of a live network since it is not natively a development network. And as you can see in the link development and live network have differing properties such including the following:

gas_limit
gas_buffer
gas_price
reverting_tx_gas_limit

My guess is that one or several of them are responsible for the problem. I tried to change the brownie-config.yaml to play with these parameters, but I am not sure if I am operating correctly.

It is possible that it is linked to the version of Ganache we work with. I work with Ganache 7.0.5, while I think the video was made with Ganache 6.x.x

Other useful advice

If you haven't try already, I suggest that you try to explore a bit with a debugger, it makes it easier to understand your issues. You might be luckier than me in finding a more satisfactory solution.

If you work with vscode you can create .vscode folder in your working folder (brownie_fund_me) and create the launch.json with the code below in it. It will allow you to debug your python code, and run some inline command to check your variables and all during code execution. Pretty useful for troubleshooting. You need to adapt "pythonPath" and "program" to your ownenvironment. Also, you may need to copy brownie.exe to be in the same folder as your brownie package folder. Let me know if you have any problem with that.

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Brownie Test",
            "type": "python",
            "request": "launch",
            "pythonPath": "D:/Anaconda3/envs/blockchain/python.exe",
            "program":"D:/Anaconda3/envs/blockchain/lib/site-packages/brownie.exe",
            "console": "integratedTerminal",
            "args": ["test","-s","--network","ganache-local"],
        },

        {
            "name": "Brownie Debug",
            "type": "python",
            "request": "launch",
            "pythonPath": "D:/Anaconda3/envs/blockchain/python.exe",
            "program":"D:/Anaconda3/envs/blockchain/lib/site-packages/brownie.exe",
            "console": "integratedTerminal",
            "args": ["run","scripts/deploy.py","--network","ganache-local"],
        }
    ]
}

Main questions

How to create a bad_actor account that is prefunded? Is the problem linked to the Ganache version? Is the error linked to the properties of the network, and if it is the case how to change them?

Ed-Marcavage commented 2 years ago

You need to use the addresses from Chainlink VRF v1 NOT v2 in your .yaml, remember to re-deploy your contract with these newly updated addresses. Please see the link below for the addresses: https://docs.chain.link/docs/vrf/v1/supported-networks/ https://stackoverflow.com/questions/71194882/execution-reverted-during-call-this-transaction-will-likely-revert-if-you-wish

T1murKO commented 2 years ago

The same issue. Relly weird behavior, has two different types of errors raised by require in developement and local ganache chain.

Ed-Marcavage commented 2 years ago

Try deploying to Goerli

Cosmodude commented 2 years ago

You need to use the addresses from Chainlink VRF v1 NOT v2 in your .yaml, remember to re-deploy your contract with these newly updated addresses. Please see the link below for the addresses: https://docs.chain.link/docs/vrf/v1/supported-networks/ https://stackoverflow.com/questions/71194882/execution-reverted-during-call-this-transaction-will-likely-revert-if-you-wish

I have checked everything, my addresses are from v1. Still have the error. I am using Goerli

Actually, my error is slightly different: Gas estimation failed: 'execution reverted: 2'. This transaction will likely revert. If you wish to broadcast, you must set the gas limit manually.

denchance commented 2 years ago

Hi, I got the same issue and thanks to your post, I could manage a quick fix, which is however not completely satisfactory. I invite you to read the issue I posted today (it doesn't contain the quick fix, as I hadn't found it yet): #1442

Quick fix

As you noted, when you fix the gas_limit parameter you then get the following error.

ValueError: Execution reverted during call: 'VM Exception while processing transaction: revert'. This transaction will likely revert. If you wish to broadcast, include allow_revert:True as a transaction parameter.

If you try to add the parameter allow_revert: true you'll have the following error: fund_me.withdraw({"from": bad_actor,"gas_limit":12000000,"allow_revert":True})

ValueError: sender doesn't have enough funds to send tx. The upfront cost is: 240000000000000000 and the sender's account only has: 0

Which is not surprising, because for some reason when you use the method accounts.add() to create the bad_actor, it generates an empty account with a balance of 0. I looked it up but don't know how to change that. Therefore, if you fix the gas_price to 0, the code should work. In other words the following line should solve your issue: fund_me.withdraw({"from": bad_actor,"gas_price":0,"gas_limit":12000000,"allow_revert":True})

Alternatively you can also replace bad_actor, by any other account in the accounts list (except account[0] the actual owner), for example, this line will also work: fund_me.withdraw({"from": accounts[3],"gas_limit":12000000,"allow_revert":True})

_Note that the gaslimit has been fixed at 1200000 because above that, the test fails in the development network with the following message (this is linked to the default configuration of the development network) :

ValueError: Exceeds block gas limit

Exploring the problem

With regards to the sender's account only has: 0 error, it might be a property of the method accounts.add() that the account created has a balance of 0 or a property of the network on which it is created, I am not sure. It might be possible to redefine this in the network config, but I didn't find any way to do it.

My gut feeling is that the primary issue is linked to the default network config. https://eth-brownie.readthedocs.io/en/stable/config.html#config I believe that our ganache-local network has the default properties of a live network since it is not natively a development network. And as you can see in the link development and live network have differing properties such including the following:

gas_limit
gas_buffer
gas_price
reverting_tx_gas_limit

My guess is that one or several of them are responsible for the problem. I tried to change the brownie-config.yaml to play with these parameters, but I am not sure if I am operating correctly.

It is possible that it is linked to the version of Ganache we work with. I work with Ganache 7.0.5, while I think the video was made with Ganache 6.x.x

Other useful advice

If you haven't try already, I suggest that you try to explore a bit with a debugger, it makes it easier to understand your issues. You might be luckier than me in finding a more satisfactory solution.

If you work with vscode you can create .vscode folder in your working folder (brownie_fund_me) and create the launch.json with the code below in it. It will allow you to debug your python code, and run some inline command to check your variables and all during code execution. Pretty useful for troubleshooting. You need to adapt "pythonPath" and "program" to your ownenvironment. Also, you may need to copy brownie.exe to be in the same folder as your brownie package folder. Let me know if you have any problem with that.

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Brownie Test",
            "type": "python",
            "request": "launch",
            "pythonPath": "D:/Anaconda3/envs/blockchain/python.exe",
            "program":"D:/Anaconda3/envs/blockchain/lib/site-packages/brownie.exe",
            "console": "integratedTerminal",
            "args": ["test","-s","--network","ganache-local"],
        },

        {
            "name": "Brownie Debug",
            "type": "python",
            "request": "launch",
            "pythonPath": "D:/Anaconda3/envs/blockchain/python.exe",
            "program":"D:/Anaconda3/envs/blockchain/lib/site-packages/brownie.exe",
            "console": "integratedTerminal",
            "args": ["run","scripts/deploy.py","--network","ganache-local"],
        }
    ]
}

Main questions

How to create a bad_actor account that is prefunded? Is the problem linked to the Ganache version? Is the error linked to the properties of the network, and if it is the case how to change them?

Thanks, @kthibault77 One of these two works for me.

fund_me.withdraw({"from": bad_actor,"gas_price":0,"gas_limit":12000000,"allow_revert":True})

OR

fund_me.withdraw({"from": accounts[3],"gas_limit":12000000,"allow_revert":True})

BTW, the ENV version for me as following:

My codes

def test_only_owner_can_withdraw():
    if network.show_active() not in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
        pytest.skip("only for local testing")
    fund_me = deploy_fund_me()
    bad_actor = accounts.add()
    with pytest.raises(exceptions.VirtualMachineError):
        fund_me.withdraw(
            {
                "from": bad_actor,
                "gas_price": 0,
                "gas_limit": 12000000,
                "allow_revert": True,
            }
        )

OR

def test_only_owner_can_withdraw():
    if network.show_active() not in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
        pytest.skip("only for local testing")
    fund_me = deploy_fund_me()
    bad_actor = accounts[1]
    with pytest.raises(exceptions.VirtualMachineError):
        fund_me.withdraw(
            {"from": bad_actor, "gas_limit": 12000000, "allow_revert": True}
        )