Skip to content

Commit f7953fe

Browse files
committed
feat: track hyperbridge evm activity
1 parent 7a6f88a commit f7953fe

File tree

3 files changed

+198
-0
lines changed

3 files changed

+198
-0
lines changed

src/adapters/hyperbridge/index.ts

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
import { BridgeAdapter, PartialContractEventParams } from "../../helpers/bridgeAdapter.type";
2+
import { getTxDataFromEVMEventLogs } from "../../helpers/processTransactions";
3+
import { Chain } from "@defillama/sdk/build/general";
4+
import { EventData } from "../../utils/types";
5+
import { getProvider } from "@defillama/sdk";
6+
import { ethers } from "ethers";
7+
8+
const intentGateway = "0x1a4ee689a004b10210a1df9f24a387ea13359acf";
9+
const tokenGateway = "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE";
10+
11+
export const intentGatewayAddresses = {
12+
ethereum: intentGateway,
13+
arbitrum: intentGateway,
14+
base: intentGateway,
15+
bsc: intentGateway,
16+
polygon: intentGateway,
17+
} as const;
18+
19+
export const tokenGatewayAddresses = {
20+
ethereum: tokenGateway,
21+
arbitrum: tokenGateway,
22+
base: tokenGateway,
23+
bsc: tokenGateway,
24+
polygon: tokenGateway,
25+
} as const;
26+
27+
type SupportedChains = keyof typeof intentGatewayAddresses;
28+
29+
const TRANSFER_TOPIC = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
30+
31+
const constructParams = (chain: SupportedChains) => {
32+
const igGateway = intentGatewayAddresses[chain];
33+
const tgGateway = tokenGatewayAddresses[chain];
34+
35+
return async (fromBlock: number, toBlock: number) => {
36+
// ========== Intent Gateway Events (need custom filtering) ==========
37+
const escrowReleasedParams: PartialContractEventParams = {
38+
target: igGateway,
39+
topic: "EscrowReleased(bytes32)",
40+
abi: ["event EscrowReleased(bytes32 indexed commitment)"],
41+
logKeys: {
42+
blockNumber: "blockNumber",
43+
txHash: "transactionHash",
44+
},
45+
isDeposit: true,
46+
};
47+
48+
const orderFilledParams: PartialContractEventParams = {
49+
target: igGateway,
50+
topic: "OrderFilled(bytes32,address)",
51+
abi: ["event OrderFilled(bytes32 indexed commitment, address filler)"],
52+
logKeys: {
53+
blockNumber: "blockNumber",
54+
txHash: "transactionHash",
55+
},
56+
isDeposit: false,
57+
};
58+
59+
// ========== Token Gateway Events (can use getTokenFromReceipt) ==========
60+
const assetTeleportedParams: PartialContractEventParams = {
61+
target: tgGateway,
62+
topic: "AssetTeleported(bytes32,string,uint256,bytes32,address,bytes32,bool)",
63+
abi: [
64+
"event AssetTeleported(bytes32 to, string dest, uint256 amount, bytes32 commitment, address indexed from, bytes32 indexed assetId, bool redeem)",
65+
],
66+
logKeys: {
67+
blockNumber: "blockNumber",
68+
txHash: "transactionHash",
69+
},
70+
argKeys: {
71+
from: "from",
72+
},
73+
getTokenFromReceipt: {
74+
token: true,
75+
amount: true,
76+
},
77+
fixedEventData: {
78+
to: tgGateway,
79+
},
80+
isDeposit: true,
81+
};
82+
83+
const assetReceivedParams: PartialContractEventParams = {
84+
target: tgGateway,
85+
topic: "AssetReceived(uint256,bytes32,bytes32,address,bytes32)",
86+
abi: [
87+
"event AssetReceived(uint256 amount, bytes32 commitment, bytes32 indexed from, address indexed beneficiary, bytes32 indexed assetId)",
88+
],
89+
logKeys: {
90+
blockNumber: "blockNumber",
91+
txHash: "transactionHash",
92+
},
93+
argKeys: {
94+
to: "beneficiary",
95+
},
96+
getTokenFromReceipt: {
97+
token: true,
98+
amount: true,
99+
},
100+
fixedEventData: {
101+
from: tgGateway,
102+
},
103+
isDeposit: false,
104+
};
105+
106+
const intentGatewayParams = [escrowReleasedParams, orderFilledParams];
107+
const intentGatewayEvents = await getTxDataFromEVMEventLogs(
108+
"hyperbridge",
109+
chain as Chain,
110+
fromBlock,
111+
toBlock,
112+
intentGatewayParams
113+
);
114+
115+
const tokenGatewayParams = [assetTeleportedParams, assetReceivedParams];
116+
const tokenGatewayEvents = await getTxDataFromEVMEventLogs(
117+
"hyperbridge",
118+
chain as Chain,
119+
fromBlock,
120+
toBlock,
121+
tokenGatewayParams
122+
);
123+
124+
// Process Intent Gateway events with custom filtering
125+
const processedIntentGatewayEvents: EventData[] = [];
126+
127+
for (const event of intentGatewayEvents) {
128+
try {
129+
const provider = getProvider(chain as Chain);
130+
const txReceipt = await provider.getTransactionReceipt(event.txHash);
131+
if (!txReceipt?.logs) continue;
132+
133+
for (const log of txReceipt.logs) {
134+
if (log.topics && log.topics[0] === TRANSFER_TOPIC && log.topics.length === 3) {
135+
const from = "0x" + log.topics[1].slice(26);
136+
const to = "0x" + log.topics[2].slice(26);
137+
const token = log.address;
138+
const amount = ethers.BigNumber.from(log.data);
139+
140+
if (event.isDeposit) {
141+
// EscrowReleased: only transfers FROM gateway (escrow release to filler)
142+
if (from.toLowerCase() === igGateway.toLowerCase()) {
143+
processedIntentGatewayEvents.push({
144+
txHash: event.txHash,
145+
blockNumber: event.blockNumber,
146+
from: from,
147+
to: to,
148+
token: token,
149+
amount: amount,
150+
isDeposit: true,
151+
});
152+
}
153+
} else {
154+
// OrderFilled: transfers NOT involving gateway (filler → user)
155+
if (from.toLowerCase() !== igGateway.toLowerCase() && to.toLowerCase() !== igGateway.toLowerCase()) {
156+
processedIntentGatewayEvents.push({
157+
txHash: event.txHash,
158+
blockNumber: event.blockNumber,
159+
from: from,
160+
to: to,
161+
token: token,
162+
amount: amount,
163+
isDeposit: false,
164+
});
165+
}
166+
}
167+
}
168+
}
169+
} catch (e) {
170+
console.error(`Error processing Intent Gateway transaction ${event.txHash}:`, e);
171+
}
172+
}
173+
174+
return [...processedIntentGatewayEvents, ...tokenGatewayEvents];
175+
};
176+
};
177+
178+
const adapter: BridgeAdapter = {
179+
ethereum: constructParams("ethereum"),
180+
arbitrum: constructParams("arbitrum"),
181+
base: constructParams("base"),
182+
bsc: constructParams("bsc"),
183+
polygon: constructParams("polygon"),
184+
};
185+
186+
export default adapter;

src/adapters/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ import pheasantNetwork from "./pheasant-network";
9696
import teleswap from "./teleswap";
9797
import agglayer from "./agglayer";
9898
import fxrp from "./flare/fxrp";
99+
import hyperbridge from "./hyperbridge";
99100

100101
export default {
101102
polygon,
@@ -195,6 +196,7 @@ export default {
195196
teleswap,
196197
agglayer,
197198
fxrp,
199+
hyperbridge,
198200
} as {
199201
[bridge: string]: BridgeAdapter | AsyncBridgeAdapter;
200202
};

src/data/bridgeNetworkData.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2583,4 +2583,14 @@ export default [
25832583
chains: ["Flare", "XRPL"],
25842584
destinationChain: "XRPL",
25852585
},
2586+
2587+
{
2588+
id: 101,
2589+
displayName: "Hyperbridge",
2590+
bridgeDbName: "hyperbridge",
2591+
iconLink: "icons:hyperbridge",
2592+
largeTxThreshold: 10000,
2593+
url: "https://hyperbridge.network",
2594+
chains: ["Ethereum", "Arbitrum", "Base", "BSC", "Polygon", "Optimism", "Soneium"],
2595+
},
25862596
] as BridgeNetwork[];

0 commit comments

Comments
 (0)