tokenbridge/monitor/utils/events.js

267 lines
10 KiB
JavaScript
Raw Permalink Normal View History

2019-05-08 15:12:02 +02:00
require('dotenv').config()
const logger = require('../logger')('eventsUtils')
2019-07-12 14:49:46 +02:00
const {
BRIDGE_MODES,
getBridgeABIs,
getBridgeMode,
HOME_ERC_TO_NATIVE_ABI,
ERC20_ABI,
ZERO_ADDRESS,
OLD_AMB_USER_REQUEST_FOR_SIGNATURE_ABI,
OLD_AMB_USER_REQUEST_FOR_AFFIRMATION_ABI
2019-07-12 14:49:46 +02:00
} = require('../../commons')
const { normalizeEventInformation } = require('./message')
const { filterTransferBeforeES } = require('./tokenUtils')
const { writeFile, readCacheFile } = require('./file')
2020-11-04 14:24:42 +03:00
const { web3Home, web3Foreign, getHomeBlockNumber, getForeignBlockNumber } = require('./web3')
const { getPastEvents } = require('./web3Cache')
2019-05-08 15:12:02 +02:00
const { COMMON_HOME_BRIDGE_ADDRESS, COMMON_FOREIGN_BRIDGE_ADDRESS, MONITOR_CACHE_EVENTS } = process.env
2020-11-04 14:24:42 +03:00
const MONITOR_HOME_START_BLOCK = Number(process.env.MONITOR_HOME_START_BLOCK) || 0
const MONITOR_FOREIGN_START_BLOCK = Number(process.env.MONITOR_FOREIGN_START_BLOCK) || 0
2019-05-08 15:12:02 +02:00
const cacheFilePath = '/tmp/cachedEvents.json'
async function main(mode) {
if (MONITOR_CACHE_EVENTS === 'true') {
logger.debug('checking existing events cache')
const cachedEvents = readCacheFile(cacheFilePath)
if (cachedEvents !== false) {
logger.debug('returning events stored in cache')
return cachedEvents
}
}
const homeErcBridge = new web3Home.eth.Contract(HOME_ERC_TO_NATIVE_ABI, COMMON_HOME_BRIDGE_ADDRESS)
const bridgeMode = mode || (await getBridgeMode(homeErcBridge))
const { HOME_ABI, FOREIGN_ABI } = getBridgeABIs(bridgeMode)
Consistent variable naming (#198) * Add console.table * First steps in validate script * env rename * Added parameter names * Descriptions * Print and configuration * Added more parameters * Rename gas oracle to gas supplier * More changes * Removed env examples for now * RPC rename * Bridge address rename * More changes * jobs * Renames * Typo * jobs * Changes * jobs * Changes * Monitor changes * jovs * Typo * Changes * REACT_APP_ env prefix * Typo * Rollback changes * Oracle deployment * Defaults * Monitor * Naming * Typo * Typo * Envs * ui deployment * ALl jobs * Vars in ultimate * Lint * Lint * Lint * Another way to add REACT_APP prefixing * Unnecessary mapping * No output timeout * No output timeout * Got rid of ERC20_TOKEN_ADDRESS * Configuration readme * Configuration * Prefixes * timeout * Docs * Docs * docs * docs * docs * Roll back ERC20_TOKEN_ADDRESS for erc-to-erc * Typo * lint * Rollback * ROllback validator * Rollback yarn.lock * dai and wetc update * Rollback ERC20_TOKEN_ADDRESS * erc to native * examples * all jobs * roll back * roll back ERC20_TOKEN_ADDRESS: "0xdbeE25CbE97e4A5CC6c499875774dc7067E9426B" * ui env example * typo * Allow rpc for ultimate * Test * ERC20_TOKEN_ADDRESS rollback * Specify port * React port * All jobs * cosmetics * Values * Restore erc20 token * Rearrange example for easier comparision * Rearrange ultimate for easier comparision * Rearrange for easier comparision * Refactor * Conditional app styles * Loading environment variables in react app * Add missing vars for UI in wetc and dai * Bring back test parameters readme * Readme for monitor vars * Reading environment variables in e2e-commons (#207)
2019-09-13 09:11:38 +02:00
const homeBridge = new web3Home.eth.Contract(HOME_ABI, COMMON_HOME_BRIDGE_ADDRESS)
const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
let isExternalErc20 = false
2019-09-18 16:45:13 -03:00
let erc20Contract
let erc20Address
let normalizeEvent = normalizeEventInformation
2019-09-18 16:45:13 -03:00
if (bridgeMode !== BRIDGE_MODES.ARBITRARY_MESSAGE) {
erc20Address = await foreignBridge.methods.erc20token().call()
isExternalErc20 = true
2019-09-18 16:45:13 -03:00
erc20Contract = new web3Foreign.eth.Contract(ERC20_ABI, erc20Address)
} else {
normalizeEvent = e => e
2019-09-18 16:45:13 -03:00
}
2019-05-08 15:12:02 +02:00
logger.debug('getting last block numbers')
2020-11-04 14:24:42 +03:00
const homeBlockNumber = await getHomeBlockNumber()
const foreignBlockNumber = await getForeignBlockNumber()
const homeConfirmations = await homeBridge.methods.requiredBlockConfirmations().call()
const foreignConfirmations = await foreignBridge.methods.requiredBlockConfirmations().call()
const homeDelayedBlockNumber = homeBlockNumber - homeConfirmations
const foreignDelayedBlockNumber = foreignBlockNumber - foreignConfirmations
let homeToForeignRequests = []
let foreignToHomeRequests = []
let homeMigrationBlock = MONITOR_HOME_START_BLOCK
let foreignMigrationBlock = MONITOR_FOREIGN_START_BLOCK
if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) {
const oldHomeBridge = new web3Home.eth.Contract(OLD_AMB_USER_REQUEST_FOR_SIGNATURE_ABI, COMMON_HOME_BRIDGE_ADDRESS)
const oldForeignBridge = new web3Foreign.eth.Contract(
OLD_AMB_USER_REQUEST_FOR_AFFIRMATION_ABI,
COMMON_FOREIGN_BRIDGE_ADDRESS
)
logger.debug("calling oldHomeBridge.getPastEvents('UserRequestForSignature(bytes)')")
homeToForeignRequests = (await getPastEvents(oldHomeBridge, {
event: 'UserRequestForSignature',
fromBlock: MONITOR_HOME_START_BLOCK,
2020-11-04 14:24:42 +03:00
toBlock: homeDelayedBlockNumber,
chain: 'home'
})).map(normalizeEvent)
logger.debug(`found ${homeToForeignRequests.length} events`)
if (homeToForeignRequests.length > 0) {
2020-11-04 14:24:42 +03:00
homeMigrationBlock = Math.max(...homeToForeignRequests.map(x => x.blockNumber))
}
logger.debug("calling oldForeignBridge.getPastEvents('UserRequestForAffirmation(bytes)')")
foreignToHomeRequests = (await getPastEvents(oldForeignBridge, {
event: 'UserRequestForAffirmation',
fromBlock: MONITOR_FOREIGN_START_BLOCK,
2020-11-04 14:24:42 +03:00
toBlock: foreignDelayedBlockNumber,
chain: 'foreign'
})).map(normalizeEvent)
logger.debug(`found ${foreignToHomeRequests.length} events`)
if (foreignToHomeRequests.length > 0) {
2020-11-04 14:24:42 +03:00
foreignMigrationBlock = Math.max(...foreignToHomeRequests.map(x => x.blockNumber))
}
}
2019-05-08 15:12:02 +02:00
logger.debug("calling homeBridge.getPastEvents('UserRequestForSignature')")
const homeToForeignRequestsNew = (await getPastEvents(homeBridge, {
event: 'UserRequestForSignature',
fromBlock: homeMigrationBlock,
2020-11-04 14:24:42 +03:00
toBlock: homeDelayedBlockNumber,
chain: 'home'
})).map(normalizeEvent)
homeToForeignRequests = [...homeToForeignRequests, ...homeToForeignRequestsNew]
2019-05-08 15:12:02 +02:00
logger.debug("calling foreignBridge.getPastEvents('RelayedMessage')")
const homeToForeignConfirmations = (await getPastEvents(foreignBridge, {
event: 'RelayedMessage',
Consistent variable naming (#198) * Add console.table * First steps in validate script * env rename * Added parameter names * Descriptions * Print and configuration * Added more parameters * Rename gas oracle to gas supplier * More changes * Removed env examples for now * RPC rename * Bridge address rename * More changes * jobs * Renames * Typo * jobs * Changes * jobs * Changes * Monitor changes * jovs * Typo * Changes * REACT_APP_ env prefix * Typo * Rollback changes * Oracle deployment * Defaults * Monitor * Naming * Typo * Typo * Envs * ui deployment * ALl jobs * Vars in ultimate * Lint * Lint * Lint * Another way to add REACT_APP prefixing * Unnecessary mapping * No output timeout * No output timeout * Got rid of ERC20_TOKEN_ADDRESS * Configuration readme * Configuration * Prefixes * timeout * Docs * Docs * docs * docs * docs * Roll back ERC20_TOKEN_ADDRESS for erc-to-erc * Typo * lint * Rollback * ROllback validator * Rollback yarn.lock * dai and wetc update * Rollback ERC20_TOKEN_ADDRESS * erc to native * examples * all jobs * roll back * roll back ERC20_TOKEN_ADDRESS: "0xdbeE25CbE97e4A5CC6c499875774dc7067E9426B" * ui env example * typo * Allow rpc for ultimate * Test * ERC20_TOKEN_ADDRESS rollback * Specify port * React port * All jobs * cosmetics * Values * Restore erc20 token * Rearrange example for easier comparision * Rearrange ultimate for easier comparision * Rearrange for easier comparision * Refactor * Conditional app styles * Loading environment variables in react app * Add missing vars for UI in wetc and dai * Bring back test parameters readme * Readme for monitor vars * Reading environment variables in e2e-commons (#207)
2019-09-13 09:11:38 +02:00
fromBlock: MONITOR_FOREIGN_START_BLOCK,
2020-11-04 14:24:42 +03:00
toBlock: foreignBlockNumber,
chain: 'foreign',
safeToBlock: foreignDelayedBlockNumber
})).map(normalizeEvent)
2019-05-08 15:12:02 +02:00
logger.debug("calling homeBridge.getPastEvents('AffirmationCompleted')")
const foreignToHomeConfirmations = (await getPastEvents(homeBridge, {
event: 'AffirmationCompleted',
Consistent variable naming (#198) * Add console.table * First steps in validate script * env rename * Added parameter names * Descriptions * Print and configuration * Added more parameters * Rename gas oracle to gas supplier * More changes * Removed env examples for now * RPC rename * Bridge address rename * More changes * jobs * Renames * Typo * jobs * Changes * jobs * Changes * Monitor changes * jovs * Typo * Changes * REACT_APP_ env prefix * Typo * Rollback changes * Oracle deployment * Defaults * Monitor * Naming * Typo * Typo * Envs * ui deployment * ALl jobs * Vars in ultimate * Lint * Lint * Lint * Another way to add REACT_APP prefixing * Unnecessary mapping * No output timeout * No output timeout * Got rid of ERC20_TOKEN_ADDRESS * Configuration readme * Configuration * Prefixes * timeout * Docs * Docs * docs * docs * docs * Roll back ERC20_TOKEN_ADDRESS for erc-to-erc * Typo * lint * Rollback * ROllback validator * Rollback yarn.lock * dai and wetc update * Rollback ERC20_TOKEN_ADDRESS * erc to native * examples * all jobs * roll back * roll back ERC20_TOKEN_ADDRESS: "0xdbeE25CbE97e4A5CC6c499875774dc7067E9426B" * ui env example * typo * Allow rpc for ultimate * Test * ERC20_TOKEN_ADDRESS rollback * Specify port * React port * All jobs * cosmetics * Values * Restore erc20 token * Rearrange example for easier comparision * Rearrange ultimate for easier comparision * Rearrange for easier comparision * Refactor * Conditional app styles * Loading environment variables in react app * Add missing vars for UI in wetc and dai * Bring back test parameters readme * Readme for monitor vars * Reading environment variables in e2e-commons (#207)
2019-09-13 09:11:38 +02:00
fromBlock: MONITOR_HOME_START_BLOCK,
2020-11-04 14:24:42 +03:00
toBlock: homeBlockNumber,
chain: 'home',
safeToBlock: homeDelayedBlockNumber
})).map(normalizeEvent)
2019-05-08 15:12:02 +02:00
logger.debug("calling foreignBridge.getPastEvents('UserRequestForAffirmation')")
const foreignToHomeRequestsNew = (await getPastEvents(foreignBridge, {
event: 'UserRequestForAffirmation',
fromBlock: foreignMigrationBlock,
2020-11-04 14:24:42 +03:00
toBlock: foreignDelayedBlockNumber,
chain: 'foreign'
})).map(normalizeEvent)
foreignToHomeRequests = [...foreignToHomeRequests, ...foreignToHomeRequestsNew]
let informationRequests
let informationResponses
if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) {
logger.debug("calling homeBridge.getPastEvents('UserRequestForInformation')")
informationRequests = (await getPastEvents(homeBridge, {
event: 'UserRequestForInformation',
fromBlock: MONITOR_HOME_START_BLOCK,
toBlock: homeDelayedBlockNumber,
chain: 'home'
})).map(normalizeEvent)
logger.debug("calling foreignBridge.getPastEvents('InformationRetrieved')")
informationResponses = (await getPastEvents(homeBridge, {
event: 'InformationRetrieved',
fromBlock: MONITOR_HOME_START_BLOCK,
toBlock: homeBlockNumber,
safeToBlock: homeDelayedBlockNumber,
chain: 'home'
})).map(normalizeEvent)
}
if (isExternalErc20) {
logger.debug("calling erc20Contract.getPastEvents('Transfer')")
let transferEvents = (await getPastEvents(erc20Contract, {
event: 'Transfer',
fromBlock: MONITOR_FOREIGN_START_BLOCK,
toBlock: foreignDelayedBlockNumber,
options: {
filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS }
2020-11-04 14:24:42 +03:00
},
chain: 'foreign'
})).map(normalizeEvent)
let directTransfers = transferEvents
const tokensSwappedAbiExists = FOREIGN_ABI.filter(e => e.type === 'event' && e.name === 'TokensSwapped')[0]
if (tokensSwappedAbiExists) {
logger.debug('collecting half duplex tokens participated in the bridge balance')
logger.debug("calling foreignBridge.getPastEvents('TokensSwapped')")
const tokensSwappedEvents = await getPastEvents(foreignBridge, {
event: 'TokensSwapped',
fromBlock: MONITOR_FOREIGN_START_BLOCK,
2020-11-04 14:24:42 +03:00
toBlock: foreignBlockNumber,
chain: 'foreign',
safeToBlock: foreignDelayedBlockNumber
})
// 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 uniqueTokenAddressesSet = new Set(bridgeTokensSwappedEvents.map(e => e.returnValues.from))
// Exclude chai token from previous erc20
try {
logger.debug('calling foreignBridge.chaiToken() to remove it from half duplex tokens list')
const chaiToken = await foreignBridge.methods.chaiToken().call()
uniqueTokenAddressesSet.delete(chaiToken)
} catch (e) {
logger.debug('call to foreignBridge.chaiToken() failed')
}
// Exclude dai token from previous erc20
try {
logger.debug('calling foreignBridge.erc20token() to remove it from half duplex tokens list')
const daiToken = await foreignBridge.methods.erc20token().call()
uniqueTokenAddressesSet.delete(daiToken)
} catch (e) {
logger.debug('call to foreignBridge.erc20token() failed')
}
const uniqueTokenAddresses = [...uniqueTokenAddressesSet]
await Promise.all(
uniqueTokenAddresses.map(async tokenAddress => {
const halfDuplexTokenContract = new web3Foreign.eth.Contract(ERC20_ABI, tokenAddress)
logger.debug('Half duplex token:', tokenAddress)
logger.debug("calling halfDuplexTokenContract.getPastEvents('Transfer')")
const halfDuplexTransferEvents = (await getPastEvents(halfDuplexTokenContract, {
event: 'Transfer',
fromBlock: MONITOR_FOREIGN_START_BLOCK,
toBlock: foreignDelayedBlockNumber,
options: {
filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS }
2020-11-04 14:24:42 +03:00
},
chain: 'foreign'
})).map(normalizeEvent)
// Remove events after the ES
logger.debug('filtering half duplex transfers happened before ES')
const validHalfDuplexTransfers = await filterTransferBeforeES(halfDuplexTransferEvents)
transferEvents = [...validHalfDuplexTransfers, ...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
directTransfers = directTransfers.filter(
e => foreignToHomeRequests.findIndex(t => t.referenceTx === e.referenceTx) === -1
)
foreignToHomeRequests = [...foreignToHomeRequests, ...directTransfers]
}
logger.debug('Done')
const result = {
2019-09-18 16:45:13 -03:00
homeToForeignRequests,
homeToForeignConfirmations,
foreignToHomeConfirmations,
foreignToHomeRequests,
informationRequests,
informationResponses,
2019-09-18 16:45:13 -03:00
isExternalErc20,
2020-11-04 14:24:42 +03:00
bridgeMode,
2021-04-02 12:59:49 +03:00
homeBlockNumber,
foreignBlockNumber,
2020-11-04 14:24:42 +03:00
homeDelayedBlockNumber,
foreignDelayedBlockNumber
2019-05-08 15:12:02 +02:00
}
if (MONITOR_CACHE_EVENTS === 'true') {
logger.debug('saving obtained events into cache file')
2021-04-02 12:59:49 +03:00
writeFile(cacheFilePath, result, { useCwd: false })
}
return result
2019-05-08 15:12:02 +02:00
}
module.exports = main