Skip to content

Commit

Permalink
watcher: add mainnet NTT networks
Browse files Browse the repository at this point in the history
  • Loading branch information
panoel committed Apr 10, 2024
1 parent 779da05 commit fffd4a1
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 31 deletions.
5 changes: 4 additions & 1 deletion common/src/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ export const INITIAL_DEPLOYMENT_BLOCK_BY_NETWORK_AND_CHAIN: {
export const INITIAL_NTT_DEPLOYMENT_BLOCK_BY_NETWORK_AND_CHAIN: {
[key in Network]: { [key in Chain]?: string };
} = {
['Mainnet']: {},
['Mainnet']: {
Ethereum: '19583505',
Fantom: '78727372',
},
['Testnet']: {
Solana: '285100152',
Sepolia: '5472203',
Expand Down
57 changes: 41 additions & 16 deletions watcher/src/NTTConsts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,39 +24,41 @@ export const OutboundTransferQueuedTopic =

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

//
// The following are from INttManagerEvents.sol
//

/// @notice Emitted when a message is sent from the nttManager.
/// @dev Topic0
/// 0x9716fe52fe4e02cf924ae28f19f5748ef59877c6496041b986fbad3dae6a8ecf
/// 0x9cc8ade41ef46b98ba8bcad8c6bfa643934e6b84d3ce066cd38b5f0813bb2ae5.
/// @param recipient The recipient of the message.
/// @param refundAddress The address on the destination chain to which the
/// refund of unused gas will be paid
/// @param amount The amount transferred.
/// @param fee The amount of ether sent along with the tx to cover the delivery fee.
/// @param recipientChain The chain ID of the recipient.
/// @param msgSequence The unique sequence ID of the message.
/// event TransferSent( bytes32 recipient, uint256 amount, uint256 fee, uint16 recipientChain, uint64 msgSequence);
export const TransferSentTopic =
'0x9716fe52fe4e02cf924ae28f19f5748ef59877c6496041b986fbad3dae6a8ecf';
'0xe54e51e42099622516fa3b48e9733581c9dbdcb771cafb093f745a0532a35982';

/// @notice Emitted when the peer contract is updated.
/// @dev Topic0
/// 0x51b8437a7e22240c473f4cbdb4ed3a4f4bf5a9e7b3c511d7cfe0197325735700.
/// 0x1456404e7f41f35c3daac941bb50bad417a66275c3040061b4287d787719599d.
/// @param chainId_ The chain ID of the peer contract.
/// @param oldPeerContract The old peer contract address.
/// @param oldPeerDecimals The old peer contract decimals.
/// @param peerContract The new peer contract address.
/// event PeerUpdated(uint16 indexed chainId_, bytes32 oldPeerContract, bytes32 peerContract);
/// @param peerDecimals The new peer contract decimals.
export const PeerUpdatedTopic =
'0x51b8437a7e22240c473f4cbdb4ed3a4f4bf5a9e7b3c511d7cfe0197325735700';
'0x1456404e7f41f35c3daac941bb50bad417a66275c3040061b4287d787719599d';

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

/// @notice Emitted when an transceiver is removed from the nttManager.
/// @dev Topic0
/// 0xc6289e62021fd0421276d06677862d6b328d9764cdd4490ca5ac78b173f25883.
/// 0xf05962b5774c658e85ed80c91a75af9d66d2af2253dda480f90bce78aff5eda5.
/// @param transceiver The address of the transceiver.
/// @param transceiversNum The current number of transceivers.
/// @param threshold The current threshold of transceivers.
/// event TransceiverAdded(address transceiver, uint256 transceiversNum, uint8 threshold);
/// Event | TransceiverAdded(address,uint256,uint8) | 0xf05962b5774c658e85ed80c91a75af9d66d2af2253dda480f90bce78aff5eda5
export const TransceiverAddedTopic =
'0xc6289e62021fd0421276d06677862d6b328d9764cdd4490ca5ac78b173f25883';
'0xf05962b5774c658e85ed80c91a75af9d66d2af2253dda480f90bce78aff5eda5';

/// @notice Emitted when an transceiver is removed from the nttManager.
/// @dev Topic0
/// 0x638e631f34d9501a3ff0295873b29f50d0207b5400bf0e48b9b34719e6b1a39e.
/// 0x697a3853515b88013ad432f29f53d406debc9509ed6d9313dcfe115250fcd18f.
/// @param transceiver The address of the transceiver.
/// @param threshold The current threshold of transceivers.
/// event TransceiverRemoved(address transceiver, uint8 threshold);
/// Event | TransceiverRemoved(address,uint8) | 0x697a3853515b88013ad432f29f53d406debc9509ed6d9313dcfe115250fcd18f
export const TransceiverRemovedTopic =
'0x638e631f34d9501a3ff0295873b29f50d0207b5400bf0e48b9b34719e6b1a39e';
'0x697a3853515b88013ad432f29f53d406debc9509ed6d9313dcfe115250fcd18f';

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

/// @notice Emitted when an outbound transfer has been cancelled
/// @dev Topic0
/// 0xf80e572ae1b63e2449629b6c7d783add85c36473926f216077f17ee002bcfd07.
/// @param sequence The sequence number being cancelled
/// @param recipient The canceller and recipient of the funds
/// @param amount The amount of the transfer being cancelled
// event OutboundTransferCancelled(uint256 sequence, address recipient, uint256 amount);
export const OutboundTransferCancelledTopic =
'0xf80e572ae1b63e2449629b6c7d783add85c36473926f216077f17ee002bcfd07';

// All topics:
export const NTT_TOPICS = [
InboundTransferQueuedTopic,
Expand All @@ -129,6 +141,16 @@ export const NTT_TOPICS = [
TransceiverRemovedTopic,
MessageAlreadyExecutedTopic,
TransferRedeemedTopic,
OutboundTransferCancelledTopic,
];

// Lifecycle topics:
export const NTT_LIFECYCLE_TOPICS = [
InboundTransferQueuedTopic,
OutboundTransferQueuedTopic,
OutboundTransferRateLimitedTopic,
TransferSentTopic,
TransferRedeemedTopic,
];

export const TransferLockIx = 'transferLock';
Expand Down Expand Up @@ -156,7 +178,10 @@ export const NTT_SOLANA_IXS = [
export const NTT_CONTRACT: { [key in Network]: { [key in Chain]?: string[] } } = {
['Mainnet']: {
Ethereum: ['0xeBdCe9a913d9400EE75ef31Ce8bd34462D01a1c1'],
Fantom: ['0x68dB2f05Aa2d77DEf981fd2be32661340c9222FB'],
Fantom: [
'0x68dB2f05Aa2d77DEf981fd2be32661340c9222FB',
'0x2F733095B80A04b38b0D10cC884524a3d09b836a',
],
},
['Testnet']: {
Solana: ['nTTh3bZ5Aer6xboWZe39RDEft4MeVxSQ8D1EYAVLZw9'],
Expand Down
37 changes: 26 additions & 11 deletions watcher/src/watchers/NTTWatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
LifeCycle,
NTT_CONTRACT,
NTT_DECIMALS,
NTT_TOPICS,
NTT_LIFECYCLE_TOPICS,
OutboundTransferQueuedTopic,
OutboundTransferRateLimitedTopic,
TransferRedeemedTopic,
Expand Down Expand Up @@ -253,7 +253,7 @@ export class NTTWatcher extends Watcher {
for (const nttAddress of nttAddresses) {
// Get and filter logs
const logs: Log[] = (await this.getLogs(fromBlock, toBlock, nttAddress, [])).filter(
isNTTEvent
isNttLifecycleEvent
);
const timestampsByBlock: { [block: number]: string } = {};
// fetch timestamps for each block
Expand All @@ -265,7 +265,7 @@ export class NTTWatcher extends Watcher {
}
this.logger.info(`processing ${logs.length} logs`);
for (const log of logs) {
this.logger.debug('log:', log);
this.logger.debug(`log topic: ${log.topics[0]}`);
const blockNumber = log.blockNumber;
const txhash = log.transactionHash;
this.logger.debug(`blockNumber: ${blockNumber}, txhash: ${txhash}`);
Expand Down Expand Up @@ -411,6 +411,8 @@ export class NTTWatcher extends Watcher {
lc.digest = digest;
lc.outboundTransferReleasableTime = timestampsByBlock[blockNumber];
await saveToPG(this.pg, lc, OutboundTransferRateLimitedTopic, this.logger);
} else {
this.logger.warn(`Unhandled log topic: ${log.topics[0]}`);
}
}

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

type decodedTransferSent = {
recipient: string;
refundAddr: string;
amount: string;
fee: string;
recipientChain: number;
Expand All @@ -434,24 +437,36 @@ type decodedTransferSent = {

/// event TransferSent( bytes32 recipient, uint256 amount, uint256 fee, uint16 recipientChain, uint64 msgSequence);
function decodeNttTransferSent(data: string): decodedTransferSent {
// There are 5 fields in this message. Each is 32 bytes long (64 characters)
// event TransferSent(
// bytes32 recipient,
// bytes32 refundAddress,
// uint256 amount,
// uint256 fee,
// uint16 recipientChain,
// uint64 msgSequence
// );
// There are 6 fields in this message. All of them are 32 bytes (64 characters in hex)
// If data starts with '0x', we need to remove it
if (data.startsWith('0x')) {
data = data.slice(2);
}
let retVal: decodedTransferSent = {
recipient: '',
refundAddr: '',
amount: '',
fee: '',
recipientChain: 0,
msgSequence: 0,
};
if (data.length === 320) {
if (data.length === 384) {
retVal.recipient = data.slice(0, 64);
retVal.amount = '0x' + data.slice(64, 128);
retVal.fee = '0x' + data.slice(128, 192);
retVal.recipientChain = Number('0x' + data.slice(192, 256));
retVal.msgSequence = Number('0x' + data.slice(256, 320));
retVal.refundAddr = '0x' + data.slice(64, 128);
retVal.amount = '0x' + data.slice(128, 192);
retVal.fee = '0x' + data.slice(192, 256);
retVal.recipientChain = Number('0x' + data.slice(256, 320));
retVal.msgSequence = Number('0x' + data.slice(320, 384));
} else {
throw new Error('Invalid data length. Expected 384 characters. Got ' + data.length);
}
return retVal;
}
Expand All @@ -469,8 +484,8 @@ function makeNttTransferKey(mgrAddress: string, recipient: string, seq: number):
export const makeVaaId = (chainId: number, emitter: string, seq: number): string =>
`${chainId}/${emitter}/${seq}`;

function isNTTEvent(log: Log): boolean {
return NTT_TOPICS.some((topic) => log.topics[0].includes(topic));
function isNttLifecycleEvent(log: Log): boolean {
return NTT_LIFECYCLE_TOPICS.some((topic) => log.topics[0].includes(topic));
}

async function saveToPG(pg: Knex, lc: LifeCycle, initiatingEvent: string, logger: WormholeLogger) {
Expand Down
18 changes: 15 additions & 3 deletions watcher/src/watchers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,17 @@ export function makeFinalizedWatcher(network: Network, chainName: Chain): Watche
}

export function makeFinalizedNTTWatcher(network: Network, chainName: Chain): Watcher {
if (network === 'Testnet') {
if (network === 'Mainnet') {
if (chainName === 'Ethereum') {
return new NTTWatcher(network, chainName, 'finalized');
} else if (chainName === 'Fantom') {
return new NTTWatcher(network, chainName);
} else {
throw new Error(
`Attempted to create finalized NTT watcher for unsupported mainnet chain ${chainName}`
);
}
} else if ('Testnet') {
// These are testnet only chains
if (chainName === 'Sepolia' || chainName === 'Holesky') {
return new NTTWatcher(network, chainName, 'finalized');
Expand All @@ -93,10 +103,12 @@ export function makeFinalizedNTTWatcher(network: Network, chainName: Chain): Wat
return new NTTSolanaWatcher(network);
} else {
throw new Error(
`Attempted to create finalized watcher for unsupported testnet chain ${chainName}`
`Attempted to create finalized NTT watcher for unsupported testnet chain ${chainName}`
);
}
} else {
throw new Error(`Attempted to create finalized watcher for unsupported chain ${chainName}`);
throw new Error(
`Attempted to create finalized NTT watcher for unsupported network ${network}, ${chainName}`
);
}
}

0 comments on commit fffd4a1

Please sign in to comment.