Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions contracts/handlers/HypercoreDepositorHandler.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.0;

import "../interfaces/SpokePoolMessageHandler.sol";
import "@openzeppelin/contracts-v4/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts-v4/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts-v4/security/ReentrancyGuard.sol";
import { CoreWriterLib, PrecompileLib } from "hyper-evm-lib/src/CoreWriterLib.sol";
import { HLConversions } from "hyper-evm-lib/src/common/HLConversions.sol";

/**
* @title Allows caller to bridge tokens from HyperEVM to Hypercore and send them to an end user's account
* on Hypercore.
* @dev This contract should only be deployed on HyperEVM.
* @dev This contract can replace a MulticallHandler on HyperEVM if the intent only wants to deposit tokens into
* Hypercore and bypass the other complex arbitrary calldata logic.
* @dev This contract can also be called directly to deposit tokens into Hypercore on behalf of an end user.
*/
contract HypercoreDepositorHandler is AcrossMessageHandler, ReentrancyGuard {
using SafeERC20 for IERC20;

/**
* @notice Bridges tokens from HyperEVM to Hypercore and sends them to the end user's account on Hypercore.
* @dev Requires msg.sender to have approved this contract to spend the tokens.
* @param token The address of the token to deposit.
* @param amount The amount of tokens on HyperEVM to deposit.
* @param user The address of the user on Hypercore to send the tokens to.
*/
function depositToHypercore(address token, uint256 amount, address user) external nonReentrant {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assumes that the tokens are dropped on the contract atomically, right?

What are the downsides of doing a transferFrom from msg.sender to pull the tokens in?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's a great call, I overlooked this flow. We definitely should pull funds from the msg.sender in depositToHypercore, unlike in handleAcrossV3Message

IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
_bridgeToCore(token, amount);
_spotSend(user, token, amount);
}

/**
* @notice Entrypoint function if this contract is called by the SpokePool contract following an intent fill.
* @dev Deposits tokens into Hypercore and sends them to the end user's account on Hypercore.
* @param token The address of the token sent.
* @param amount The amount of tokens received by this contract.
* @param message Encoded end user address.
*/
function handleV3AcrossMessage(
address token,
uint256 amount,
address /* relayer */,
bytes memory message
) external nonReentrant {
address user = abi.decode(message, (address));
_bridgeToCore(token, amount);
_spotSend(user, token, amount);
}

function _bridgeToCore(address token, uint256 evmAmount) internal {
// Bridge tokens from HyperEVM to Hypercore. This call should revert if this contract has insufficient balance.
CoreWriterLib.bridgeToCore(token, evmAmount);
}

function _spotSend(address user, address token, uint256 evmAmount) internal {
// Convert EVM amount to wei amount (used in HyperCore)
uint64 tokenIndex = PrecompileLib.getTokenIndex(token);
uint64 coreAmount = HLConversions.evmToWei(tokenIndex, evmAmount);

// use CoreWriterLib to call the spotSend CoreWriter action and send tokens to end user.
// @dev: the following call does not execute atomically with the deposit into Hypercore.
// Therefore, this contract will maintain a balance of tokens for one block until the spot send into Hypercore
// is confirmed.
CoreWriterLib.spotSend(user, tokenIndex, coreAmount);
}

// Native tokens are not supported by this contract.
}
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ remappings = [
"eth-gas-reporter/=node_modules/eth-gas-reporter/",
"hardhat-deploy/=node_modules/hardhat-deploy/",
"hardhat/=node_modules/hardhat/",
"hyper-evm-lib=node_modules/hyper-evm-lib/",
]
via_ir = true
optimizer_runs = 800
Expand Down
36 changes: 31 additions & 5 deletions generated/constants.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,23 @@
"137": {
"name": "Polygon",
"family": "NONE",
"nativeToken": "MATIC",
"nativeToken": "POL",
"publicRPC": "https://polygon-rpc.com",
"blockExplorer": "https://polygonscan.com",
"cctpDomain": 7,
"oftEid": 30109,
"hypDomainId": 137
},
"143": {
"name": "Monad Mainnet",
"family": "NONE",
"nativeToken": "MON",
"publicRPC": "https://rpc-mainnet.monadinfra.com/",
"blockExplorer": "https://monadscan.com/",
"cctpDomain": 15,
"oftEid": 30390,
"hypDomainId": 143
},
"232": {
"name": "Lens",
"family": "ZK_STACK",
Expand Down Expand Up @@ -230,6 +240,16 @@
"oftEid": -1,
"hypDomainId": -1
},
"10143": {
"name": "Monad Testnet",
"family": "NONE",
"nativeToken": "MON",
"publicRPC": "https://testnet-rpc.monad.xyz/",
"blockExplorer": "https://testnet.monvision.io/",
"cctpDomain": 15,
"oftEid": 40204,
"hypDomainId": 10143
},
"34443": {
"name": "Mode",
"family": "OP_STACK",
Expand Down Expand Up @@ -293,7 +313,7 @@
"80002": {
"name": "Polygon Amoy",
"family": "NONE",
"nativeToken": "MATIC",
"nativeToken": "POL",
"publicRPC": "https://rpc-amoy.polygon.technology",
"blockExplorer": "https://amoy.polygonscan.com",
"cctpDomain": 7,
Expand Down Expand Up @@ -447,6 +467,7 @@
"LISK": 1135,
"MAINNET": 1,
"MODE": 34443,
"MONAD": 143,
"OPTIMISM": 10,
"PLASMA": 9745,
"POLYGON": 137,
Expand All @@ -469,6 +490,7 @@
"LENS_SEPOLIA": 37111,
"LISK_SEPOLIA": 4202,
"MODE_SEPOLIA": 919,
"MONAD_TESTNET": 10143,
"OPTIMISM_SEPOLIA": 11155420,
"PLASMA_TESTNET": 9746,
"POLYGON_AMOY": 80002,
Expand All @@ -479,8 +501,8 @@
"SOLANA_DEVNET": 133268194659241
},
"TESTNET_CHAIN_IDs": [
421614, 84532, 168587773, 808813, 998, 763373, 129399, 37111, 4202, 919, 11155420, 9746, 80002, 534351, 11155111,
1301, 300, 133268194659241
421614, 84532, 168587773, 808813, 998, 763373, 129399, 37111, 4202, 919, 10143, 11155420, 9746, 80002, 534351,
11155111, 1301, 300, 133268194659241
],
"WETH": {
"1": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
Expand Down Expand Up @@ -527,6 +549,7 @@
"56": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
"130": "0x4200000000000000000000000000000000000006",
"137": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270",
"143": "0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A",
"288": "0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000",
"300": "0x2D6Db36B3117802E996f13073A08A685D3FeF7eD",
"324": "0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91",
Expand All @@ -542,6 +565,7 @@
"8453": "0x4200000000000000000000000000000000000006",
"9745": "0x6100E367285b01F48D07953803A2d8dCA5D19873",
"9746": "0x6100E367285b01F48D07953803A2d8dCA5D19873",
"10143": "0x760AfE86e5de5fa0Ee542fc7B7B713e1c5425701",
"34443": "0x4200000000000000000000000000000000000006",
"37111": "0xeee5a340Cdc9c179Db25dea45AcfD5FE8d4d3eB8",
"41455": "0xb7Da55D7040ef9C887e20374D76A88F93A59119E",
Expand Down Expand Up @@ -855,12 +879,14 @@
"10": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
"130": "0x078D782b760474a361dDA0AF3839290b0EF57AD6",
"137": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
"143": "0x754704Bc059F8C67012fEd69BC8A327a5aafb603",
"232": "0x88F08E304EC4f90D644Cec3Fb69b8aD414acf884",
"480": "0x79A02482A880bCE3F13e09Da970dC34db4CD24d1",
"998": "0x2B3370eE501B4a559b57D449569354196457D8Ab",
"999": "0xb88339CB7199b77E23DB6E890353E22632Ba630f",
"1301": "0x31d0220469e10c4E71834a79b1f276d740d3768F",
"8453": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"10143": "0xf817257fed379853cDe0fa4F97AB987181B1E5Ea",
"42161": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
"59144": "0x176211869cA2b568f2A7D4EE941E073a821EE1ff",
"80002": "0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582",
Expand Down Expand Up @@ -890,7 +916,7 @@
"232": "0x6bDc36E20D267Ff0dd6097799f82e78907105e2F"
},
"WMATIC": {
"1": "0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0",
"1": "0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6",
"137": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270",
"80002": "0x360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9",
"11155111": "0x3fd0A53F4Bf853985a95F4Eb3F9C9FDE1F8e2b53"
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"@uma/contracts-node": "^0.4.17",
"axios": "^1.7.4",
"bs58": "^6.0.0",
"hyper-evm-lib": "hyperliquid-dev/hyper-evm-lib",
"prettier-plugin-rust": "^0.1.9",
"yargs": "^17.7.2",
"zksync-web3": "^0.14.3"
Expand Down
4 changes: 4 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10761,6 +10761,10 @@ husky@^4.2.3:
slash "^3.0.0"
which-pm-runs "^1.0.0"

hyper-evm-lib@hyperliquid-dev/hyper-evm-lib:
version "0.0.0"
resolved "https://codeload.github.com/hyperliquid-dev/hyper-evm-lib/tar.gz/ee5e5e8593e9265fca35719e4efaa4fd3092123e"

[email protected]:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
Expand Down
Loading