gmx.testing
Documentation for eth_defi.gmx.testing Python module.
Fork testing helpers for GMX.
Supports both Anvil and Tenderly for mocking oracles and impersonating keepers.
Submodules
constants– address constants and resolution helpersfork_provider– provider detection and RPC helpersoracle– mock oracle setup and price querieskeeper– keeper impersonation and order execution
- deal_eth(web3, recipient, amount_wei)
Fund an address with native ETH (equivalent to Foundry’s
vm.deal).
- deal_tokens(web3, token_address, recipient, amount)
Fund an address with ERC20 tokens (equivalent to Foundry’s
deal).Uses
anvil_setStorageAtto directly set the balance in the token’s storage. Works for most standard ERC20 tokens that use amapping(address => uint256)for balances.
- detect_provider_type(web3)
Detect if we’re using Anvil or Tenderly.
- Returns
"anvil","tenderly", or"unknown"- Parameters
web3 (web3.main.Web3) –
- Return type
- execute_order_and_get_result(web3, order_key)
Execute order as keeper and return the parsed execution result.
Convenience wrapper around
execute_order_as_keeper()that also parses the execution events to extract prices, fees, and status.- Parameters
web3 (web3.main.Web3) – Web3 instance connected to the fork
order_key (bytes) – The 32-byte order key from OrderCreated event
- Returns
Tuple of
(receipt, keeper_address, execution_result)whereexecution_resultis anOrderExecutionResultfrometh_defi.gmx.events
- execute_order_as_keeper(web3, order_key)
Execute order by impersonating keeper.
Works with both Anvil and Tenderly.
Warning
On Anvil (and Tenderly) forks this function has a side-effect: the test wallet’s native ETH balance drops to exactly 0 after the keeper transaction is mined.
Why it happens – verified via Tenderly transaction debugger:
When the order is created (
create_market_buy_order/open_position), the GMX order struct stores the wallet address asreceiverwithshouldUnwrapNativeToken = True(seeBaseOrder._build_order_paramsineth_defi/gmx/order/base_order.py). DuringexecuteOrder, the GMX protocol’s internal settlement logic transfers the wallet’s entire native ETH balance to a GMX settlement contract. This happens because the wallet address is inunlocked_addresses(i.e.anvil_impersonateAccountwas called for it), which allows the fork node to process ETH transfers from the wallet without a signed transaction.This is a fork-only artefact. In production the wallet is never impersonated, so GMX contracts cannot move ETH from it. The wallet nonce and ERC-20 balances are unaffected.
Callers that need to send further wallet transactions (e.g.
cancel_order,close_position, creating SL/TP orders) must re-fund the wallet after calling this function:exec_receipt, keeper = execute_order_as_keeper(web3, order_key) # Restore wallet ETH so subsequent txs can pay for gas web3.provider.make_request( "anvil_setBalance", [wallet_address, hex(100_000_000 * 10**18)], ) wallet.sync_nonce(web3)- Returns
Tuple of
(receipt, keeper_address).- Parameters
web3 (web3.main.Web3) –
order_key (bytes) –
- extract_order_key_from_receipt(receipt, web3=None)
Extract order key from OrderCreated event in receipt.
GMX v2.2 uses EventLog2 with the order key in
topics[2].topics[0]: EventLog2 signaturetopics[1]: OrderCreated event hash (a7427759...)topics[2]: order keytopics[3]: account address
- fetch_on_chain_oracle_prices(web3)
Fetch current oracle prices from GMX before replacing with mock.
Queries the actual on-chain oracle to get prices that will pass GMX’s validation, since GMX validates mock prices against actual chain state.
- get_mock_oracle_price(web3, token_symbol='WETH')
Read the configured price from the mock oracle on the fork.
Queries the MockOracleProvider contract directly to get the price that was set during fixture setup, avoiding any drift from the GMX API.
Use this in tests to get the exact price the mock oracle will use, ensuring limit order trigger prices match the oracle’s acceptable range.
- impersonate_account(web3, address)
Start impersonating account (works with Anvil and Tenderly).
- Parameters
web3 (web3.main.Web3) –
address (str) –
- mine_block(web3)
Manually mine a block.
Used when Anvil is started with
--no-miningflag. After sending transactions, call this to mine them into a block.- Parameters
web3 (web3.main.Web3) – Web3 instance
- set_balance(web3, address, balance_hex)
Set balance for address (works with Anvil and Tenderly).
- set_code(web3, address, bytecode)
Set bytecode at address (works with Anvil and Tenderly).
- set_next_block_timestamp(web3, timestamp)
Set the timestamp for the next block to be mined.
Useful for preventing oracle price staleness on Anvil forks.
- Parameters
web3 (web3.main.Web3) – Web3 instance
timestamp (int) – Unix timestamp for the next block (in seconds)
- setup_mock_oracle(web3, eth_price_usd=None, usdc_price_usd=None)
Setup mock oracle by replacing bytecode at production address.
Follows GMX’s pattern from forked-env-example:
Fetch current on-chain prices (if not provided)
Deploy MockOracleProvider and get its bytecode
Replace production oracle bytecode using
anvil_setCodeConfigure prices on the mock at production address
This ensures mock prices match on-chain state for GMX validation.
Modules
|
Constants and address resolution helpers for GMX fork testing. |
|
Fork provider detection and RPC helpers for GMX testing. |
|
Keeper impersonation and order execution helpers for GMX fork testing. |
|
Mock oracle setup and price helpers for GMX fork testing. |