For DevelopersGX EVMInteracting with GX Core

Interacting with GX Core

GX EVM contracts can interact with the native GX Core trading engine through system precompiles and the core bridge contract. This enables on-chain DeFi protocols to read trading data and trigger exchange operations.

System Precompiles

GX Chain provides precompiled contracts at reserved addresses that expose GX Core data to EVM contracts.

Precompile Addresses

AddressNameDescription
0x0000000000000000000000000000000100GxOracleRead oracle prices for all markets
0x0000000000000000000000000000000101GxMarketsQuery market metadata and parameters
0x0000000000000000000000000000000102GxPositionsRead user positions and margin data
0x0000000000000000000000000000000103GxBridgeTransfer assets between GX Core and GX EVM

GxOracle Precompile

Read current oracle prices for any asset:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
 
interface IGxOracle {
    /// @notice Get the oracle price for a perpetual asset
    /// @param assetIndex The perpetual asset index (0 = BTC, 1 = ETH, etc.)
    /// @return price The oracle price scaled to 8 decimal places
    /// @return timestamp The timestamp of the price update
    function getPrice(uint256 assetIndex) external view returns (uint256 price, uint256 timestamp);
 
    /// @notice Get oracle prices for multiple assets in one call
    /// @param assetIndices Array of asset indices
    /// @return prices Array of prices
    /// @return timestamps Array of timestamps
    function getPrices(uint256[] calldata assetIndices)
        external view returns (uint256[] memory prices, uint256[] memory timestamps);
}
 
// Usage
contract MyStrategy {
    IGxOracle constant oracle = IGxOracle(address(0x100));
 
    function getBtcPrice() external view returns (uint256) {
        (uint256 price, ) = oracle.getPrice(0); // BTC = index 0
        return price; // e.g., 6743250000000 = $67,432.50 (8 decimals)
    }
}

GxMarkets Precompile

Query market parameters:

interface IGxMarkets {
    struct MarketInfo {
        string name;
        uint8 szDecimals;
        uint32 maxLeverage;
        bool onlyIsolated;
        bool isActive;
    }
 
    function getMarket(uint256 assetIndex) external view returns (MarketInfo memory);
    function getMarketCount() external view returns (uint256);
}

GxPositions Precompile

Read user positions:

interface IGxPositions {
    struct Position {
        int256 size;       // Positive = long, negative = short (scaled by szDecimals)
        uint256 entryPx;   // Entry price (8 decimals)
        uint256 margin;     // Margin allocated (8 decimals)
        int256 unrealizedPnl; // Current unrealized PnL (8 decimals)
    }
 
    function getPosition(address user, uint256 assetIndex)
        external view returns (Position memory);
 
    function getAccountValue(address user) external view returns (uint256);
    function getWithdrawable(address user) external view returns (uint256);
}

GX Core Bridge Contract

The bridge contract at 0x0000000000000000000000000000000103 enables asset transfers between GX EVM and GX Core.

Transfer from EVM to Core

interface IGxBridge {
    /// @notice Deposit USDC from EVM to GX Core trading account
    /// @param amount Amount in USDC (6 decimals)
    function depositToCore(uint256 amount) external;
 
    /// @notice Withdraw USDC from GX Core to EVM
    /// @param amount Amount in USDC (6 decimals)
    function withdrawFromCore(uint256 amount) external;
 
    /// @notice Get the USDC balance on GX Core for an address
    function coreBalance(address user) external view returns (uint256);
}

See GX Core EVM Transfers for detailed transfer flows.

Example: On-Chain Liquidation Bot

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
 
interface IGxOracle {
    function getPrice(uint256 assetIndex) external view returns (uint256 price, uint256 timestamp);
}
 
interface IGxPositions {
    struct Position {
        int256 size;
        uint256 entryPx;
        uint256 margin;
        int256 unrealizedPnl;
    }
    function getPosition(address user, uint256 assetIndex) external view returns (Position memory);
    function getAccountValue(address user) external view returns (uint256);
}
 
contract LiquidationMonitor {
    IGxOracle constant oracle = IGxOracle(address(0x100));
    IGxPositions constant positions = IGxPositions(address(0x102));
 
    event LiquidationCandidate(address indexed user, uint256 assetIndex, uint256 accountValue);
 
    function checkLiquidation(address user, uint256 assetIndex) external view returns (bool) {
        uint256 accountValue = positions.getAccountValue(user);
        IGxPositions.Position memory pos = positions.getPosition(user, assetIndex);
 
        if (pos.size == 0) return false;
 
        // Check if account value is below maintenance margin
        uint256 absSize = pos.size > 0 ? uint256(pos.size) : uint256(-pos.size);
        (uint256 price, ) = oracle.getPrice(assetIndex);
        uint256 notional = (absSize * price) / 1e8;
        uint256 maintenanceMargin = notional / 20; // 5% maintenance
 
        return accountValue < maintenanceMargin;
    }
}

Gas Costs

Precompile calls are priced to reflect the computational cost of reading L1 state:

OperationGas Cost
getPrice (single)2,000
getPrices (batch)2,000 + 500 per asset
getPosition5,000
getAccountValue3,000
getMarket2,000
depositToCore50,000
withdrawFromCore50,000

Limitations

  • Precompile data reflects the latest finalized GX Core state. There may be a 1-2 second delay from the real-time trading state.
  • Write operations (deposits/withdrawals) via the bridge are processed in the next GX Core block, not instantly.
  • Precompiles are read-only except for the bridge contract. You cannot place orders or cancel positions from EVM contracts directly.