Skip to content

Commit fffd4a1

Browse files
committed
watcher: add mainnet NTT networks
1 parent 779da05 commit fffd4a1

File tree

4 files changed

+86
-31
lines changed

4 files changed

+86
-31
lines changed

common/src/consts.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,10 @@ export const INITIAL_DEPLOYMENT_BLOCK_BY_NETWORK_AND_CHAIN: {
6969
export const INITIAL_NTT_DEPLOYMENT_BLOCK_BY_NETWORK_AND_CHAIN: {
7070
[key in Network]: { [key in Chain]?: string };
7171
} = {
72-
['Mainnet']: {},
72+
['Mainnet']: {
73+
Ethereum: '19583505',
74+
Fantom: '78727372',
75+
},
7376
['Testnet']: {
7477
Solana: '285100152',
7578
Sepolia: '5472203',

watcher/src/NTTConsts.ts

+41-16
Original file line numberDiff line numberDiff line change
@@ -24,39 +24,41 @@ export const OutboundTransferQueuedTopic =
2424

2525
/// @notice Emitted when an outbound transfer is rate limited.
2626
/// @dev Topic0
27-
/// 0x754d657d1363ee47d967b415652b739bfe96d5729ccf2f26625dcdbc147db68b.
27+
/// 0xf33512b84e24a49905c26c6991942fc5a9652411769fc1e448f967cdb049f08a.
2828
/// @param sender The initial sender of the transfer.
2929
/// @param amount The amount to be transferred.
3030
/// @param currentCapacity The capacity left for transfers within the 24-hour window.:w
31-
/// event OutboundTransferRateLimited( address indexed sender, uint64 sequence, uint256 amount, uint256 currentCapacity);
31+
/// OutboundTransferRateLimited(address,uint64,uint256,uint256)
3232
export const OutboundTransferRateLimitedTopic =
33-
'0x754d657d1363ee47d967b415652b739bfe96d5729ccf2f26625dcdbc147db68b';
33+
'0xf33512b84e24a49905c26c6991942fc5a9652411769fc1e448f967cdb049f08a';
3434

3535
//
3636
// The following are from INttManagerEvents.sol
3737
//
3838

3939
/// @notice Emitted when a message is sent from the nttManager.
4040
/// @dev Topic0
41-
/// 0x9716fe52fe4e02cf924ae28f19f5748ef59877c6496041b986fbad3dae6a8ecf
41+
/// 0x9cc8ade41ef46b98ba8bcad8c6bfa643934e6b84d3ce066cd38b5f0813bb2ae5.
4242
/// @param recipient The recipient of the message.
43+
/// @param refundAddress The address on the destination chain to which the
44+
/// refund of unused gas will be paid
4345
/// @param amount The amount transferred.
4446
/// @param fee The amount of ether sent along with the tx to cover the delivery fee.
4547
/// @param recipientChain The chain ID of the recipient.
4648
/// @param msgSequence The unique sequence ID of the message.
47-
/// event TransferSent( bytes32 recipient, uint256 amount, uint256 fee, uint16 recipientChain, uint64 msgSequence);
4849
export const TransferSentTopic =
49-
'0x9716fe52fe4e02cf924ae28f19f5748ef59877c6496041b986fbad3dae6a8ecf';
50+
'0xe54e51e42099622516fa3b48e9733581c9dbdcb771cafb093f745a0532a35982';
5051

5152
/// @notice Emitted when the peer contract is updated.
5253
/// @dev Topic0
53-
/// 0x51b8437a7e22240c473f4cbdb4ed3a4f4bf5a9e7b3c511d7cfe0197325735700.
54+
/// 0x1456404e7f41f35c3daac941bb50bad417a66275c3040061b4287d787719599d.
5455
/// @param chainId_ The chain ID of the peer contract.
5556
/// @param oldPeerContract The old peer contract address.
57+
/// @param oldPeerDecimals The old peer contract decimals.
5658
/// @param peerContract The new peer contract address.
57-
/// event PeerUpdated(uint16 indexed chainId_, bytes32 oldPeerContract, bytes32 peerContract);
59+
/// @param peerDecimals The new peer contract decimals.
5860
export const PeerUpdatedTopic =
59-
'0x51b8437a7e22240c473f4cbdb4ed3a4f4bf5a9e7b3c511d7cfe0197325735700';
61+
'0x1456404e7f41f35c3daac941bb50bad417a66275c3040061b4287d787719599d';
6062

6163
/// @notice Emitted when a message has been attested to.
6264
/// @dev Topic0
@@ -79,22 +81,22 @@ export const ThresholdChangedTopic =
7981

8082
/// @notice Emitted when an transceiver is removed from the nttManager.
8183
/// @dev Topic0
82-
/// 0xc6289e62021fd0421276d06677862d6b328d9764cdd4490ca5ac78b173f25883.
84+
/// 0xf05962b5774c658e85ed80c91a75af9d66d2af2253dda480f90bce78aff5eda5.
8385
/// @param transceiver The address of the transceiver.
8486
/// @param transceiversNum The current number of transceivers.
8587
/// @param threshold The current threshold of transceivers.
86-
/// event TransceiverAdded(address transceiver, uint256 transceiversNum, uint8 threshold);
88+
/// Event | TransceiverAdded(address,uint256,uint8) | 0xf05962b5774c658e85ed80c91a75af9d66d2af2253dda480f90bce78aff5eda5
8789
export const TransceiverAddedTopic =
88-
'0xc6289e62021fd0421276d06677862d6b328d9764cdd4490ca5ac78b173f25883';
90+
'0xf05962b5774c658e85ed80c91a75af9d66d2af2253dda480f90bce78aff5eda5';
8991

9092
/// @notice Emitted when an transceiver is removed from the nttManager.
9193
/// @dev Topic0
92-
/// 0x638e631f34d9501a3ff0295873b29f50d0207b5400bf0e48b9b34719e6b1a39e.
94+
/// 0x697a3853515b88013ad432f29f53d406debc9509ed6d9313dcfe115250fcd18f.
9395
/// @param transceiver The address of the transceiver.
9496
/// @param threshold The current threshold of transceivers.
95-
/// event TransceiverRemoved(address transceiver, uint8 threshold);
97+
/// Event | TransceiverRemoved(address,uint8) | 0x697a3853515b88013ad432f29f53d406debc9509ed6d9313dcfe115250fcd18f
9698
export const TransceiverRemovedTopic =
97-
'0x638e631f34d9501a3ff0295873b29f50d0207b5400bf0e48b9b34719e6b1a39e';
99+
'0x697a3853515b88013ad432f29f53d406debc9509ed6d9313dcfe115250fcd18f';
98100

99101
/// @notice Emitted when a message has already been executed to
100102
/// notify client of against retries.
@@ -116,6 +118,16 @@ export const MessageAlreadyExecutedTopic =
116118
export const TransferRedeemedTopic =
117119
'0x504e6efe18ab9eed10dc6501a417f5b12a2f7f2b1593aed9b89f9bce3cf29a91';
118120

121+
/// @notice Emitted when an outbound transfer has been cancelled
122+
/// @dev Topic0
123+
/// 0xf80e572ae1b63e2449629b6c7d783add85c36473926f216077f17ee002bcfd07.
124+
/// @param sequence The sequence number being cancelled
125+
/// @param recipient The canceller and recipient of the funds
126+
/// @param amount The amount of the transfer being cancelled
127+
// event OutboundTransferCancelled(uint256 sequence, address recipient, uint256 amount);
128+
export const OutboundTransferCancelledTopic =
129+
'0xf80e572ae1b63e2449629b6c7d783add85c36473926f216077f17ee002bcfd07';
130+
119131
// All topics:
120132
export const NTT_TOPICS = [
121133
InboundTransferQueuedTopic,
@@ -129,6 +141,16 @@ export const NTT_TOPICS = [
129141
TransceiverRemovedTopic,
130142
MessageAlreadyExecutedTopic,
131143
TransferRedeemedTopic,
144+
OutboundTransferCancelledTopic,
145+
];
146+
147+
// Lifecycle topics:
148+
export const NTT_LIFECYCLE_TOPICS = [
149+
InboundTransferQueuedTopic,
150+
OutboundTransferQueuedTopic,
151+
OutboundTransferRateLimitedTopic,
152+
TransferSentTopic,
153+
TransferRedeemedTopic,
132154
];
133155

134156
export const TransferLockIx = 'transferLock';
@@ -156,7 +178,10 @@ export const NTT_SOLANA_IXS = [
156178
export const NTT_CONTRACT: { [key in Network]: { [key in Chain]?: string[] } } = {
157179
['Mainnet']: {
158180
Ethereum: ['0xeBdCe9a913d9400EE75ef31Ce8bd34462D01a1c1'],
159-
Fantom: ['0x68dB2f05Aa2d77DEf981fd2be32661340c9222FB'],
181+
Fantom: [
182+
'0x68dB2f05Aa2d77DEf981fd2be32661340c9222FB',
183+
'0x2F733095B80A04b38b0D10cC884524a3d09b836a',
184+
],
160185
},
161186
['Testnet']: {
162187
Solana: ['nTTh3bZ5Aer6xboWZe39RDEft4MeVxSQ8D1EYAVLZw9'],

watcher/src/watchers/NTTWatcher.ts

+26-11
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
LifeCycle,
1818
NTT_CONTRACT,
1919
NTT_DECIMALS,
20-
NTT_TOPICS,
20+
NTT_LIFECYCLE_TOPICS,
2121
OutboundTransferQueuedTopic,
2222
OutboundTransferRateLimitedTopic,
2323
TransferRedeemedTopic,
@@ -253,7 +253,7 @@ export class NTTWatcher extends Watcher {
253253
for (const nttAddress of nttAddresses) {
254254
// Get and filter logs
255255
const logs: Log[] = (await this.getLogs(fromBlock, toBlock, nttAddress, [])).filter(
256-
isNTTEvent
256+
isNttLifecycleEvent
257257
);
258258
const timestampsByBlock: { [block: number]: string } = {};
259259
// fetch timestamps for each block
@@ -265,7 +265,7 @@ export class NTTWatcher extends Watcher {
265265
}
266266
this.logger.info(`processing ${logs.length} logs`);
267267
for (const log of logs) {
268-
this.logger.debug('log:', log);
268+
this.logger.debug(`log topic: ${log.topics[0]}`);
269269
const blockNumber = log.blockNumber;
270270
const txhash = log.transactionHash;
271271
this.logger.debug(`blockNumber: ${blockNumber}, txhash: ${txhash}`);
@@ -411,6 +411,8 @@ export class NTTWatcher extends Watcher {
411411
lc.digest = digest;
412412
lc.outboundTransferReleasableTime = timestampsByBlock[blockNumber];
413413
await saveToPG(this.pg, lc, OutboundTransferRateLimitedTopic, this.logger);
414+
} else {
415+
this.logger.warn(`Unhandled log topic: ${log.topics[0]}`);
414416
}
415417
}
416418

@@ -426,6 +428,7 @@ export class NTTWatcher extends Watcher {
426428

427429
type decodedTransferSent = {
428430
recipient: string;
431+
refundAddr: string;
429432
amount: string;
430433
fee: string;
431434
recipientChain: number;
@@ -434,24 +437,36 @@ type decodedTransferSent = {
434437

435438
/// event TransferSent( bytes32 recipient, uint256 amount, uint256 fee, uint16 recipientChain, uint64 msgSequence);
436439
function decodeNttTransferSent(data: string): decodedTransferSent {
437-
// There are 5 fields in this message. Each is 32 bytes long (64 characters)
440+
// event TransferSent(
441+
// bytes32 recipient,
442+
// bytes32 refundAddress,
443+
// uint256 amount,
444+
// uint256 fee,
445+
// uint16 recipientChain,
446+
// uint64 msgSequence
447+
// );
448+
// There are 6 fields in this message. All of them are 32 bytes (64 characters in hex)
438449
// If data starts with '0x', we need to remove it
439450
if (data.startsWith('0x')) {
440451
data = data.slice(2);
441452
}
442453
let retVal: decodedTransferSent = {
443454
recipient: '',
455+
refundAddr: '',
444456
amount: '',
445457
fee: '',
446458
recipientChain: 0,
447459
msgSequence: 0,
448460
};
449-
if (data.length === 320) {
461+
if (data.length === 384) {
450462
retVal.recipient = data.slice(0, 64);
451-
retVal.amount = '0x' + data.slice(64, 128);
452-
retVal.fee = '0x' + data.slice(128, 192);
453-
retVal.recipientChain = Number('0x' + data.slice(192, 256));
454-
retVal.msgSequence = Number('0x' + data.slice(256, 320));
463+
retVal.refundAddr = '0x' + data.slice(64, 128);
464+
retVal.amount = '0x' + data.slice(128, 192);
465+
retVal.fee = '0x' + data.slice(192, 256);
466+
retVal.recipientChain = Number('0x' + data.slice(256, 320));
467+
retVal.msgSequence = Number('0x' + data.slice(320, 384));
468+
} else {
469+
throw new Error('Invalid data length. Expected 384 characters. Got ' + data.length);
455470
}
456471
return retVal;
457472
}
@@ -469,8 +484,8 @@ function makeNttTransferKey(mgrAddress: string, recipient: string, seq: number):
469484
export const makeVaaId = (chainId: number, emitter: string, seq: number): string =>
470485
`${chainId}/${emitter}/${seq}`;
471486

472-
function isNTTEvent(log: Log): boolean {
473-
return NTT_TOPICS.some((topic) => log.topics[0].includes(topic));
487+
function isNttLifecycleEvent(log: Log): boolean {
488+
return NTT_LIFECYCLE_TOPICS.some((topic) => log.topics[0].includes(topic));
474489
}
475490

476491
async function saveToPG(pg: Knex, lc: LifeCycle, initiatingEvent: string, logger: WormholeLogger) {

watcher/src/watchers/utils.ts

+15-3
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,17 @@ export function makeFinalizedWatcher(network: Network, chainName: Chain): Watche
8181
}
8282

8383
export function makeFinalizedNTTWatcher(network: Network, chainName: Chain): Watcher {
84-
if (network === 'Testnet') {
84+
if (network === 'Mainnet') {
85+
if (chainName === 'Ethereum') {
86+
return new NTTWatcher(network, chainName, 'finalized');
87+
} else if (chainName === 'Fantom') {
88+
return new NTTWatcher(network, chainName);
89+
} else {
90+
throw new Error(
91+
`Attempted to create finalized NTT watcher for unsupported mainnet chain ${chainName}`
92+
);
93+
}
94+
} else if ('Testnet') {
8595
// These are testnet only chains
8696
if (chainName === 'Sepolia' || chainName === 'Holesky') {
8797
return new NTTWatcher(network, chainName, 'finalized');
@@ -93,10 +103,12 @@ export function makeFinalizedNTTWatcher(network: Network, chainName: Chain): Wat
93103
return new NTTSolanaWatcher(network);
94104
} else {
95105
throw new Error(
96-
`Attempted to create finalized watcher for unsupported testnet chain ${chainName}`
106+
`Attempted to create finalized NTT watcher for unsupported testnet chain ${chainName}`
97107
);
98108
}
99109
} else {
100-
throw new Error(`Attempted to create finalized watcher for unsupported chain ${chainName}`);
110+
throw new Error(
111+
`Attempted to create finalized NTT watcher for unsupported network ${network}, ${chainName}`
112+
);
101113
}
102114
}

0 commit comments

Comments
 (0)