本文へ移動
レビューを依頼

HyperEVM 開発 · HyperEVM の DeFi · 8/8

L1 の売買と組み合わせる

組み合わせの狙い

HyperEVM の約束は、スマートコントラクトがネイティブの板と組み合わさることです。コントラクトは precompile で HyperCore を読み、0x3333333333333333333333333333333333333333 にある CoreWriter というシステムコントラクトで HyperCore に書き込みます。そのため戦略は、すべてチェーン上で動かすことも、コントラクトとチェーン外の keeper で仕事を分けることもできます。

構成の型

型1: スマートコントラクトの vault + keeper

HyperEVM (On-Chain)          L1 (Order Book)
┌─────────────────┐          ┌──────────────┐
│  Vault Contract │          │  Positions   │
│  - Deposits     │          │  - BTC Long  │
│  - Shares       │◄────────►│  - ETH Short │
│  - Accounting   │  Keeper  │  - Funding   │
└─────────────────┘          └──────────────┘

vault コントラクトは HyperEVM 上で預け入れと持ち分の計算を受け持ちます。実際の売買は keeper のボットが L1 で行います。keeper は vault の資産額を読み、それに比例してポジションを調整します。

型2: チェーン上で価格を点検する

// A contract that flags when a market's mark price drifts away from its oracle.
// PriceReader is the contract from the "Reading L1 State" lesson.
contract DeviationWatch is PriceReader {
    event Deviation(uint32 perpIndex, uint64 markPx, uint64 oraclePx);

    function check(uint32 perpIndex) external {
        uint64 mark = markPx(perpIndex);
        uint64 oracle = oraclePx(perpIndex);

        // Flag a gap of more than 0.5% of the oracle price, in either direction
        // (an oracle of 0 means the market has no price yet: flag it too)
        uint256 gap = mark > oracle ? uint256(mark - oracle) : uint256(oracle - mark);
        if (oracle == 0 || gap * 1000 > uint256(oracle) * 5) {
            emit Deviation(perpIndex, mark, oracle);
        }
    }
}

keeper は Deviation イベントを見張り、チェーンの外で対応します。たとえば自分の気配値を止めたり、市場を運営する人に知らせたりします。

型3: CoreWriter で直接売買する

コントラクトは、CoreWriter の sendRawAction を呼ぶことで、自分の HyperCore 口座の注文を出せます。中身は、バージョンの1バイト(0x01)、3バイトの操作 ID、そのあとに ABI でエンコードした項目が続きます。操作 1 は指値注文です(操作の一覧)。

// Testnet only — sketch, no access control
interface ICoreWriter {
    function sendRawAction(bytes calldata data) external;
}

contract CoreTrader {
    ICoreWriter constant CORE_WRITER =
        ICoreWriter(0x3333333333333333333333333333333333333333);

    // limitPx and sz are 10^8 * the human-readable value
    function placeLimitOrder(uint32 asset, bool isBuy, uint64 limitPx, uint64 sz) external {
        bytes memory fields = abi.encode(
            asset, isBuy, limitPx, sz,
            false,       // reduceOnly
            uint8(3),    // tif: 1 = Alo, 2 = Gtc, 3 = Ioc
            uint128(0)   // cloid: 0 = none
        );
        // version 1, action ID 1 (limit order)
        CORE_WRITER.sendRawAction(abi.encodePacked(uint8(1), uint24(1), fields));
    }
}

知っておくこと:

テストネットでの実測(2026-10-17〜19、hyperevm-amm と hyperevm-perp)。どちらも学習用のプロジェクトで、監査は受けていません。

環境をまたぐ流れ

預け入れの流れ

  1. ユーザーが、紐づけ済みのトークン(例: USDC)を HyperEVM の vault コントラクトに預けます
  2. コントラクトがユーザーに持ち分を発行します
  3. コントラクト(またはそれを呼ぶ keeper)が、トークンをそのトークンのシステムアドレスに送ります。これでコントラクトの HyperCore の現物残高に入金されます。ただしテストネット(2026-10-17)では、USDC でうまくいきませんでした。Circle の CoreDepositWallet を通したコントラクトの HyperCore 口座への入金は、誰が呼んでも入りませんでした。EOA への入金は 1 秒以内に届きました。テストネットだけの制限と報告されていて、メインネットではコントラクトにも入金されるとのことです。頼る前に少額で試してください
  4. ポジションは、CoreWriter で建てるか(コントラクトが主導)、コントラクトが CoreWriter の操作 9 で承認した agent wallet から API で建てます

引き出しの流れ

  1. ユーザーが HyperEVM 上で引き出しを申し込みます
  2. コントラクトが持ち分を焼却し、イベントを出します
  3. 比例する分の HyperCore のポジションを閉じます
  4. CoreWriter の現物送金(操作 6)で、トークンのシステムアドレスに送り、資金を HyperEVM に戻します
  5. あとの EVM ブロックで届いたら、USDC をユーザーに送ります

テストネットでは、Core → EVM の送金は次に読んだときには届いていました(USDC は 1 秒以内)。注意点が 3 つあります。届いてもコントラクトの receive() は呼ばれず、残高が増えるだけです。HYPE 以外のトークンを送るときは、コントラクトの HyperCore 口座の HYPE が少し要ります(USDC で 0.00002 HYPE)。そして、新しい HyperCore 口座への最初の送金には、口座の有効化として約 1 USDC かかります(コントラクトから HYPE を送ったときは、送った額から差し引かれました)

Core → EVM の送金はあとのブロックで届きます。そのため引き出しは非同期になります。「申し込んでから受け取る」形で設計してください。

システム全体を作る

// Keeper that connects a HyperEVM vault to HyperCore trading (ethers v6)
import { ethers, EventLog } from "ethers";

class HybridVaultKeeper {
    constructor(
        private vaultContract: ethers.Contract,
        // plus a HyperCore API client of your choice, signing with an agent wallet
    ) {}

    async processDeposit(event: EventLog) {
        const amount = event.args.amount;
        // Move funds to the vault's HyperCore account (system address transfer)
        // Open positions proportional to deposit
    }

    async processWithdrawal(event: EventLog) {
        const shares = event.args.shares;
        // Calculate proportional position to close
        // Close HyperCore positions
        // Move USDC back to HyperEVM, then let the user claim
    }
}

これから

作り手たちが試している方向です。

HyperEVM と HyperCore の間で、フラッシュローンのような一度にまとめた裁定はできません。CoreWriter の操作は EVM ブロックのあとに実行され、注文にはさらにチェーン上の遅れがあるからです。