Skip to content

Commit a60f238

Browse files
committed
feat(adapters): add Hyperlane
1 parent da34551 commit a60f238

File tree

3 files changed

+258
-0
lines changed

3 files changed

+258
-0
lines changed

src/adapters/hyperlane/index.ts

+216
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
import { BridgeAdapter, PartialContractEventParams } from "../../helpers/bridgeAdapter.type";
2+
import { Chain } from "@defillama/sdk/build/general";
3+
import { getTxDataFromEVMEventLogs } from "../../helpers/processTransactions";
4+
import { BigNumber } from "ethers";
5+
6+
type ChainToAddress = { [chain: string]: string };
7+
8+
/* Addresses Source: https://github.com/hyperlane-xyz/hyperlane-registry */
9+
// TODO: Automate intake from @hyperlane-xyz/registry (will need new APIs exposed)
10+
11+
/* Mailbox Contract: https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/Mailbox.sol */
12+
const MAILBOXES: ChainToAddress = {
13+
ancient8: '0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7',
14+
arbitrum: '0x979Ca5202784112f4738403dBec5D0F3B9daabB9',
15+
avalanche: '0xFf06aFcaABaDDd1fb08371f9ccA15D73D51FeBD6',
16+
base: '0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D',
17+
blast: '0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7',
18+
bsc: '0x2971b9Aec44bE4eb673DF1B88cDB57b96eefe8a4',
19+
celo: '0x50da3B3907A08a24fe4999F4Dcf337E8dC7954bb',
20+
ethereum: '0xc005dc82818d67AF737725bD4bf75435d065D239',
21+
fraxtal: '0x2f9DB5616fa3fAd1aB06cB2C906830BA63d135e3',
22+
gnosis: '0xaD09d78f4c6b9dA2Ae82b1D34107802d380Bb74f',
23+
holesky: '0x46f7C5D896bbeC89bE1B19e4485e59b4Be49e9Cc',
24+
inevm: '0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7',
25+
linea: '0x02d16BC51af6BfD153d67CA61754cF912E82C4d9',
26+
mantapacific: '0x3a464f746D23Ab22155710f44dB16dcA53e0775E',
27+
mode: '0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7',
28+
moonbeam: '0x094d03E751f49908080EFf000Dd6FD177fd44CC3',
29+
optimism: '0xd4C1905BB1D26BC93DAC913e13CaCC278CdCC80D',
30+
polygon: '0x5d934f4e2f797775e53561bB72aca21ba36B96BB',
31+
polygonzkevm: '0x3a464f746D23Ab22155710f44dB16dcA53e0775E',
32+
redstone: '0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D',
33+
scroll: '0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7',
34+
sei: '0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7',
35+
viction: '0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7',
36+
zetachain: '0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7',
37+
};
38+
39+
const ECLIP_TOKENS: ChainToAddress = {
40+
neutron: "neutron1dvzvf870mx9uf65uqhx40yzx9gu4xlqqq2pnx362a0ndmustww3smumrf5", // 2+
41+
arbitrum: "0x93ca0d85837FF83158Cd14D65B169CdB223b1921",
42+
};
43+
44+
const ETH_TOKENS: ChainToAddress = {
45+
ethereum: "0x15b5D6B614242B118AA404528A7f3E2Ad241e4A4",
46+
viction: "0x182e8d7c5f1b06201b102123fc7df0eaeb445a7b",
47+
}
48+
49+
/* HypXERC20 Contract: https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/token/extensions/HypXERC20.sol */
50+
/* HypXERC20Lockbox Contract: https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/token/extensions/HypXERC20Lockbox.sol */
51+
const ezETH_TOKENS: ChainToAddress = {
52+
bsc: "0x6266e803057fa68C35018C3FB0B59db7129C23BB",
53+
arbitrum: "0xC8F280d3eC30746f77c28695827d309d16939BF1",
54+
optimism: "0x1d1a210E71398c17FD7987eDF1dc347539bB541F",
55+
base: "0x584BA77ec804f8B6A559D196661C0242C6844F49",
56+
blast: "0x8C603c6BDf8a9d548fC5D2995750Cc25eF59183b",
57+
mode: "0xcd95B8dF351400BF4cbAb340b6EfF2454aDB299E",
58+
linea: "0xcd95B8dF351400BF4cbAb340b6EfF2454aDB299E",
59+
ethereum: "0xdFf621F952c23972dFD3A9E5d7B9f6339e9c078B",
60+
};
61+
62+
const INJ_TOKENS: ChainToAddress = {
63+
injective: "inj1mv9tjvkaw7x8w8y9vds8pkfq46g2vcfkjehc6k",
64+
inevm: "0x26f32245fCF5Ad53159E875d5Cae62aEcf19c2d4",
65+
};
66+
67+
const milkTIA_TOKENS: ChainToAddress = {
68+
osmosis: "osmo17xuecsykqw2xcxwv8cau7uy4hgdwqt0u4qxflyc2yshhggpazfjs6kfqd3",
69+
mantapacific: "0x32474653127048d9fC20000e21dEd396b47968E8",
70+
};
71+
72+
const nTIA_ARBITRUM_TOKENS: ChainToAddress = {
73+
neutron: "neutron1jyyjd3x0jhgswgm6nnctxvzla8ypx50tew3ayxxwkrjfxhvje6kqzvzudq", // 2+
74+
arbitrum: "0xD56734d7f9979dD94FAE3d67C7e928234e71cD4C",
75+
};
76+
77+
const oTIA_MANTA_TOKENS: ChainToAddress = {
78+
osmosis: "osmo1h4y9xjcvs8lrx4z8ha48uq9a338w74dpl2ly3tf74fzvugp2kj4q9l0jkw",
79+
mantapacific: "0x88410F3D8135b4D23b98dC37C4652C6969a5B1a8",
80+
};
81+
82+
const nTIA_MANTA_PACIFIC_TOKENS: ChainToAddress = {
83+
neutron: "neutron1ch7x3xgpnj62weyes8vfada35zff6z59kt2psqhnx9gjnt2ttqdqtva3pa", // 2+
84+
mantapacific: "0x6Fae4D9935E2fcb11fC79a64e917fb2BF14DaFaa",
85+
};
86+
87+
const ETH_ANCIENT8_TOKENS: ChainToAddress = {
88+
ethereum: "0x8b4192B9Ad1fCa440A5808641261e5289e6de95D",
89+
ancient8: "0x97423A68BAe94b5De52d767a17aBCc54c157c0E5",
90+
};
91+
92+
const ETH_INEVM_TOKENS: ChainToAddress = {
93+
ethereum: "0xED56728fb977b0bBdacf65bCdD5e17Bb7e84504f",
94+
inevm: "0x8358d8291e3bedb04804975eea0fe9fe0fafb147",
95+
};
96+
97+
const ETH_VICTION_TOKENS: ChainToAddress = {
98+
ethereum: "0x31Dca7762930f56D81292f85E65c9D67575804fE",
99+
viction: "0xbda330ea8f3005c421c8088e638fbb64fa71b9e0",
100+
};
101+
102+
const HYPERLANE_TOKENS_SET: ChainToAddress[] = [
103+
ECLIP_TOKENS,
104+
ETH_TOKENS,
105+
ezETH_TOKENS,
106+
INJ_TOKENS,
107+
milkTIA_TOKENS,
108+
nTIA_ARBITRUM_TOKENS,
109+
oTIA_MANTA_TOKENS,
110+
nTIA_MANTA_PACIFIC_TOKENS,
111+
ETH_ANCIENT8_TOKENS,
112+
ETH_INEVM_TOKENS,
113+
ETH_VICTION_TOKENS,
114+
];
115+
116+
/* NOTE: Can't pull– hyperlane-registry out-of-date. */
117+
const HYPERLANE_CORE_CHAINS = Object.keys({
118+
...MAILBOXES,
119+
...ECLIP_TOKENS,
120+
...ETH_TOKENS,
121+
...ezETH_TOKENS,
122+
...INJ_TOKENS,
123+
...milkTIA_TOKENS,
124+
...nTIA_ARBITRUM_TOKENS,
125+
...oTIA_MANTA_TOKENS,
126+
...nTIA_MANTA_PACIFIC_TOKENS,
127+
...ETH_ANCIENT8_TOKENS,
128+
...ETH_INEVM_TOKENS,
129+
...ETH_VICTION_TOKENS,
130+
});
131+
132+
const getMailboxParams = (
133+
mailboxAddress: string,
134+
token: string,
135+
): PartialContractEventParams[] => {
136+
const mailboxDispatchParams: PartialContractEventParams = {
137+
target: mailboxAddress,
138+
topic: "Dispatch(address,uint32,bytes32,bytes)",
139+
abi: [
140+
"event Dispatch(address indexed sender, uint32 indexed destination, bytes32 indexed recipient, bytes message)"
141+
],
142+
logKeys: {
143+
blockNumber: "blockNumber",
144+
txHash: "transactionHash",
145+
},
146+
argKeys: {
147+
from: "sender",
148+
to: "recipient",
149+
amount: "message",
150+
},
151+
argGetters: {
152+
amount: (log: any) => BigNumber.from(log.message),
153+
},
154+
fixedEventData: {
155+
token,
156+
},
157+
isDeposit: true,
158+
// inputDataExtraction: {
159+
// inputDataABI: [
160+
// "function dispatch(uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody)"
161+
// ],
162+
// inputDataFnName: "dispatch",
163+
// inputDataKeys: {
164+
// amount: "messageBody",
165+
// },
166+
// useDefaultAbiEncoder: true,
167+
// },
168+
};
169+
170+
const mailboxProcessParams: PartialContractEventParams = {
171+
target: mailboxAddress,
172+
topic: "Process(uint32,bytes32,address)",
173+
abi: [
174+
"event Process(uint32 indexed origin, bytes32 indexed sender, address indexed recipient)"
175+
],
176+
logKeys: {
177+
blockNumber: "blockNumber",
178+
txHash: "transactionHash",
179+
},
180+
argKeys: {
181+
from: "sender",
182+
to: "recipient",
183+
},
184+
isDeposit: false,
185+
};
186+
return [mailboxDispatchParams, mailboxProcessParams];
187+
};
188+
189+
const constructParams = (chain: string) => {
190+
let eventParams: PartialContractEventParams[] = [];
191+
192+
const mailbox: string = MAILBOXES[chain];
193+
194+
if (mailbox) {
195+
for (const hyperlaneTokens of HYPERLANE_TOKENS_SET) {
196+
const hyperlaneToken: string = hyperlaneTokens[chain];
197+
if (hyperlaneToken) eventParams.push(...getMailboxParams(mailbox, hyperlaneToken));
198+
}
199+
}
200+
201+
return async (fromBlock: number, toBlock: number) =>
202+
getTxDataFromEVMEventLogs(
203+
"hyperlane",
204+
chain as Chain,
205+
fromBlock,
206+
toBlock,
207+
eventParams
208+
);
209+
};
210+
211+
const adapter: BridgeAdapter = HYPERLANE_CORE_CHAINS.reduce((bridgeAdapter, chain) => {
212+
bridgeAdapter[chain] = constructParams(chain);
213+
return bridgeAdapter;
214+
}, {} as BridgeAdapter);
215+
216+
export default adapter;

src/adapters/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import xswap from "./xswap";
6060
import owlto from "./owlto";
6161
import zkbridge from "./zkbridge";
6262
import helixbridge from "./helixbridge"
63+
import hyperlane from "./hyperlane";
6364

6465
export default {
6566
polygon,
@@ -123,6 +124,7 @@ export default {
123124
zkbridge,
124125
zkbridge111: zkbridge,
125126
helixbridge,
127+
hyperlane,
126128
} as {
127129
[bridge: string]: BridgeAdapter;
128130
};

src/data/bridgeNetworkData.ts

+40
Original file line numberDiff line numberDiff line change
@@ -1280,4 +1280,44 @@ export default [
12801280
gnosis: "xdai",
12811281
},
12821282
},
1283+
{
1284+
id: 65,
1285+
displayName: "Hyperlane",
1286+
bridgeDbName: "hyperlane",
1287+
iconLink: "icons:hyperlane",
1288+
largeTxThreshold: 10000,
1289+
url: "https://hyperlane.xyz/",
1290+
chains: [
1291+
"Ancient8",
1292+
"Arbitrum",
1293+
"Avalanche",
1294+
"Base",
1295+
"Blast",
1296+
"Bsc",
1297+
"Celo",
1298+
"Ethereum",
1299+
"Fraxtal",
1300+
"Gnosis",
1301+
"Holesky",
1302+
"Inevm",
1303+
"Linea",
1304+
"Mantapacific",
1305+
"Mode",
1306+
"Moonbeam",
1307+
"Optimism",
1308+
"Polygon",
1309+
"Polygonzkevm",
1310+
"Redstone",
1311+
"Scroll",
1312+
"Sei",
1313+
"Viction",
1314+
"Zetachain",
1315+
"Neutron",
1316+
"Injective",
1317+
"Osmosis",
1318+
],
1319+
chainMapping: {
1320+
avalanche: "avax",
1321+
},
1322+
},
12831323
] as BridgeNetwork[];

0 commit comments

Comments
 (0)