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 helpers

  • fork_provider – provider detection and RPC helpers

  • oracle – mock oracle setup and price queries

  • keeper – keeper impersonation and order execution

deal_eth(web3, recipient, amount_wei)

Fund an address with native ETH (equivalent to Foundry’s vm.deal).

Parameters
  • web3 (web3.main.Web3) – Web3 instance

  • recipient (str) – Address to fund

  • amount_wei (int) – Amount in wei

deal_tokens(web3, token_address, recipient, amount)

Fund an address with ERC20 tokens (equivalent to Foundry’s deal).

Uses anvil_setStorageAt to directly set the balance in the token’s storage. Works for most standard ERC20 tokens that use a mapping(address => uint256) for balances.

Parameters
  • web3 (web3.main.Web3) – Web3 instance

  • token_address (str) – ERC20 token contract address

  • recipient (str) – Address to fund

  • amount (int) – Amount in token’s smallest unit (e.g. wei for WETH, 10^6 for USDC)

detect_provider_type(web3)

Detect if we’re using Anvil or Tenderly.

Returns

"anvil", "tenderly", or "unknown"

Parameters

web3 (web3.main.Web3) –

Return type

str

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) where execution_result is an OrderExecutionResult from eth_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 as receiver with shouldUnwrapNativeToken = True (see BaseOrder._build_order_params in eth_defi/gmx/order/base_order.py). During executeOrder, 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 in unlocked_addresses (i.e. anvil_impersonateAccount was 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 signature

  • topics[1]: OrderCreated event hash (a7427759...)

  • topics[2]: order key

  • topics[3]: account address

Parameters
  • receipt (dict) – Transaction receipt

  • web3 (web3.main.Web3 | None) – Optional Web3 instance. If provided, uses the event module for full event decoding. If not provided, falls back to simple topic extraction.

Returns

The 32-byte order key

Return type

bytes

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.

Returns

(eth_price_usd, usdc_price_usd) as integers in USD

Parameters

web3 (web3.main.Web3) –

Return type

tuple[int, int]

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.

Parameters
  • web3 (web3.main.Web3) – Web3 instance connected to the fork

  • token_symbol (str) – Token symbol ("WETH" or "USDC")

Returns

Price in USD as float

Return type

float

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-mining flag. 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).

Parameters
  • web3 (web3.main.Web3) –

  • address (str) –

  • balance_hex (str) –

set_code(web3, address, bytecode)

Set bytecode at address (works with Anvil and Tenderly).

Parameters
  • web3 (web3.main.Web3) – Web3 instance

  • address (str) – Contract address where to set the bytecode

  • bytecode (str) – Bytecode to set (hex string with or without 0x prefix, or bytes)

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:

  1. Fetch current on-chain prices (if not provided)

  2. Deploy MockOracleProvider and get its bytecode

  3. Replace production oracle bytecode using anvil_setCode

  4. Configure prices on the mock at production address

This ensures mock prices match on-chain state for GMX validation.

Parameters
  • web3 (web3.main.Web3) – Web3 instance

  • eth_price_usd (int | None) – ETH price in USD (if None, fetches from chain)

  • usdc_price_usd (int | None) – USDC price in USD (if None, fetches from chain)

stop_impersonating_account(web3, address)

Stop impersonating account (works with Anvil and Tenderly).

Parameters
  • web3 (web3.main.Web3) –

  • address (str) –

Modules

eth_defi.gmx.testing.constants

Constants and address resolution helpers for GMX fork testing.

eth_defi.gmx.testing.fork_provider

Fork provider detection and RPC helpers for GMX testing.

eth_defi.gmx.testing.keeper

Keeper impersonation and order execution helpers for GMX fork testing.

eth_defi.gmx.testing.oracle

Mock oracle setup and price helpers for GMX fork testing.