Skip to content

Commit 239620c

Browse files
committed
fix(rebalancer): tighten LiFi chain metadata lookups
1 parent 8831edd commit 239620c

2 files changed

Lines changed: 83 additions & 9 deletions

File tree

typescript/rebalancer/src/bridges/LiFiBridge.test.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,28 @@ const DUPLICATE_CHAIN_ID_CONFIG: ExternalBridgeConfig = {
6464
},
6565
};
6666

67+
const NON_EVM_DOMAIN_COLLISION_CONFIG: ExternalBridgeConfig = {
68+
integrator: 'test-rebalancer',
69+
chainMetadata: {
70+
ethereum: {
71+
chainId: 1,
72+
protocol: ProtocolType.Ethereum,
73+
name: 'ethereum',
74+
displayName: 'Ethereum',
75+
domainId: 1,
76+
rpcUrls: [{ http: 'https://ethereum-rpc.local' }],
77+
},
78+
cosmos: {
79+
chainId: 999999999,
80+
protocol: ProtocolType.Cosmos,
81+
name: 'cosmos',
82+
displayName: 'Cosmos',
83+
domainId: 1,
84+
rpcUrls: [{ http: 'https://rpc.cosmos.invalid' }],
85+
},
86+
},
87+
};
88+
6789
// Use all-digit hex addresses to avoid EIP-55 checksum case mutations
6890
const TOKEN_ADDR = '0x1234567890123456789012345678901234567890';
6991
const SENDER_ADDR = '0x9876543210987654321098765432109876543210';
@@ -711,6 +733,44 @@ describe('LiFiBridge constructor chainMetadataByChainId', function () {
711733
expect(msg.toLowerCase()).to.include('private key');
712734
});
713735
});
736+
737+
it('should index Tron by chainId even when domainId differs', () => {
738+
const TRON_CHAIN_ID = 728126428;
739+
const bridge = new LiFiBridge(
740+
{
741+
integrator: 'test-rebalancer',
742+
chainMetadata: {
743+
tron: {
744+
chainId: TRON_CHAIN_ID,
745+
protocol: ProtocolType.Tron,
746+
name: 'tron',
747+
displayName: 'Tron',
748+
domainId: 999000999,
749+
rpcUrls: [{ http: 'https://api.trongrid.io/jsonrpc' }],
750+
},
751+
},
752+
},
753+
testLogger,
754+
);
755+
const getProtocolTypeForChainId = (
756+
bridge as any
757+
).getProtocolTypeForChainId.bind(bridge);
758+
759+
expect(getProtocolTypeForChainId(TRON_CHAIN_ID)).to.equal(
760+
ProtocolType.Tron,
761+
);
762+
expect(getProtocolTypeForChainId(999000999)).to.equal(undefined);
763+
});
764+
765+
it('should not let non-EVM domainIds overwrite EVM chainId lookups', () => {
766+
const bridge = new LiFiBridge(NON_EVM_DOMAIN_COLLISION_CONFIG, testLogger);
767+
const getProtocolTypeForChainId = (
768+
bridge as any
769+
).getProtocolTypeForChainId.bind(bridge);
770+
771+
expect(getProtocolTypeForChainId(1)).to.equal(ProtocolType.Ethereum);
772+
expect(getProtocolTypeForChainId(999999999)).to.equal(ProtocolType.Cosmos);
773+
});
714774
});
715775

716776
describe('LiFiBridge source protocol handling', function () {

typescript/rebalancer/src/bridges/LiFiBridge.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ import {
1414
} from '@lifi/sdk';
1515
import bs58 from 'bs58';
1616
import type { ChainMetadata } from '@hyperlane-xyz/sdk';
17-
import { ProtocolType, assert, ensure0x } from '@hyperlane-xyz/utils';
17+
import {
18+
ProtocolType,
19+
assert,
20+
ensure0x,
21+
isEVMLike,
22+
} from '@hyperlane-xyz/utils';
1823
import type { Logger } from 'pino';
1924
import { type Chain, createWalletClient, http } from 'viem';
2025
import { privateKeyToAccount } from 'viem/accounts';
@@ -142,12 +147,8 @@ export class LiFiBridge implements IExternalBridge {
142147
const metadataByDomainId = new Map<number, ChainMetadata>();
143148
for (const metadata of Object.values(config.chainMetadata)) {
144149
metadataByDomainId.set(metadata.domainId, metadata);
145-
if (metadata.chainId !== undefined) {
146-
if (metadata.protocol === ProtocolType.Ethereum) {
147-
this.chainMetadataByChainId.set(Number(metadata.chainId), metadata);
148-
} else {
149-
this.chainMetadataByChainId.set(metadata.domainId, metadata);
150-
}
150+
if (metadata.chainId !== undefined && isEVMLike(metadata.protocol)) {
151+
this.chainMetadataByChainId.set(Number(metadata.chainId), metadata);
151152
}
152153
}
153154
// Also key by LiFi chain IDs so both Hyperlane domains and LiFi IDs
@@ -187,11 +188,24 @@ export class LiFiBridge implements IExternalBridge {
187188
* Iterates metadata to find matching chainId and returns first HTTP RPC URL.
188189
*/
189190
private getRpcUrlForChainId(chainId: number): string | undefined {
190-
return this.chainMetadataByChainId.get(chainId)?.rpcUrls?.[0]?.http;
191+
return this.getMetadataForChainId(chainId)?.rpcUrls?.[0]?.http;
191192
}
192193

193194
private getProtocolTypeForChainId(chainId: number): ProtocolType | undefined {
194-
return this.chainMetadataByChainId.get(chainId)?.protocol;
195+
return this.getMetadataForChainId(chainId)?.protocol;
196+
}
197+
198+
private getMetadataForChainId(chainId: number): ChainMetadata | undefined {
199+
const directMetadata = this.chainMetadataByChainId.get(chainId);
200+
if (directMetadata) {
201+
return directMetadata;
202+
}
203+
204+
const matches = Object.values(this.config.chainMetadata ?? {}).filter(
205+
(metadata) =>
206+
metadata.chainId !== undefined && Number(metadata.chainId) === chainId,
207+
);
208+
return matches.length === 1 ? matches[0] : undefined;
195209
}
196210

197211
private addressesEqual(a: string, b: string, chainId: number): boolean {

0 commit comments

Comments
 (0)