Interacting with HyperCore
Read precompiles
The testnet EVM provides read precompiles that allows querying HyperCore information. The precompile addresses start at 0x0000000000000000000000000000000000000800 and have methods for querying information such as perps positions, spot balances, vault equity, staking delegations, oracle prices, and the L1 block number.
The values are guaranteed to match the latest HyperCore state at the time the EVM block is constructed.
Attached is a Solidity file L1Read.sol
describing the read precompiles. As an example, this call queries the third perp oracle price on testnet:
cast call 0x0000000000000000000000000000000000000807 0x0000000000000000000000000000000000000000000000000000000000000003 --rpc-url https://rpc.hyperliquid-testnet.xyz/evm
To convert to floating point numbers, divide the returned price by 10^(6 - szDecimals)
for perps and 10^(8 - base asset szDecimals)
for spot.
Precompiles called on invalid inputs such as invalid assets or vault address will return an error and consume all gas passed into the precompile call frame. Precompiles have a gas cost of 2000 + 65 * output_len
.
CoreWriter contract
A system contract is available at 0x3333333333333333333333333333333333333333 for sending transactions from the HyperEVM to HyperCore. It burns ~25,000 gas before emitting a log to be processed by HyperCore as an action. In practice the gas usage for a basic call will be ~47000. A solidity file CoreWriter.sol
for the write system contract is attached.
Action encoding details
Byte 1: Encoding version
Currently, only version
1
is supported, but enables future upgrades while maintaining backward compatibility.
Bytes 2-4: Action ID
These three bytes, when decoded as a big-endian unsigned integer, represent the unique identifier for the action.
Remaining bytes: Action encoding
The rest of the bytes constitue the action-specific data. It is always the raw ABI encoding of a sequence of Solidity types
To prevent any potential latency advantages for using HyperEVM to bypass the L1 mempool, order actions and vault transfers sent from CoreWriter are delayed onchain for a few seconds. This has no noticeable effect on UX because the end user has to wait for at least one small block confirmation. These onchain-delayed actions appear twice in the L1 explorer: first as an enqueuing and second as a HyperCore execution.
1
Limit order
(asset, isBuy, limitPx, sz, reduceOnly, encodedTif, cloid)
(uint32, bool, uint64, uint64, bool, uint8, uint128)
Tif encoding: 1
for Alo
, 2
for Gtc
, 3
for Ioc
. Cloid encoding: 0 means no cloid, otherwise uses the number as the cloid. limitPx and sz should be sent as 10^8 * the human readable value
2
Vault transfer
(vault, isDeposit, usd)
(address, bool, uint64)
3
Token delegate
(validator, wei, isUndelegate)
(address, uint64, bool)
4
Staking deposit
wei
uint64
5
Staking withdraw
wei
uint64
6
Spot send
(destination, token, wei)
(address, uint64, uint64)
7
USD class transfer
(ntl, toPerp)
(uint64, bool)
8
Finalize EVM Contract
(token, encodedFinalizeEvmContractVariant, createNonce)
(uint64, uint8, uint64)
encodedFinalizeEvmContractVariant 1
for Create
, 2
for FirstStorageSlot
, 3
for CustomStorageSlot
. If Create
variant, then createNonce
input argument is used.
9
Add API wallet
(API wallet address, API wallet name)
(address, string)
If the API wallet name is empty then this becomes the main API wallet / agent
10
Cancel order by oid
(asset, oid)
(uint32, uint64)
11
Cancel order by cloid
(asset, cloid)
(uint32, uint128)
Below is an example contract that would send an action on behalf of its own contract address on HyperCore, which also demonstrates one way to construct the encoded action in Solidity.
contract CoreWriterCaller {
function sendUsdClassTransfer(uint64 ntl, bool toPerp) external {
bytes memory encodedAction = abi.encode(ntl, toPerp);
bytes memory data = new bytes(4 + encodedAction.length);
data[0] = 0x01;
data[1] = 0x00;
data[2] = 0x00;
data[3] = 0x07;
for (uint256 i = 0; i < encodedAction.length; i++) {
data[4 + i] = encodedAction[i];
}
CoreWriter(0x3333333333333333333333333333333333333333).sendRawAction(data);
}
}
Happy building. Any feedback is appreciated.
Last updated