11// SPDX-License-Identifier: UNLICENSED
22pragma solidity ^ 0.8.0 ;
33
4- import { Test, console } from "forge-std/Test.sol " ;
5-
6- import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol " ;
7- import { OFTComposeMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTComposeMsgCodec.sol " ;
84import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol " ;
95
10- import { HyperLiquidComposer, IHyperAsset } from "@layerzerolabs/hyperliquid-composer/contracts/HyperLiquidComposer.sol " ;
11- import { ICoreWriter } from "@layerzerolabs/hyperliquid-composer/contracts/interfaces/ICoreWriter.sol " ;
12-
13- import { HyperLiquidComposerCodec } from "@layerzerolabs/hyperliquid-composer/contracts/library/HyperLiquidComposerCodec.sol " ;
6+ import { OFTComposeMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTComposeMsgCodec.sol " ;
147
8+ import { IHyperAsset } from "@layerzerolabs/hyperliquid-composer/contracts/interfaces/IHyperLiquidComposerCore.sol " ;
159import { IHYPEPrecompile } from "@layerzerolabs/hyperliquid-composer/contracts/interfaces/IHYPEPrecompile.sol " ;
16- import { HypePrecompileMock } from "@layerzerolabs/hyperliquid-composer/test/mocks/HypePrecompileMock.sol " ;
17- import { SpotBalancePrecompileMock } from "@layerzerolabs/hyperliquid-composer/test/mocks/SpotBalancePrecompileMock.sol " ;
10+ import { ICoreWriter } from "@layerzerolabs/hyperliquid-composer/contracts/interfaces/ICoreWriter.sol " ;
1811
1912import { MyOFT } from "../../contracts/MyOFT.sol " ;
13+ import { SpotBalancePrecompileMock } from "@layerzerolabs/hyperliquid-composer/test/mocks/SpotBalancePrecompileMock.sol " ;
2014
21- contract HyperLiquidComposerTest is Test {
22- IHyperAsset public ALICE;
23- IHyperAsset public HYPE;
24- address public constant HL_LZ_ENDPOINT_V2 = 0xf9e1815F151024bDE4B7C10BAC10e8Ba9F6b53E1 ;
25-
26- address public constant HL_LZ_ENDPOINT_V2_TESTNET = 0xf9e1815F151024bDE4B7C10BAC10e8Ba9F6b53E1 ;
27- address public constant HL_LZ_ENDPOINT_V2_MAINNET = 0x3A73033C0b1407574C76BdBAc67f126f6b4a9AA9 ;
28-
29- address public constant HLP_CORE_WRITER = 0x3333333333333333333333333333333333333333 ;
30- address public constant HLP_PRECOMPILE_READ_SPOT_BALANCE = 0x0000000000000000000000000000000000000801 ;
31- // Ethereum Sepolia
32- uint32 public constant SRC_EID = 40161 ;
33- // HyperLiquid Testnet
34- uint32 public DST_EID;
35-
36- MyOFT public oft;
37- HyperLiquidComposer public hyperLiquidComposer;
38-
39- address public userA = makeAddr ("userA " );
40- address public userB = makeAddr ("userB " );
41-
42- uint64 public constant AMOUNT_TO_SEND = 1e18 ;
43- uint64 public constant AMOUNT_TO_FUND = 100 gwei ;
44- uint64 public constant DUST = 1 wei ;
45-
46- function setUp () public {
47- // Skip test if fork fails
48- try vm.createSelectFork ("https://rpc.hyperliquid-testnet.xyz/evm " ) {} catch {
49- console.log ("Forking testnet https://rpc.hyperliquid-testnet.xyz/evm failed " );
50- vm.skip (true );
51- }
52-
53- ALICE = IHyperAsset ({
54- assetBridgeAddress: HyperLiquidComposerCodec.into_assetBridgeAddress (1231 ),
55- coreIndexId: 1231 ,
56- decimalDiff: 18 - 6
57- });
58-
59- HYPE = IHyperAsset ({
60- assetBridgeAddress: 0x2222222222222222222222222222222222222222 ,
61- coreIndexId: 1105 ,
62- decimalDiff: 18 - 10
63- });
64-
65- vm.etch (HLP_PRECOMPILE_READ_SPOT_BALANCE, address (new SpotBalancePrecompileMock ()).code);
66- SpotBalancePrecompileMock (HLP_PRECOMPILE_READ_SPOT_BALANCE).setSpotBalance (
67- ALICE.assetBridgeAddress,
68- ALICE.coreIndexId,
69- type (uint64 ).max
70- );
71-
72- SpotBalancePrecompileMock (HLP_PRECOMPILE_READ_SPOT_BALANCE).setSpotBalance (
73- HYPE.assetBridgeAddress,
74- HYPE.coreIndexId,
75- type (uint64 ).max
76- );
77-
78- oft = new MyOFT ("test " , "test " , HL_LZ_ENDPOINT_V2, msg .sender );
15+ import { HyperLiquidComposer } from "@layerzerolabs/hyperliquid-composer/contracts/HyperLiquidComposer.sol " ;
7916
80- hyperLiquidComposer = new HyperLiquidComposer (
81- HL_LZ_ENDPOINT_V2,
82- address (oft),
83- ALICE.coreIndexId,
84- ALICE.decimalDiff
85- );
86- DST_EID = oft.endpoint ().eid ();
17+ import { HyperliquidBaseTest } from "@layerzerolabs/hyperliquid-composer/test/HyperliquidBase.t.sol " ;
18+ import { console } from "forge-std/Test.sol " ;
8719
88- vm.deal (HL_LZ_ENDPOINT_V2, 100 ether);
20+ contract HyperLiquidComposerTest is HyperliquidBaseTest {
21+ function setUp () public override {
22+ super .setUp ();
8923 }
9024
9125 function test_deployment () public view {
9226 IHyperAsset memory hypeAsset = hyperLiquidComposer.getHypeAsset ();
9327 assertEq (hypeAsset.assetBridgeAddress, 0x2222222222222222222222222222222222222222 );
94- assertEq (hypeAsset.coreIndexId, 1105 );
28+ uint256 expectedHypeCoreIndexId = block .chainid == 998 ? 1105 : 150 ;
29+ assertEq (hypeAsset.coreIndexId, expectedHypeCoreIndexId);
9530 assertEq (hypeAsset.decimalDiff, 10 );
9631
9732 IHyperAsset memory oftAsset = hyperLiquidComposer.getOFTAsset ();
98- assertEq (oftAsset.assetBridgeAddress, ALICE .assetBridgeAddress);
99- assertEq (oftAsset.coreIndexId, ALICE .coreIndexId);
100- assertEq (oftAsset.decimalDiff, ALICE .decimalDiff);
33+ assertEq (oftAsset.assetBridgeAddress, ERC20 .assetBridgeAddress);
34+ assertEq (oftAsset.coreIndexId, ERC20 .coreIndexId);
35+ assertEq (oftAsset.decimalDiff, ERC20 .decimalDiff);
10136 }
10237
10338 function test_hypeIndexByChainId_testnet () public {
104- try vm.createSelectFork ("https://rpc.hyperliquid-testnet.xyz/evm " ) {} catch {
105- console.log ("Forking testnet https://rpc.hyperliquid-testnet.xyz/evm failed " );
39+ string memory rpcUrl = "https://rpc.hyperliquid-testnet.xyz/evm " ;
40+ try vm.envString ("RPC_URL_HYPERLIQUID_TESTNET " ) returns (string memory _rpcUrl ) {
41+ rpcUrl = _rpcUrl;
42+ } catch {
43+ console.log ("Using default mainnet RPC URL " );
44+ }
45+ // Skip test if fork fails
46+ try vm.createSelectFork (rpcUrl) {} catch {
47+ console.log ("Forking testnet " , rpcUrl, " failed " );
10648 vm.skip (true );
10749 }
10850
10951 MyOFT oftTestnet = new MyOFT ("test " , "test " , HL_LZ_ENDPOINT_V2_TESTNET, msg .sender );
11052 HyperLiquidComposer hypeComposerTestnet = new HyperLiquidComposer (
11153 HL_LZ_ENDPOINT_V2_TESTNET,
11254 address (oftTestnet),
113- ALICE .coreIndexId,
114- ALICE .decimalDiff
55+ ERC20 .coreIndexId,
56+ ERC20 .decimalDiff
11557 );
11658
11759 assertEq (hypeComposerTestnet.hypeIndexByChainId (998 ), 1105 );
11860 }
11961
12062 function test_hypeIndexByChainId_mainnet () public {
121- try vm.createSelectFork ("https://rpc.hyperliquid.xyz/evm " ) {} catch {
122- console.log ("Forking mainnet https://rpc.hyperliquid.xyz/evm failed " );
63+ string memory rpcUrl = "https://rpc.hyperliquid.xyz/evm " ;
64+ try vm.envString ("RPC_URL_HYPERLIQUID_MAINNET " ) returns (string memory _rpcUrl ) {
65+ rpcUrl = _rpcUrl;
66+ } catch {
67+ console.log ("Using default mainnet RPC URL " );
68+ }
69+ // Skip test if fork fails
70+ try vm.createSelectFork (rpcUrl) {} catch {
71+ console.log ("Forking mainnet " , rpcUrl, " failed " );
12372 vm.skip (true );
12473 }
12574
12675 MyOFT oftMainnet = new MyOFT ("test " , "test " , HL_LZ_ENDPOINT_V2_MAINNET, msg .sender );
12776 HyperLiquidComposer hypeComposerMainnet = new HyperLiquidComposer (
12877 HL_LZ_ENDPOINT_V2_MAINNET,
12978 address (oftMainnet),
130- ALICE .coreIndexId,
131- ALICE .decimalDiff
79+ ERC20 .coreIndexId,
80+ ERC20 .decimalDiff
13281 );
13382
13483 assertEq (hypeComposerMainnet.hypeIndexByChainId (999 ), 150 );
@@ -140,7 +89,7 @@ contract HyperLiquidComposerTest is Test {
14089 // Build composerMsg similar to the outcome of OFTCore.send()
14190 bytes memory composerMsg_ = OFTComposeMsgCodec.encode (
14291 0 ,
143- SRC_EID ,
92+ ETH_EID ,
14493 AMOUNT_TO_SEND + DUST,
14594 abi.encodePacked (addressToBytes32 (userA), composeMsg)
14695 );
@@ -151,10 +100,10 @@ contract HyperLiquidComposerTest is Test {
151100
152101 // Expect the Transfer event to be emitted
153102 vm.expectEmit (address (oft));
154- emit IERC20 .Transfer (address (hyperLiquidComposer), ALICE .assetBridgeAddress, AMOUNT_TO_SEND);
103+ emit IERC20 .Transfer (address (hyperLiquidComposer), ERC20 .assetBridgeAddress, AMOUNT_TO_SEND);
155104
156105 uint64 coreAmount = hyperLiquidComposer.quoteHyperCoreAmount (AMOUNT_TO_SEND, true ).core;
157- bytes memory action = abi.encode (userB, ALICE .coreIndexId, coreAmount);
106+ bytes memory action = abi.encode (userB, ERC20 .coreIndexId, coreAmount);
158107 bytes memory payload = abi.encodePacked (hyperLiquidComposer.SPOT_SEND_HEADER (), action);
159108 vm.expectEmit (HLP_CORE_WRITER);
160109 emit ICoreWriter.RawAction (address (hyperLiquidComposer), payload);
@@ -175,7 +124,7 @@ contract HyperLiquidComposerTest is Test {
175124 // Build composerMsg similar to the outcome of OFTCore.send()
176125 bytes memory composerMsg_ = OFTComposeMsgCodec.encode (
177126 0 ,
178- SRC_EID ,
127+ ETH_EID ,
179128 AMOUNT_TO_SEND,
180129 abi.encodePacked (addressToBytes32 (userA), composeMsg)
181130 );
@@ -189,10 +138,10 @@ contract HyperLiquidComposerTest is Test {
189138
190139 // Expect the Transfer event to be emitted
191140 vm.expectEmit (address (oft));
192- emit IERC20 .Transfer (address (hyperLiquidComposer), ALICE .assetBridgeAddress, AMOUNT_TO_SEND);
141+ emit IERC20 .Transfer (address (hyperLiquidComposer), ERC20 .assetBridgeAddress, AMOUNT_TO_SEND);
193142
194143 uint64 coreAmount = hyperLiquidComposer.quoteHyperCoreAmount (AMOUNT_TO_SEND, true ).core;
195- bytes memory action = abi.encode (userB, ALICE .coreIndexId, coreAmount);
144+ bytes memory action = abi.encode (userB, ERC20 .coreIndexId, coreAmount);
196145 bytes memory payload = abi.encodePacked (hyperLiquidComposer.SPOT_SEND_HEADER (), action);
197146 vm.expectEmit (HLP_CORE_WRITER);
198147 emit ICoreWriter.RawAction (address (hyperLiquidComposer), payload);
0 commit comments