GX Core EVM Transfers
This page explains how to transfer assets between the GX Core trading engine and the GX EVM smart contract environment.
Architecture
GX Exchange maintains two separate balance systems:
| Layer | Balance Type | Used For |
|---|---|---|
| GX Core | Trading balance | Order placement, margin, perp/spot trading |
| GX EVM | EVM balance | Smart contract interactions, ERC-20 tokens, DeFi |
Assets must be explicitly transferred between these layers. They cannot be spent in one layer while held in the other.
Core to EVM Transfer
Move USDC from your GX Core trading balance to your GX EVM address.
Via API
POST /exchange
{
"action": {
"type": "coreToEvm",
"amount": "1000.0"
},
"nonce": 1700000000123,
"signature": { "r": "0x...", "s": "0x...", "v": 27 }
}| Field | Type | Description |
|---|---|---|
amount | string | USDC amount to transfer to EVM |
Via SDK
const result = await client.exchange({
action: {
type: "coreToEvm",
amount: "1000.0",
},
nonce: Date.now(),
});result = exchange.core_to_evm(amount="1000.0")Processing
- The transfer is processed in the current GX Core block (< 2 seconds).
- USDC appears as an ERC-20 balance at the USDC contract address on GX EVM.
- No gas fee is charged for the Core-to-EVM direction.
EVM to Core Transfer
Move USDC from your GX EVM address back to your GX Core trading balance.
Via Bridge Contract
Call the depositToCore function on the GX Bridge precompile:
// From a smart contract
interface IGxBridge {
function depositToCore(uint256 amount) external;
}
IGxBridge constant bridge = IGxBridge(address(0x103));
function sendToCore(uint256 amount) external {
// First approve the bridge to spend USDC
IERC20(usdcAddress).approve(address(0x103), amount);
bridge.depositToCore(amount);
}Via ethers.js
import { ethers } from "ethers";
const provider = new ethers.JsonRpcProvider("https://rpc.gx.exchange");
const wallet = new ethers.Wallet("0xYourPrivateKey...", provider);
const bridgeAddress = "0x0000000000000000000000000000000103";
const bridgeAbi = ["function depositToCore(uint256 amount) external"];
const bridge = new ethers.Contract(bridgeAddress, bridgeAbi, wallet);
// Approve USDC spend first
const usdcAddress = "0x..."; // GX EVM USDC contract
const usdc = new ethers.Contract(usdcAddress, [
"function approve(address spender, uint256 amount) external returns (bool)"
], wallet);
const amount = ethers.parseUnits("1000", 6); // 1000 USDC (6 decimals)
await usdc.approve(bridgeAddress, amount);
// Transfer to Core
const tx = await bridge.depositToCore(amount);
await tx.wait();
console.log("Transferred to GX Core");Processing
- The EVM transaction must be mined in a block (1 second for fast block, up to 1 minute for slow block).
- The GX Core balance is credited in the next Core block after the EVM block is finalized.
- Total latency: 2-5 seconds for fast blocks.
Transfer Timing Summary
| Direction | Initiation | Confirmation | Total Latency |
|---|---|---|---|
| Core to EVM | API call | Next Core block | 1-2 seconds |
| EVM to Core | EVM transaction | Next Core block after EVM finality | 2-5 seconds |
Checking Balances
GX Core Balance
POST /info
{ "type": "clearinghouseState", "user": "0xYourAddress..." }GX EVM Balance
const provider = new ethers.JsonRpcProvider("https://rpc.gx.exchange");
// Native GX balance
const gxBalance = await provider.getBalance("0xYourAddress...");
// USDC ERC-20 balance
const usdc = new ethers.Contract(usdcAddress, [
"function balanceOf(address) view returns (uint256)"
], provider);
const usdcBalance = await usdc.balanceOf("0xYourAddress...");Fees
| Transfer Direction | Fee |
|---|---|
| Core to EVM | Free |
| EVM to Core | EVM gas fee only (no additional bridge fee) |
Constraints
| Constraint | Value |
|---|---|
| Minimum transfer | 1 USDC |
| Maximum transfer | Limited by available balance |
| Transfer currency | USDC only (other assets require swaps) |
| Cooldown | None — transfers can be submitted at any frequency |