diff --git a/src/CoreWriterLib.sol b/src/CoreWriterLib.sol index e01270f..d1d9fe7 100644 --- a/src/CoreWriterLib.sol +++ b/src/CoreWriterLib.sol @@ -86,10 +86,8 @@ library CoreWriterLib { bridgeToEvm(tokenIndex, evmAmount, true); } - // NOTE: For bridging non-HYPE tokens, the contract must hold some HYPE on core (enough to cover the transfer gas), otherwise spotSend will fail + // NOTE: For bridging non-HYPE tokens, the contract must hold some HYPE on core (enough to cover the transfer gas), otherwise sendAsset will fail function bridgeToEvm(uint64 token, uint256 amount, bool isEvmAmount) internal { - address systemAddress = getSystemAddress(token); - uint64 coreAmount; if (isEvmAmount) { coreAmount = HLConversions.evmToWei(token, amount); @@ -99,7 +97,14 @@ library CoreWriterLib { coreAmount = uint64(amount); } - spotSend(systemAddress, token, coreAmount); + sendAsset( + getSystemAddress(token), + address(0), + HLConstants.SPOT_DEX, + HLConstants.SPOT_DEX, + token, + coreAmount + ); } function spotSend(address to, uint64 token, uint64 amountWei) internal { diff --git a/src/examples/BridgeToEvmTest.sol b/src/examples/BridgeToEvmTest.sol new file mode 100644 index 0000000..c0d8a85 --- /dev/null +++ b/src/examples/BridgeToEvmTest.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {CoreWriterLib, HLConstants} from "@hyper-evm-lib/src/CoreWriterLib.sol"; + +contract BridgeToEvmTest { + using SafeERC20 for IERC20; + + address public immutable owner; + + modifier onlyOwner() { + require(msg.sender == owner, "not owner"); + _; + } + + constructor() payable { + owner = msg.sender; + } + + function bridgeToCore(uint64 token, uint256 evmAmount) external payable onlyOwner { + CoreWriterLib.bridgeToCore(token, evmAmount); + } + + function bridgeToEvm(uint64 token, uint256 evmAmount) external onlyOwner { + CoreWriterLib.bridgeToEvm(token, evmAmount, true); + } + + function bridgeToEvmCoreAmount(uint64 token, uint64 coreAmount) external onlyOwner { + CoreWriterLib.bridgeToEvm(token, coreAmount, false); + } + + function withdrawERC20(address token, uint256 amount) external onlyOwner { + IERC20(token).safeTransfer(owner, amount); + } + + function withdrawETH() external onlyOwner { + (bool success,) = owner.call{value: address(this).balance}(""); + require(success, "ETH transfer failed"); + } + + receive() external payable {} +} diff --git a/test/simulation/HyperCore.sol b/test/simulation/HyperCore.sol index 8a01daa..4c04a56 100644 --- a/test/simulation/HyperCore.sol +++ b/test/simulation/HyperCore.sol @@ -46,6 +46,11 @@ contract HyperCore is CoreExecution { return; } + if (kind == HLConstants.SEND_ASSET_ACTION) { + executeSendAsset(sender, abi.decode(data, (SendAssetAction))); + return; + } + if (kind == HLConstants.USD_CLASS_TRANSFER_ACTION) { executeUsdClassTransfer(sender, abi.decode(data, (UsdClassTransferAction))); return; diff --git a/test/simulation/hyper-core/CoreExecution.sol b/test/simulation/hyper-core/CoreExecution.sol index 0cd51a1..26ae167 100644 --- a/test/simulation/hyper-core/CoreExecution.sol +++ b/test/simulation/hyper-core/CoreExecution.sol @@ -446,6 +446,21 @@ contract CoreExecution is CoreView { } } + function executeSendAsset(address sender, SendAssetAction memory action) public { + require( + action.source_dex == HLConstants.SPOT_DEX && action.destination_dex == HLConstants.SPOT_DEX, + "only SPOT_DEX supported in simulator" + ); + + // When destination is BASE_SYSTEM_ADDRESS, map to token-specific system address for EVM bridging + address destination = action.destination; + if (destination == address(HLConstants.BASE_SYSTEM_ADDRESS)) { + destination = CoreWriterLib.getSystemAddress(action.token); + } + + executeSpotSend(sender, SpotSendAction(destination, action.token, action.amountWei)); + } + function executeUsdClassTransfer(address sender, UsdClassTransferAction memory action) public initAccountWithToken(sender, USDC_TOKEN_INDEX) diff --git a/test/simulation/hyper-core/CoreState.sol b/test/simulation/hyper-core/CoreState.sol index f8611b8..cb2071d 100644 --- a/test/simulation/hyper-core/CoreState.sol +++ b/test/simulation/hyper-core/CoreState.sol @@ -452,6 +452,15 @@ contract CoreState is StdCheats { uint64 _wei; } + struct SendAssetAction { + address destination; + address subAccount; + uint32 source_dex; + uint32 destination_dex; + uint64 token; + uint64 amountWei; + } + struct UsdClassTransferAction { uint64 ntl; bool toPerp;