provider.ganache
Documentation for eth_defi.provider.ganache Python module.
Ganache integration.
Ganache is an EVM test backend and mainnet forking written in JavaScript from Truffle project.
This module contains utilities to automatically launch and manipulate ganache-cli process.
You need to have ganache-cli installed in order to use these.
How to install ganache-cli using npm:
npm install -g ganache
For more information about Ganache see
Most of this code is lifted from Brownie project (MIT) and it is not properly cleaned up yet.
Module Attributes
The default hardfork rules used by Ganache |
Functions
|
Creates the ganache "fork" of given JSON-RPC endpoint. |
Classes
Control ganache-cli processes launched on background. |
Exceptions
Warned when there are issued with ganache-cli command line. |
|
We could not launch because ganache-cli command is missing |
- EVM_DEFAULT = 'london'
The default hardfork rules used by Ganache
- exception NoGanacheInstalled
Bases:
ExceptionWe could not launch because ganache-cli command is missing
- __init__(*args, **kwargs)
- __new__(**kwargs)
- add_note()
Exception.add_note(note) – add a note to the exception
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- exception InvalidArgumentWarning
Bases:
WarningWarned when there are issued with ganache-cli command line.
- __init__(*args, **kwargs)
- __new__(**kwargs)
- add_note()
Exception.add_note(note) – add a note to the exception
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- class GanacheLaunch
Bases:
objectControl ganache-cli processes launched on background.
Comes with a helpful
close()method when it is time to put Ganache rest.- process: psutil.Popen
UNIX process that we opened
- close(verbose=False, block=True, block_timeout=30)
Kill the ganache-cli process.
Ganache is pretty hard to kill, so keep killing it until it dies and the port is free again.
- Parameters
block – Block the execution until Ganache has terminated
block_timeout – How long we give for Ganache to clean up after itself
verbose – If set, dump anything in Ganache stdout to the Python logging using level INFO.
- fork_network(json_rpc_url, unlocked_addresses=[], cmd='ganache-cli', port=19999, evm_version='london', block_time=0, quiet=False, launch_wait_seconds=20.0)
Creates the ganache “fork” of given JSON-RPC endpoint.
Warning
This function is not recommended due to stability issues with Ganache. Use
eth_defi.anvil.fork_network_anvil()instead.Forking a mainnet is common way to test against live deployments. This function invokes ganache-cli command and tells it to fork a given JSON-RPC endpoint.
A subprocess is started on the background. To stop this process, call
eth_defi.ganache.GanacheLaunch.close(). This function waits launch_wait_seconds in order to ganache-cli process to start and complete the chain fork.Note
Currently only supports HTTP JSON-RPC connections.
Warning
Forking a network with ganache-cli is a slow process. It is recommended that you use fast Ethereum Tester based testing if possible.
Here is an example that forks BNB chain mainnet and transfer 500 BUSD stablecoin to a test account we control:
@pytest.fixture() def large_busd_holder() -> HexAddress: # A random account picked from BNB Smart chain that holds a lot of BUSD. # Binance Hot Wallet 6 return HexAddress(HexStr("0x8894E0a0c962CB723c1976a4421c95949bE2D4E3")) @pytest.fixture() def ganache_bnb_chain_fork(large_busd_holder) -> str: # Create a testable fork of live BNB chain. mainnet_rpc = os.environ["BNB_CHAIN_JSON_RPC"] launch = fork_network( mainnet_rpc, unlocked_addresses=[large_busd_holder], ) yield launch.json_rpc_url # Wind down Ganache process after the test is complete launch.close() @pytest.fixture def web3(ganache_bnb_chain_fork: str): # Set up a local unit testing blockchain return Web3(HTTPProvider(ganache_bnb_chain_fork)) def test_mainnet_fork_transfer_busd(web3: Web3, large_busd_holder: HexAddress, user_1: LocalAccount): # BUSD deployment on BNB chain # https://bscscan.com/token/0xe9e7cea3dedca5984780bafc599bd69add087d56 busd_details = fetch_erc20_details(web3, "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56") busd = busd_details.contract # Transfer 500 BUSD to the user 1 tx_hash = busd.functions.transfer(user_1.address, 500 * 10**18).transact({"from": large_busd_holder}) # Because Ganache has instamine turned on by default, we do not need to wait for the transaction receipt = web3.eth.get_transaction_receipt(tx_hash) assert receipt.status == 1, "BUSD transfer reverted" assert busd.functions.balanceOf(user_1.address).call() == 500 * 10**18
See the full example in tests source code.
Polygon needs to set a specific EVM version:
mainnet_rpc = os.environ["POLYGON_JSON_RPC"] launch = fork_network(mainnet_rpc, evm_version="istanbul")
If ganache-cli refuses to terminate properly, you can kill a process by a port with:
# Kill any process listening to localhost:19999 kill -SIGKILL $(lsof -ti:19999)
This function uses Python logging subsystem. If you want to see error/info/debug logs with pytest you can do:
pytest --log-cli-level=debug
For public JSON-RPC endpoints check
- Parameters
cmd – Override ganache-cli command. If not given we look up from PATH.
json_rpc_url (str) – HTTP JSON-RPC URL of the network we want to fork
unlocked_addresses (List[Union[eth_typing.evm.HexAddress, str]]) – List of addresses of which ownership we take to allow test code to transact as them
port – Localhost port we bind for Ganache JSON-RPC
launch_wait_seconds – How long we wait ganache-cli to start until giving up
evm_version – “london” for the default hard fork
block_time – How long Ganache takes to mine a block. Default is zero and any RPC transaction will immediately return with the transaction inclusion. Set to 1 so that you can poll the transaction as you would do with a live JSON-RPC node.
quiet – Disable extensive logging. If there is a lot of Ganache logging it seems to crash on Github CI.
- Return type