From 346fa1e732d9fac3c393b09a6477f9dc19cd2fe7 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Wed, 6 Nov 2019 16:49:01 -0300 Subject: [PATCH] Support token migration (#224) * Filter transfer event in token swap in Oracle * Support token swap in monitor --- commons/constants.js | 5 ++- contracts | 2 +- monitor/utils/events.js | 46 +++++++++++++++++++-- oracle/src/events/processTransfers/index.js | 16 ++++++- 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/commons/constants.js b/commons/constants.js index 53c86b68..fe2304b5 100644 --- a/commons/constants.js +++ b/commons/constants.js @@ -17,8 +17,11 @@ const FEE_MANAGER_MODE = { UNDEFINED: 'UNDEFINED' } +const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' + module.exports = { BRIDGE_MODES, ERC_TYPES, - FEE_MANAGER_MODE + FEE_MANAGER_MODE, + ZERO_ADDRESS } diff --git a/contracts b/contracts index 39910b77..cc771828 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 39910b771b1a93a10db829a0b3dddd074c9e1b4e +Subproject commit cc7718284d8a35cf74f6ec6847fd7dc7ed1ca885 diff --git a/monitor/utils/events.js b/monitor/utils/events.js index 7ea4eef1..d71454ea 100644 --- a/monitor/utils/events.js +++ b/monitor/utils/events.js @@ -11,7 +11,8 @@ const { ERC20_ABI, ERC677_BRIDGE_TOKEN_ABI, getTokenType, - getPastEvents + getPastEvents, + ZERO_ADDRESS } = require('../../commons') const { normalizeEventInformation } = require('./message') @@ -87,7 +88,7 @@ async function main(mode) { })).map(normalizeEvent) if (isExternalErc20) { logger.debug("calling erc20Contract.getPastEvents('Transfer')") - const transferEvents = (await getPastEvents(erc20Contract, { + let transferEvents = (await getPastEvents(erc20Contract, { event: 'Transfer', fromBlock: MONITOR_FOREIGN_START_BLOCK, toBlock: foreignBlockNumber, @@ -96,8 +97,47 @@ async function main(mode) { } })).map(normalizeEvent) + let directTransfers = transferEvents + const tokensSwappedAbiExists = FOREIGN_ABI.filter(e => e.type === 'event' && e.name === 'TokensSwapped')[0] + if (tokensSwappedAbiExists) { + const tokensSwappedEvents = await getPastEvents(foreignBridge, { + event: 'TokensSwapped', + fromBlock: MONITOR_FOREIGN_START_BLOCK, + toBlock: foreignBlockNumber + }) + + // Get token swap events emitted by foreign bridge + const bridgeTokensSwappedEvents = tokensSwappedEvents.filter(e => e.address === COMMON_FOREIGN_BRIDGE_ADDRESS) + + // Get transfer events for each previous erc20 + const uniqueTokenAddresses = [...new Set(bridgeTokensSwappedEvents.map(e => e.returnValues.from))] + await Promise.all( + uniqueTokenAddresses.map(async tokenAddress => { + const previousERC20 = new web3Foreign.eth.Contract(ERC20_ABI, tokenAddress) + + const previousTransferEvents = (await getPastEvents(previousERC20, { + event: 'Transfer', + fromBlock: MONITOR_FOREIGN_START_BLOCK, + toBlock: foreignBlockNumber, + options: { + filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS } + } + })).map(normalizeEvent) + transferEvents = [...previousTransferEvents, ...transferEvents] + }) + ) + + // filter transfer that is part of a token swap + directTransfers = transferEvents.filter( + e => + bridgeTokensSwappedEvents.findIndex( + t => t.transactionHash === e.referenceTx && e.recipient === ZERO_ADDRESS + ) === -1 + ) + } + // Get transfer events that didn't have a UserRequestForAffirmation event in the same transaction - const directTransfers = transferEvents.filter( + directTransfers = directTransfers.filter( e => foreignToHomeRequests.findIndex(t => t.referenceTx === e.referenceTx) === -1 ) diff --git a/oracle/src/events/processTransfers/index.js b/oracle/src/events/processTransfers/index.js index 9bf716a9..0b8d8c93 100644 --- a/oracle/src/events/processTransfers/index.js +++ b/oracle/src/events/processTransfers/index.js @@ -1,7 +1,7 @@ require('../../../env') const promiseLimit = require('promise-limit') const { HttpListProviderError } = require('http-list-provider') -const { BRIDGE_VALIDATORS_ABI } = require('../../../../commons') +const { BRIDGE_VALIDATORS_ABI, ZERO_ADDRESS } = require('../../../../commons') const rootLogger = require('../../services/logger') const { web3Home, web3Foreign } = require('../../services/web3') const { AlreadyProcessedError, AlreadySignedError, InvalidValidatorError } = require('../../utils/errors') @@ -17,7 +17,9 @@ function processTransfersBuilder(config) { const userRequestForAffirmationAbi = config.foreignBridgeAbi.filter( e => e.type === 'event' && e.name === 'UserRequestForAffirmation' )[0] + const tokensSwappedAbi = config.foreignBridgeAbi.filter(e => e.type === 'event' && e.name === 'TokensSwapped')[0] const userRequestForAffirmationHash = web3Home.eth.abi.encodeEventSignature(userRequestForAffirmationAbi) + const tokensSwappedHash = tokensSwappedAbi ? web3Home.eth.abi.encodeEventSignature(tokensSwappedAbi) : '0x' return async function processTransfers(transfers) { const txToSend = [] @@ -42,6 +44,7 @@ function processTransfersBuilder(config) { logger.info({ from, value }, `Processing transfer ${transfer.transactionHash}`) const receipt = await web3Foreign.eth.getTransactionReceipt(transfer.transactionHash) + const existsAffirmationEvent = receipt.logs.some( e => e.address === config.foreignBridgeAddress && e.topics[0] === userRequestForAffirmationHash ) @@ -55,6 +58,17 @@ function processTransfersBuilder(config) { return } + const existsTokensSwappedEvent = tokensSwappedAbi + ? receipt.logs.some(e => e.address === config.foreignBridgeAddress && e.topics[0] === tokensSwappedHash) + : false + + if (from === ZERO_ADDRESS && existsTokensSwappedEvent) { + logger.info( + `Transfer event discarded because token swap is detected in transaction ${transfer.transactionHash}` + ) + return + } + let gasEstimate try { logger.debug('Estimate gas')