2019-05-08 16:12:02 +03:00
|
|
|
require('dotenv').config()
|
|
|
|
const Web3 = require('web3')
|
|
|
|
const { toBN } = require('web3').utils
|
|
|
|
const logger = require('../logger')('eventsUtils')
|
2019-07-12 15:49:46 +03:00
|
|
|
const {
|
|
|
|
BRIDGE_MODES,
|
|
|
|
ERC_TYPES,
|
|
|
|
getBridgeABIs,
|
|
|
|
getBridgeMode,
|
|
|
|
HOME_ERC_TO_ERC_ABI,
|
2019-07-26 15:26:14 +03:00
|
|
|
ERC20_ABI,
|
|
|
|
ERC677_BRIDGE_TOKEN_ABI,
|
2019-08-08 16:27:09 +03:00
|
|
|
getTokenType,
|
2019-11-06 22:49:01 +03:00
|
|
|
getPastEvents,
|
|
|
|
ZERO_ADDRESS
|
2019-07-12 15:49:46 +03:00
|
|
|
} = require('../../commons')
|
2019-10-29 22:22:02 +03:00
|
|
|
const { normalizeEventInformation } = require('./message')
|
2019-12-19 12:39:41 +03:00
|
|
|
const { filterTransferBeforeES } = require('./tokenUtils')
|
2019-05-08 16:12:02 +03:00
|
|
|
|
2019-09-13 10:11:38 +03:00
|
|
|
const {
|
|
|
|
COMMON_HOME_RPC_URL,
|
|
|
|
COMMON_FOREIGN_RPC_URL,
|
|
|
|
COMMON_HOME_BRIDGE_ADDRESS,
|
|
|
|
COMMON_FOREIGN_BRIDGE_ADDRESS
|
|
|
|
} = process.env
|
|
|
|
const MONITOR_HOME_START_BLOCK = toBN(Number(process.env.MONITOR_HOME_START_BLOCK) || 0)
|
|
|
|
const MONITOR_FOREIGN_START_BLOCK = toBN(Number(process.env.MONITOR_FOREIGN_START_BLOCK) || 0)
|
2019-05-08 16:12:02 +03:00
|
|
|
|
2019-09-13 10:11:38 +03:00
|
|
|
const homeProvider = new Web3.providers.HttpProvider(COMMON_HOME_RPC_URL)
|
2019-05-08 16:12:02 +03:00
|
|
|
const web3Home = new Web3(homeProvider)
|
|
|
|
|
2019-09-13 10:11:38 +03:00
|
|
|
const foreignProvider = new Web3.providers.HttpProvider(COMMON_FOREIGN_RPC_URL)
|
2019-05-08 16:12:02 +03:00
|
|
|
const web3Foreign = new Web3(foreignProvider)
|
|
|
|
|
2019-08-08 16:27:09 +03:00
|
|
|
const { getBlockNumber } = require('./contract')
|
2019-05-08 16:12:02 +03:00
|
|
|
|
2019-05-31 21:35:50 +03:00
|
|
|
async function main(mode) {
|
2019-09-13 10:11:38 +03:00
|
|
|
const homeErcBridge = new web3Home.eth.Contract(HOME_ERC_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
2019-05-31 21:35:50 +03:00
|
|
|
const bridgeMode = mode || (await getBridgeMode(homeErcBridge))
|
|
|
|
const { HOME_ABI, FOREIGN_ABI } = getBridgeABIs(bridgeMode)
|
2019-09-13 10:11:38 +03: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)
|
2019-05-31 21:35:50 +03:00
|
|
|
const v1Bridge = bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC_V1
|
2019-09-18 22:45:13 +03:00
|
|
|
let isExternalErc20
|
|
|
|
let erc20Contract
|
2019-12-19 12:39:41 +03:00
|
|
|
let erc20Address
|
2019-10-29 22:22:02 +03:00
|
|
|
let normalizeEvent = normalizeEventInformation
|
2019-09-18 22:45:13 +03:00
|
|
|
if (bridgeMode !== BRIDGE_MODES.ARBITRARY_MESSAGE) {
|
|
|
|
const erc20MethodName = bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC || v1Bridge ? 'erc677token' : 'erc20token'
|
2019-12-19 12:39:41 +03:00
|
|
|
erc20Address = await foreignBridge.methods[erc20MethodName]().call()
|
2019-09-18 22:45:13 +03:00
|
|
|
const tokenType = await getTokenType(
|
|
|
|
new web3Foreign.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, erc20Address),
|
|
|
|
COMMON_FOREIGN_BRIDGE_ADDRESS
|
|
|
|
)
|
|
|
|
isExternalErc20 = tokenType === ERC_TYPES.ERC20
|
|
|
|
erc20Contract = new web3Foreign.eth.Contract(ERC20_ABI, erc20Address)
|
2019-10-29 22:22:02 +03:00
|
|
|
} else {
|
|
|
|
normalizeEvent = e => e
|
2019-09-18 22:45:13 +03:00
|
|
|
}
|
2019-05-08 16:12:02 +03:00
|
|
|
|
2019-05-31 21:35:50 +03:00
|
|
|
logger.debug('getting last block numbers')
|
|
|
|
const [homeBlockNumber, foreignBlockNumber] = await getBlockNumber(web3Home, web3Foreign)
|
2019-05-08 16:12:02 +03:00
|
|
|
|
2019-05-31 21:35:50 +03:00
|
|
|
logger.debug("calling homeBridge.getPastEvents('UserRequestForSignature')")
|
2019-10-29 22:22:02 +03:00
|
|
|
const homeToForeignRequests = (await getPastEvents(homeBridge, {
|
2019-05-31 21:35:50 +03:00
|
|
|
event: v1Bridge ? 'Deposit' : 'UserRequestForSignature',
|
2019-09-13 10:11:38 +03:00
|
|
|
fromBlock: MONITOR_HOME_START_BLOCK,
|
2019-08-08 16:27:09 +03:00
|
|
|
toBlock: homeBlockNumber
|
2019-10-29 22:22:02 +03:00
|
|
|
})).map(normalizeEvent)
|
2019-05-08 16:12:02 +03:00
|
|
|
|
2019-05-31 21:35:50 +03:00
|
|
|
logger.debug("calling foreignBridge.getPastEvents('RelayedMessage')")
|
2019-10-29 22:22:02 +03:00
|
|
|
const homeToForeignConfirmations = (await getPastEvents(foreignBridge, {
|
2019-05-31 21:35:50 +03:00
|
|
|
event: v1Bridge ? 'Deposit' : 'RelayedMessage',
|
2019-09-13 10:11:38 +03:00
|
|
|
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
2019-08-08 16:27:09 +03:00
|
|
|
toBlock: foreignBlockNumber
|
2019-10-29 22:22:02 +03:00
|
|
|
})).map(normalizeEvent)
|
2019-05-08 16:12:02 +03:00
|
|
|
|
2019-05-31 21:35:50 +03:00
|
|
|
logger.debug("calling homeBridge.getPastEvents('AffirmationCompleted')")
|
2019-10-29 22:22:02 +03:00
|
|
|
const foreignToHomeConfirmations = (await getPastEvents(homeBridge, {
|
2019-05-31 21:35:50 +03:00
|
|
|
event: v1Bridge ? 'Withdraw' : 'AffirmationCompleted',
|
2019-09-13 10:11:38 +03:00
|
|
|
fromBlock: MONITOR_HOME_START_BLOCK,
|
2019-08-08 16:27:09 +03:00
|
|
|
toBlock: homeBlockNumber
|
2019-10-29 22:22:02 +03:00
|
|
|
})).map(normalizeEvent)
|
2019-05-08 16:12:02 +03:00
|
|
|
|
2019-05-31 21:35:50 +03:00
|
|
|
logger.debug("calling foreignBridge.getPastEvents('UserRequestForAffirmation')")
|
2019-10-29 22:22:02 +03:00
|
|
|
let foreignToHomeRequests = (await getPastEvents(foreignBridge, {
|
|
|
|
event: v1Bridge ? 'Withdraw' : 'UserRequestForAffirmation',
|
|
|
|
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
|
|
|
toBlock: foreignBlockNumber
|
|
|
|
})).map(normalizeEvent)
|
|
|
|
if (isExternalErc20) {
|
|
|
|
logger.debug("calling erc20Contract.getPastEvents('Transfer')")
|
2019-11-06 22:49:01 +03:00
|
|
|
let transferEvents = (await getPastEvents(erc20Contract, {
|
2019-10-29 22:22:02 +03:00
|
|
|
event: 'Transfer',
|
|
|
|
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
|
|
|
toBlock: foreignBlockNumber,
|
|
|
|
options: {
|
|
|
|
filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS }
|
|
|
|
}
|
|
|
|
})).map(normalizeEvent)
|
|
|
|
|
2019-11-06 22:49:01 +03:00
|
|
|
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
|
2020-03-13 01:12:48 +03:00
|
|
|
const uniqueTokenAddressesSet = new Set(bridgeTokensSwappedEvents.map(e => e.returnValues.from))
|
|
|
|
|
|
|
|
// Exclude chai token from previous erc20
|
|
|
|
try {
|
|
|
|
logger.debug('calling foreignBridge.chaiToken()')
|
|
|
|
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()')
|
|
|
|
const daiToken = await foreignBridge.methods.erc20token().call()
|
|
|
|
uniqueTokenAddressesSet.delete(daiToken)
|
|
|
|
} catch (e) {
|
|
|
|
logger.debug('call to foreignBridge.erc20token() failed')
|
|
|
|
}
|
|
|
|
|
|
|
|
const uniqueTokenAddresses = [...uniqueTokenAddressesSet]
|
2019-11-06 22:49:01 +03:00
|
|
|
await Promise.all(
|
|
|
|
uniqueTokenAddresses.map(async tokenAddress => {
|
2019-12-19 12:39:41 +03:00
|
|
|
const halfDuplexTokenContract = new web3Foreign.eth.Contract(ERC20_ABI, tokenAddress)
|
2019-11-06 22:49:01 +03:00
|
|
|
|
2019-12-19 12:39:41 +03:00
|
|
|
const halfDuplexTransferEvents = (await getPastEvents(halfDuplexTokenContract, {
|
2019-11-06 22:49:01 +03:00
|
|
|
event: 'Transfer',
|
|
|
|
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
|
|
|
toBlock: foreignBlockNumber,
|
|
|
|
options: {
|
|
|
|
filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS }
|
|
|
|
}
|
|
|
|
})).map(normalizeEvent)
|
2019-12-19 12:39:41 +03:00
|
|
|
|
|
|
|
// Remove events after the ES
|
|
|
|
const validHalfDuplexTransfers = await filterTransferBeforeES(
|
|
|
|
halfDuplexTransferEvents,
|
|
|
|
web3Foreign,
|
|
|
|
foreignBridge
|
|
|
|
)
|
|
|
|
|
|
|
|
transferEvents = [...validHalfDuplexTransfers, ...transferEvents]
|
2019-11-06 22:49:01 +03:00
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
// 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
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-10-29 22:22:02 +03:00
|
|
|
// Get transfer events that didn't have a UserRequestForAffirmation event in the same transaction
|
2019-11-06 22:49:01 +03:00
|
|
|
directTransfers = directTransfers.filter(
|
2019-10-29 22:22:02 +03:00
|
|
|
e => foreignToHomeRequests.findIndex(t => t.referenceTx === e.referenceTx) === -1
|
|
|
|
)
|
|
|
|
|
|
|
|
foreignToHomeRequests = [...foreignToHomeRequests, ...directTransfers]
|
|
|
|
}
|
|
|
|
|
2019-05-31 21:35:50 +03:00
|
|
|
logger.debug('Done')
|
|
|
|
return {
|
2019-09-18 22:45:13 +03:00
|
|
|
homeToForeignRequests,
|
|
|
|
homeToForeignConfirmations,
|
|
|
|
foreignToHomeConfirmations,
|
|
|
|
foreignToHomeRequests,
|
|
|
|
isExternalErc20,
|
|
|
|
bridgeMode
|
2019-05-08 16:12:02 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = main
|