hyperliquid.core_writer
Documentation for eth_defi.hyperliquid.core_writer Python module.
CoreWriter transaction encoding for Hypercore native vaults.
Encodes raw action bytes for the CoreWriter system contract at
0x3333333333333333333333333333333333333333 on HyperEVM.
The raw action format is:
byte 0: version (always
1)bytes 1-3: action ID (big-endian uint24)
bytes 4+:
abi.encode(action-specific parameters)
See /README-Hypercore-guard for the full deposit/withdrawal flow.
Bridge fee note
Core -> HyperEVM linked-token withdrawals are not fee-free. Hyperliquid
charges the bridge fee on HyperCore spot before the linked token settles
back to HyperEVM. In manual mainnet verification, bridging 9 USDC in
transaction 0x82c7ca18fed4952dfdfdffb4e7565cc768c2ab14fe7533bb42a0734cfdf36b16
returned 9 USDC to HyperEVM while reducing HyperCore spot by about
9.000783 USDC, implying an observed bridge fee of about 0.000783 USDC.
Callers should therefore not assume that spot_before - amount ==
spot_after or that the bridged EVM amount will exactly match the full
spot debit.
Example:
from eth_defi.hyperliquid.core_writer import (
encode_vault_deposit,
encode_transfer_usd_class,
CORE_WRITER_ADDRESS,
)
# Build the raw action bytes for a vault deposit
raw_action = encode_vault_deposit(vault_address, usdc_amount_wei)
# Call CoreWriter.sendRawAction(raw_action) via the guard
core_writer = web3.eth.contract(
address=CORE_WRITER_ADDRESS,
abi=core_writer_abi,
)
fn_call = core_writer.functions.sendRawAction(raw_action)
Functions
|
Build a multicall to activate a Safe's HyperCore account. |
Build a single Safe transaction that approves USDC to CoreDepositWallet. |
|
|
Build a single Safe transaction that bridges USDC to a specific HyperCore spot account. |
|
Build a single multicall transaction for the full Hypercore deposit flow. |
|
Build phase 1 of a two-phase Hypercore deposit: bridge USDC to HyperCore spot. |
|
Build phase 2 of a two-phase Hypercore deposit: spot to perp to vault. |
Build a single Safe transaction that bridges USDC from HyperEVM to HyperCore spot. |
|
Build a single Safe transaction that deposits USDC from perp into a HyperCore vault. |
|
Build a single Safe transaction that bridges USDC from HyperCore spot back to HyperEVM. |
|
|
Build a single Safe transaction that sends USDC to another HyperCore spot account. |
Build a single Safe transaction that moves USDC between spot and perp. |
|
Build a single Safe transaction for one HyperCore |
|
Build a single Safe transaction that withdraws USDC from a HyperCore vault into perp. |
|
Build a single multicall transaction for the full Hypercore withdrawal flow. |
|
Compute the actual |
|
Convert a linked-token EVM raw amount to the CoreWriter |
|
|
Encode a CoreWriter sendAsset action (action ID 13). |
|
Encode a linked-token transfer from HyperCore spot back to HyperEVM. |
|
Encode a CoreWriter spotSend action (action ID 6). |
|
Encode a CoreWriter transferUsdClass action (action ID 7). |
|
Encode a CoreWriter vaultTransfer deposit action (action ID 2). |
|
Encode a CoreWriter vaultTransfer withdraw action (action ID 2). |
|
Get the HyperCore system address for a linked token index. |
|
Get a Contract instance for the CoreDepositWallet. |
|
Get a Contract instance for the CoreWriter system contract. |
- build_activate_account_multicall(lagoon_vault, activation_amount=None)
Build a multicall to activate a Safe’s HyperCore account.
Smart contracts (like Safe multisigs) must be activated on HyperCore before
CoreDepositWallet.deposit()bridge actions will clear the EVM escrow. This multicall performs the activation in a single transaction via the Safe’s trading strategy module:approve(CoreDepositWallet, activation_amount)CoreDepositWallet.depositFor(safe, activation_amount, SPOT_DEX)
Note
New HyperCore accounts incur a 1 USDC account creation fee. The default
activation_amountof 2 USDC exceeds the fee.- Parameters
lagoon_vault (LagoonVault) – Lagoon vault instance with
trading_strategy_module_addressconfigured.activation_amount (int | None) – USDC amount in raw units (6 decimals) for activation. Defaults to
DEFAULT_ACTIVATION_AMOUNT(2 USDC).
- Returns
Bound
module.functions.multicall(data)ready to.transact().- Return type
ContractFunction
- build_hypercore_approve_deposit_wallet_call(lagoon_vault, evm_usdc_amount)
Build a single Safe transaction that approves USDC to CoreDepositWallet.
- Parameters
lagoon_vault (LagoonVault) –
evm_usdc_amount (int) –
- Return type
ContractFunction
- build_hypercore_deposit_for_spot_call(lagoon_vault, evm_usdc_amount, destination=None)
Build a single Safe transaction that bridges USDC to a specific HyperCore spot account.
- Parameters
lagoon_vault (LagoonVault) –
evm_usdc_amount (int) –
destination (HexAddress | str | None) –
- Return type
ContractFunction
- build_hypercore_deposit_multicall(lagoon_vault, evm_usdc_amount, hypercore_usdc_amount, vault_address, check_activation=False, chain_id=None, asset_address=None)
Build a single multicall transaction for the full Hypercore deposit flow.
Warning
The Safe must be activated on HyperCore before using the batched deposit. Pass
check_activation=Trueto automatically verify, or useactivate_account()beforehand. Without activation, deposited USDC gets permanently stuck in EVM escrow.Batches the 4-step deposit into one EVM transaction:
approve(CoreDepositWallet, amount)— approve USDC transferCoreDepositWallet.deposit(amount, SPOT_DEX)— bridge USDC to HyperCore spotCoreWriter.sendRawAction(transferUsdClass)— move USDC from spot to perpCoreWriter.sendRawAction(vaultTransfer)— deposit into vault
When the EVM block finishes execution, all queued CoreWriter actions are processed sequentially on HyperCore (~47k gas per action).
For extra safety under heavy HyperCore load, use the two-phase approach with
build_hypercore_deposit_phase1()andbuild_hypercore_deposit_phase2()withwait_for_evm_escrow_clear()between them.Derives all contract instances internally from the
LagoonVault:modulefromLagoonVault.trading_strategy_moduleusdc_contractfrom the vault’s underlying asset addresscore_deposit_walletfrom the chain ID (mainnet vs testnet)core_writerat the system addressCORE_WRITER_ADDRESS
Example:
from eth_defi.hyperliquid.core_writer import build_hypercore_deposit_multicall fn = build_hypercore_deposit_multicall( lagoon_vault=lagoon_vault, evm_usdc_amount=10_000 * 10**6, hypercore_usdc_amount=10_000 * 10**6, vault_address="0x...", check_activation=True, ) tx_hash = fn.transact({"from": asset_manager})- Parameters
lagoon_vault (LagoonVault) – Lagoon vault instance with
trading_strategy_module_addressconfigured.evm_usdc_amount (int) – USDC amount in EVM wei (uint256) for approve and CDW deposit.
hypercore_usdc_amount (int) – USDC amount in HyperCore wei (uint64) for CoreWriter actions.
vault_address (HexAddress | str) – Hypercore native vault address (not the Lagoon vault address).
check_activation (bool) – If
True, verifies the Safe is activated on HyperCore using thecoreUserExistsprecompile before building the multicall. Set toFalse(default) in simulate/Anvil mode where the precompile is not available.chain_id (int | None) – Override the chain ID used to look up the
CoreDepositWalletaddress. WhenNone(default), derived fromlagoon_vault.spec.chain_id. Pass explicitly when using aLagoonSatelliteVaultwhich has no.specattribute.asset_address (HexAddress | str | None) – Override the USDC token address used for the
approvecall. WhenNone(default), derived from the vault’s underlying asset (lagoon_vault.vault_contract.functions.asset()). Pass explicitly when using a satellite vault which has no.vault_contractattribute.
- Returns
Bound
module.functions.multicall(data)ready to.transact().- Raises
RuntimeError – If
check_activationis True and the Safe is not activated on HyperCore.- Return type
ContractFunction
- build_hypercore_deposit_phase1(lagoon_vault, evm_usdc_amount)
Build phase 1 of a two-phase Hypercore deposit: bridge USDC to HyperCore spot.
This multicall performs:
approve(CoreDepositWallet, amount)– approve USDC transferCoreDepositWallet.deposit(amount, SPOT_DEX)– bridge USDC to HyperCore spot
After this transaction lands, the USDC enters EVM escrow. Use
wait_for_evm_escrow_clear()to wait for the funds to arrive in the spot account, then callbuild_hypercore_deposit_phase2()for the remaining steps.Example:
from eth_defi.hyperliquid.core_writer import ( build_hypercore_deposit_phase1, build_hypercore_deposit_phase2, ) from eth_defi.hyperliquid.evm_escrow import wait_for_evm_escrow_clear # Phase 1: bridge USDC to HyperCore fn1 = build_hypercore_deposit_phase1(lagoon_vault, evm_usdc_amount=1_000_000) tx_hash = fn1.transact({"from": asset_manager}) # WARNING: Escrow clearance alone can be a misleading success signal # for fast-settling deposits. If the caller needs to prove that a # specific USDC amount reached HyperCore spot, pass expected_usdc and, # when available, a true pre-phase baseline to wait_for_evm_escrow_clear(). # Wait for escrow to clear wait_for_evm_escrow_clear(session, user=safe_address) # Phase 2: move to perp and deposit into vault fn2 = build_hypercore_deposit_phase2( lagoon_vault, hypercore_usdc_amount=1_000_000, vault_address="0x...", ) tx_hash = fn2.transact({"from": asset_manager})- Parameters
lagoon_vault (LagoonVault) – Lagoon vault instance with
trading_strategy_module_addressconfigured.evm_usdc_amount (int) – USDC amount in EVM wei (uint256) for approve and CDW deposit.
- Returns
Bound
module.functions.multicall(data)ready to.transact().- Return type
ContractFunction
- build_hypercore_deposit_phase2(lagoon_vault, hypercore_usdc_amount, vault_address)
Build phase 2 of a two-phase Hypercore deposit: spot to perp to vault.
Batches two CoreWriter actions into a single multicall:
transferUsdClass— move USDC from spot to perpvaultTransfer— deposit USDC from perp into vault
When the EVM block finishes execution, HyperCore processes all queued CoreWriter actions from that block sequentially, so the
transferUsdClasscompletes before thevaultTransferruns.Must only be called after phase 1 USDC has cleared the EVM escrow and is available in the user’s HyperCore spot account. Use
wait_for_evm_escrow_clear()between phase 1 and phase 2.- Parameters
lagoon_vault (LagoonVault) – Lagoon vault instance with
trading_strategy_module_addressconfigured.hypercore_usdc_amount (int) – USDC amount in HyperCore wei (uint64) for both CoreWriter actions.
vault_address (HexAddress | str) – Hypercore native vault address (not the Lagoon vault address).
- Returns
Bound
module.functions.multicall(data)ready to.transact().- Return type
ContractFunction
- build_hypercore_deposit_to_spot_call(lagoon_vault, evm_usdc_amount)
Build a single Safe transaction that bridges USDC from HyperEVM to HyperCore spot.
- Parameters
lagoon_vault (LagoonVault) –
evm_usdc_amount (int) –
- Return type
ContractFunction
- build_hypercore_deposit_to_vault_call(lagoon_vault, vault_address, hypercore_usdc_amount)
Build a single Safe transaction that deposits USDC from perp into a HyperCore vault.
- Parameters
lagoon_vault (LagoonVault) –
vault_address (HexAddress | str) –
hypercore_usdc_amount (int) –
- Return type
ContractFunction
- build_hypercore_send_asset_to_evm_call(lagoon_vault, evm_usdc_amount)
Build a single Safe transaction that bridges USDC from HyperCore spot back to HyperEVM.
- Parameters
evm_usdc_amount (int) – Amount in raw HyperEVM USDC decimals (6 decimals).
lagoon_vault (LagoonVault) –
- Return type
ContractFunction
Note
The bridged amount is subject to Hyperliquid Core -> HyperEVM bridge fees paid from the Safe’s spot balance. In manual mainnet verification, transaction 0x82c7ca18fed4952dfdfdffb4e7565cc768c2ab14fe7533bb42a0734cfdf36b16 returned 9 USDC to HyperEVM and consumed about 0.000783 USDC in spot bridge fees.
Warning
When bridging the entire spot balance, the caller must reduce
evm_usdc_amountto leave room for the bridge fee. Usecompute_spot_to_evm_withdrawal_amount()to compute the adjusted amount. Without this the withdrawal silently fails (no error, no event — USDC stays in spot).
- build_hypercore_spot_send_call(lagoon_vault, destination, hypercore_usdc_amount)
Build a single Safe transaction that sends USDC to another HyperCore spot account.
- Parameters
lagoon_vault (LagoonVault) –
destination (HexAddress | str) –
hypercore_usdc_amount (int) –
- Return type
ContractFunction
- build_hypercore_transfer_usd_class_call(lagoon_vault, hypercore_usdc_amount, to_perp)
Build a single Safe transaction that moves USDC between spot and perp.
- Parameters
lagoon_vault (LagoonVault) –
hypercore_usdc_amount (int) –
to_perp (bool) –
- Return type
ContractFunction
- build_hypercore_vault_transfer_call(lagoon_vault, vault_address, hypercore_usdc_amount, to_vault)
Build a single Safe transaction for one HyperCore
vaultTransferleg.This standalone builder is intended for composable multi-phase flows where the caller wants to execute and verify the vault leg separately from the later
transferUsdClassorsendAssetactions.- Parameters
lagoon_vault (LagoonVault) – Lagoon vault instance with
trading_strategy_module_addressconfigured.vault_address (HexAddress | str) – Hypercore native vault address.
hypercore_usdc_amount (int) – USDC amount in raw HyperCore / HyperEVM decimals (6 decimals).
to_vault (bool) –
Trueto deposit from perp to vault,Falseto withdraw from vault to perp.
- Return type
ContractFunction
- build_hypercore_withdraw_from_vault_call(lagoon_vault, vault_address, hypercore_usdc_amount)
Build a single Safe transaction that withdraws USDC from a HyperCore vault into perp.
- Parameters
lagoon_vault (LagoonVault) –
vault_address (HexAddress | str) –
hypercore_usdc_amount (int) –
- Return type
ContractFunction
- build_hypercore_withdraw_multicall(lagoon_vault, evm_usdc_amount, vault_address)
Build a single multicall transaction for the full Hypercore withdrawal flow.
Batches the 3-step withdrawal into one EVM transaction:
CoreWriter.sendRawAction(vaultTransfer)— withdraw from vaultCoreWriter.sendRawAction(transferUsdClass)— move USDC from perp to spotCoreWriter.sendRawAction(sendAsset)— bridge USDC back to HyperEVM
The final bridge leg is subject to Hyperliquid Core -> HyperEVM bridge fees paid from spot (see
HYPERCORE_BRIDGE_FEE_MARGIN). The fee is an extra deduction from spot — the EVM side receives exactly the requested amount — so the fee is absorbed by any pre-existing spot surplus. If the Safe has no pre-existing spot balance, the caller should usecompute_spot_to_evm_withdrawal_amount()to reduce the amount before building the multicall.When the EVM block finishes execution, all queued CoreWriter actions are processed sequentially on HyperCore (~47k gas per action).
Derives all contract instances internally from the
LagoonVault:modulefromLagoonVault.trading_strategy_modulecore_writerat the system addressCORE_WRITER_ADDRESS
- Parameters
lagoon_vault (LagoonVault) – Lagoon vault instance with
trading_strategy_module_addressconfigured.evm_usdc_amount (int) – USDC amount in raw HyperEVM decimals (6 decimals). The final
sendAssetleg is converted to linked-token wei internally.vault_address (HexAddress | str) – Hypercore native vault address (not the Lagoon vault address).
- Returns
Bound
module.functions.multicall(data)ready to.transact().- Return type
ContractFunction
- compute_spot_to_evm_withdrawal_amount(spot_balance, desired_amount)
Compute the actual
sendAssetamount after reserving bridge fee margin.HyperCore charges a bridge fee on spot before the linked token settles on HyperEVM. When the caller intends to bridge the entire spot balance, the requested amount must be reduced by
HYPERCORE_BRIDGE_FEE_MARGINso that enough USDC remains on spot to cover the fee.If the desired amount already leaves sufficient margin (
spot_balance - desired_amount >= HYPERCORE_BRIDGE_FEE_MARGIN), it is returned unchanged.If the spot balance is too small (at or below the fee margin), returns
Decimal(0)— callers must check for this and skip the withdrawal or raise an operator error.- Parameters
spot_balance (decimal.Decimal) – Current HyperCore spot free USDC balance (human-readable).
desired_amount (decimal.Decimal) – Amount the caller wants to bridge to HyperEVM (human-readable).
- Returns
Adjusted withdrawal amount (human-readable). May be zero if the spot balance cannot cover the fee margin.
- Return type
- convert_evm_raw_amount_to_linked_token_wei(token_id, evm_amount_raw)
Convert a linked-token EVM raw amount to the CoreWriter
sendAssetamount.
- encode_send_asset(destination, sub_account, source_dex, destination_dex, token_id, amount_wei)
Encode a CoreWriter sendAsset action (action ID 13).
sendAssetis the documented CoreWriter path for linked-token transfers between HyperCore spot and HyperEVM spot. To bridge USDC from HyperCore back to HyperEVM, pass the USDC system address asdestinationandSPOT_DEXfor both dex fields.
- encode_send_asset_to_evm(token_id, evm_amount_raw, sub_account='0x0000000000000000000000000000000000000000')
Encode a linked-token transfer from HyperCore spot back to HyperEVM.
- Parameters
evm_amount_raw (int) – Amount in the linked EVM token’s raw decimals, e.g. 6 decimals for USDC.
token_id (int) –
sub_account (Union[eth_typing.evm.HexAddress, str]) –
- Return type
Note
Hyperliquid charges the Core -> HyperEVM bridge fee on spot before settlement. In manual mainnet verification, a 9 USDC withdrawal in 0x82c7ca18fed4952dfdfdffb4e7565cc768c2ab14fe7533bb42a0734cfdf36b16 consumed about 0.000783 USDC in bridge fees on spot.
- encode_spot_send(destination, token_id, amount_wei)
Encode a CoreWriter spotSend action (action ID 6).
Sends tokens between HyperCore spot accounts.
Note
This does not bridge linked tokens back to HyperEVM. For Core -> HyperEVM USDC withdrawals use
encode_send_asset()with the token’s system address as the destination.- Parameters
destination (Union[eth_typing.evm.HexAddress, str]) – Recipient address (typically the Safe address for bridging back).
token_id (int) – HyperCore token index (0 = USDC).
amount_wei (int) – Amount in HyperCore wei (uint64).
- Returns
Raw action bytes for
CoreWriter.sendRawAction().- Return type
- encode_transfer_usd_class(amount_wei, to_perp)
Encode a CoreWriter transferUsdClass action (action ID 7).
Moves USDC between spot and perp accounts on HyperCore.
- encode_vault_deposit(vault, usdc_amount_wei)
Encode a CoreWriter vaultTransfer deposit action (action ID 2).
- Parameters
vault (Union[eth_typing.evm.HexAddress, str]) – Hypercore native vault address.
usdc_amount_wei (int) – USDC amount in HyperCore wei (uint64). Note: HyperCore uses different decimal representations than EVM.
- Returns
Raw action bytes for
CoreWriter.sendRawAction().- Raises
AssertionError – If the deposit amount is below
MINIMUM_VAULT_DEPOSIT.- Return type
- encode_vault_withdraw(vault, usdc_amount_wei)
Encode a CoreWriter vaultTransfer withdraw action (action ID 2).
- Parameters
vault (Union[eth_typing.evm.HexAddress, str]) – Hypercore native vault address.
usdc_amount_wei (int) – USDC amount in HyperCore wei (uint64).
- Returns
Raw action bytes for
CoreWriter.sendRawAction().- Return type
- fetch_token_system_address(token_id)
Get the HyperCore system address for a linked token index.
- Parameters
token_id (int) –
- Return type
- get_core_deposit_wallet_contract(web3, address)
Get a Contract instance for the CoreDepositWallet.
Uses the MockCoreDepositWallet ABI which has the same
deposit(uint256,uint32)signature as the real CoreDepositWallet.- Parameters
web3 (web3.main.Web3) – Web3 connection.
address (Union[eth_typing.evm.HexAddress, str]) – CoreDepositWallet address (use
CORE_DEPOSIT_WALLETwith chain ID).
- Returns
Contract instance with the CoreDepositWallet ABI.
- Return type
web3.contract.contract.Contract
- get_core_writer_contract(web3)
Get a Contract instance for the CoreWriter system contract.
Uses the MockCoreWriter ABI which exposes the same
sendRawAction(bytes)interface as the real CoreWriter precompile.- Parameters
web3 (web3.main.Web3) – Web3 connection.
- Returns
Contract instance at
CORE_WRITER_ADDRESS.- Return type
web3.contract.contract.Contract