Remove half duplex erc20 token support from oracle (#413)

This commit is contained in:
Gerardo Nardelli 2020-08-11 17:37:47 -03:00 committed by GitHub
parent c2f6b5e8ba
commit bea91c0e6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 5 additions and 470 deletions

@ -13,7 +13,6 @@ const REWARDABLE_VALIDATORS_ABI = require('../contracts/build/contracts/Rewardab
const HOME_AMB_ABI = require('../contracts/build/contracts/HomeAMB').abi const HOME_AMB_ABI = require('../contracts/build/contracts/HomeAMB').abi
const FOREIGN_AMB_ABI = require('../contracts/build/contracts/ForeignAMB').abi const FOREIGN_AMB_ABI = require('../contracts/build/contracts/ForeignAMB').abi
const BOX_ABI = require('../contracts/build/contracts/Box').abi const BOX_ABI = require('../contracts/build/contracts/Box').abi
const SAI_TOP = require('../contracts/build/contracts/SaiTopMock').abi
const HOME_AMB_ERC_TO_ERC_ABI = require('../contracts/build/contracts/HomeAMBErc677ToErc677').abi const HOME_AMB_ERC_TO_ERC_ABI = require('../contracts/build/contracts/HomeAMBErc677ToErc677').abi
const FOREIGN_AMB_ERC_TO_ERC_ABI = require('../contracts/build/contracts/ForeignAMBErc677ToErc677').abi const FOREIGN_AMB_ERC_TO_ERC_ABI = require('../contracts/build/contracts/ForeignAMBErc677ToErc677').abi
const HOME_STAKE_ERC_TO_ERC_ABI = require('../contracts/build/contracts/HomeStakeTokenMediator').abi const HOME_STAKE_ERC_TO_ERC_ABI = require('../contracts/build/contracts/HomeStakeTokenMediator').abi
@ -136,7 +135,6 @@ module.exports = {
OLD_AMB_USER_REQUEST_FOR_AFFIRMATION_ABI, OLD_AMB_USER_REQUEST_FOR_AFFIRMATION_ABI,
OLD_AMB_USER_REQUEST_FOR_SIGNATURE_ABI, OLD_AMB_USER_REQUEST_FOR_SIGNATURE_ABI,
BOX_ABI, BOX_ABI,
SAI_TOP,
HOME_STAKE_ERC_TO_ERC_ABI, HOME_STAKE_ERC_TO_ERC_ABI,
FOREIGN_STAKE_ERC_TO_ERC_ABI FOREIGN_STAKE_ERC_TO_ERC_ABI
} }

@ -1 +1 @@
Subproject commit f405ba9e56ca447b84ee5d53e93ac919b8f8565f Subproject commit dd46135248dbb4684752735aab3cf64db170a405

@ -50,8 +50,6 @@
"home": "0x488Af810997eD1730cB3a3918cD83b3216E6eAda", "home": "0x488Af810997eD1730cB3a3918cD83b3216E6eAda",
"foreign": "0x488Af810997eD1730cB3a3918cD83b3216E6eAda", "foreign": "0x488Af810997eD1730cB3a3918cD83b3216E6eAda",
"foreignToken": "0x7cc4b1851c35959d34e635a470f6b5c43ba3c9c9", "foreignToken": "0x7cc4b1851c35959d34e635a470f6b5c43ba3c9c9",
"halfDuplexToken": "0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359",
"saiTop": "0x9b0ccf7C8994E19F39b2B4CF708e0A7DF65fA8a3",
"chaiToken": "0x06af07097c9eeb7fd685c692751d5c66db49c215", "chaiToken": "0x06af07097c9eeb7fd685c692751d5c66db49c215",
"ui": "http://localhost:3002", "ui": "http://localhost:3002",
"monitor": "http://monitor-erc20-native:3012/bridge" "monitor": "http://monitor-erc20-native:3012/bridge"

@ -22,8 +22,6 @@ startValidator () {
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:collected-signatures docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:collected-signatures
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:affirmation-request docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:affirmation-request
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:transfer docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:transfer
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:half-duplex-transfer
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn worker:swap-tokens
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn worker:convert-to-chai docker-compose $1 run $2 $3 -d oracle-erc20-native yarn worker:convert-to-chai
docker-compose $1 run $2 $3 -d oracle-amb yarn watcher:signature-request docker-compose $1 run $2 $3 -d oracle-amb yarn watcher:signature-request
docker-compose $1 run $2 $3 -d oracle-amb yarn watcher:collected-signatures docker-compose $1 run $2 $3 -d oracle-amb yarn watcher:collected-signatures
@ -57,8 +55,6 @@ while [ "$1" != "" ]; do
docker-compose run -d oracle-erc20-native yarn watcher:collected-signatures docker-compose run -d oracle-erc20-native yarn watcher:collected-signatures
docker-compose run -d oracle-erc20-native yarn watcher:affirmation-request docker-compose run -d oracle-erc20-native yarn watcher:affirmation-request
docker-compose run -d oracle-erc20-native yarn watcher:transfer docker-compose run -d oracle-erc20-native yarn watcher:transfer
docker-compose run -d oracle-erc20-native yarn watcher:half-duplex-transfer
docker-compose run -d oracle-erc20-native yarn worker:swap-tokens
docker-compose run -d oracle-erc20-native yarn worker:convert-to-chai docker-compose run -d oracle-erc20-native yarn worker:convert-to-chai
docker-compose run -d oracle-amb yarn watcher:signature-request docker-compose run -d oracle-amb yarn watcher:signature-request
docker-compose run -d oracle-amb yarn watcher:collected-signatures docker-compose run -d oracle-amb yarn watcher:collected-signatures

@ -31,12 +31,7 @@ const foreignBridge = new foreignWeb3.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, CO
const homeBridge = new homeWeb3.eth.Contract(HOME_ERC_TO_NATIVE_ABI, COMMON_HOME_BRIDGE_ADDRESS) const homeBridge = new homeWeb3.eth.Contract(HOME_ERC_TO_NATIVE_ABI, COMMON_HOME_BRIDGE_ADDRESS)
describe('erc to native', () => { describe('erc to native', () => {
let halfDuplexTokenAddress
let halfDuplexToken
before(async () => { before(async () => {
halfDuplexTokenAddress = await foreignBridge.methods.halfDuplexErc20token().call()
halfDuplexToken = new foreignWeb3.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, halfDuplexTokenAddress)
// Set 2 required signatures for home bridge // Set 2 required signatures for home bridge
await setRequiredSignatures({ await setRequiredSignatures({
bridgeContract: homeBridge, bridgeContract: homeBridge,
@ -59,85 +54,6 @@ describe('erc to native', () => {
} }
}) })
}) })
it('should not convert half duplex tokens to native tokens in home', async () => {
const originalBalanceOnHome = await homeWeb3.eth.getBalance(user.address)
const transferValue = homeWeb3.utils.toWei('0.01')
// send tokens to foreign bridge
await halfDuplexToken.methods
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, transferValue)
.send({
from: user.address,
gas: '1000000'
})
.catch(e => {
console.error(e)
})
// check that balance does not increases
await promiseRetry(async (retry, number) => {
const balance = await homeWeb3.eth.getBalance(user.address)
// retry at least 4 times to check transfer is not processed
if (toBN(balance).eq(toBN(originalBalanceOnHome)) && number < 4) {
retry()
} else {
assert(toBN(balance).eq(toBN(originalBalanceOnHome)), 'User balance should not be increased')
}
})
// send tokens to foreign bridge
await erc20Token.methods
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, transferValue)
.send({
from: user.address,
gas: '1000000'
})
.catch(e => {
console.error(e)
})
// check that balance increases
await promiseRetry(async (retry, number) => {
const balance = await homeWeb3.eth.getBalance(user.address)
// retry at least 4 times to check transfer is not double processed by the two watchers
if (toBN(balance).lte(toBN(originalBalanceOnHome)) || number < 4) {
retry()
} else {
assert(
toBN(balance).eq(toBN(originalBalanceOnHome).add(toBN(transferValue))),
'User balance should be increased only by second transfer'
)
}
})
const afterTransferBalance = await homeWeb3.eth.getBalance(user.address)
// send tokens to foreign bridge
await erc20Token.methods
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, transferValue)
.send({
from: user.address,
gas: '1000000'
})
.catch(e => {
console.error(e)
})
// check that balance increases
await promiseRetry(async (retry, number) => {
const balance = await homeWeb3.eth.getBalance(user.address)
// retry at least 4 times to check transfer is not double processed by the two watchers
if (toBN(balance).lte(toBN(afterTransferBalance)) || number < 4) {
retry()
} else {
assert(
toBN(balance).eq(toBN(afterTransferBalance).add(toBN(transferValue))),
'User balance should be increased'
)
}
})
})
it('should convert tokens in foreign to coins in home', async () => { it('should convert tokens in foreign to coins in home', async () => {
const balance = await erc20Token.methods.balanceOf(user.address).call() const balance = await erc20Token.methods.balanceOf(user.address).call()
const originalBalanceOnHome = await homeWeb3.eth.getBalance(user.address) const originalBalanceOnHome = await homeWeb3.eth.getBalance(user.address)

@ -1,39 +0,0 @@
const baseConfig = require('./base.config')
const { ERC20_ABI } = require('../../commons')
const { EXIT_CODES } = require('../src/utils/constants')
const initialChecksJson = process.argv[3]
if (!initialChecksJson) {
throw new Error('initial check parameter was not provided.')
}
let initialChecks
try {
initialChecks = JSON.parse(initialChecksJson)
} catch (e) {
throw new Error('Error on decoding values from initial checks.')
}
const id = `${baseConfig.id}-half-duplex-transfer`
const transferWatcherRequired = baseConfig.id === 'erc-native'
if (!transferWatcherRequired) {
console.error(`Transfer watcher not required for bridge mode ${process.env.ORACLE_BRIDGE_MODE}`)
process.exit(EXIT_CODES.WATCHER_NOT_REQUIRED)
}
module.exports = {
...baseConfig.bridgeConfig,
...baseConfig.foreignConfig,
event: 'Transfer',
eventContractAddress: initialChecks.halfDuplexTokenAddress,
eventAbi: ERC20_ABI,
eventFilter: { to: process.env.COMMON_FOREIGN_BRIDGE_ADDRESS },
queue: 'home',
workerQueue: 'swap-tokens',
name: `watcher-${id}`,
id,
idle: initialChecks.idle
}

@ -1,20 +0,0 @@
const baseConfig = require('./base.config')
const { EXIT_CODES } = require('../src/utils/constants')
const id = `${baseConfig.id}-swap-tokens`
const workerRequired = baseConfig.id === 'erc-native'
if (!workerRequired) {
console.error(`Swap tokens worker not required for bridge mode ${process.env.ORACLE_BRIDGE_MODE}`)
process.exit(EXIT_CODES.WATCHER_NOT_REQUIRED)
}
module.exports = {
...baseConfig.bridgeConfig,
...baseConfig.foreignConfig,
workerQueue: 'swap-tokens',
senderQueue: 'foreign',
name: `worker-${id}`,
id
}

@ -7,8 +7,6 @@ services:
service: rabbit service: rabbit
networks: networks:
- net_rabbit_bridge_transfer - net_rabbit_bridge_transfer
- net_rabbit_bridge_half_duplex_transfer
- net_rabbit_bridge_swap_tokens_worker
- net_rabbit_bridge_convert_to_chai_worker - net_rabbit_bridge_convert_to_chai_worker
redis: redis:
extends: extends:
@ -16,7 +14,6 @@ services:
service: redis service: redis
networks: networks:
- net_db_bridge_transfer - net_db_bridge_transfer
- net_db_bridge_half_duplex_transfer
bridge_request: bridge_request:
extends: extends:
file: docker-compose.yml file: docker-compose.yml
@ -51,31 +48,6 @@ services:
networks: networks:
- net_db_bridge_transfer - net_db_bridge_transfer
- net_rabbit_bridge_transfer - net_rabbit_bridge_transfer
bridge_half_duplex_transfer:
cpus: 0.1
mem_limit: 500m
image: poanetwork/tokenbridge-oracle:latest
env_file: ./.env
environment:
- NODE_ENV=production
- ORACLE_VALIDATOR_ADDRESS=${ORACLE_VALIDATOR_ADDRESS}
restart: unless-stopped
entrypoint: yarn watcher:half-duplex-transfer
networks:
- net_db_bridge_half_duplex_transfer
- net_rabbit_bridge_half_duplex_transfer
bridge_swap_tokens_worker:
cpus: 0.1
mem_limit: 500m
image: poanetwork/tokenbridge-oracle:latest
env_file: ./.env
environment:
- NODE_ENV=production
- ORACLE_VALIDATOR_ADDRESS=${ORACLE_VALIDATOR_ADDRESS}
restart: unless-stopped
entrypoint: yarn worker:swap-tokens
networks:
- net_rabbit_bridge_swap_tokens_worker
bridge_convert_to_chai_worker: bridge_convert_to_chai_worker:
cpus: 0.1 cpus: 0.1
mem_limit: 500m mem_limit: 500m
@ -112,8 +84,6 @@ networks:
driver: bridge driver: bridge
net_db_bridge_transfer: net_db_bridge_transfer:
driver: bridge driver: bridge
net_db_bridge_half_duplex_transfer:
driver: bridge
net_db_bridge_senderhome: net_db_bridge_senderhome:
driver: bridge driver: bridge
net_db_bridge_senderforeign: net_db_bridge_senderforeign:
@ -126,10 +96,6 @@ networks:
driver: bridge driver: bridge
net_rabbit_bridge_transfer: net_rabbit_bridge_transfer:
driver: bridge driver: bridge
net_rabbit_bridge_half_duplex_transfer:
driver: bridge
net_rabbit_bridge_swap_tokens_worker:
driver: bridge
net_rabbit_bridge_senderhome: net_rabbit_bridge_senderhome:
driver: bridge driver: bridge
net_rabbit_bridge_senderforeign: net_rabbit_bridge_senderforeign:

@ -9,13 +9,11 @@
"watcher:collected-signatures": "./scripts/start-worker.sh watcher collected-signatures-watcher", "watcher:collected-signatures": "./scripts/start-worker.sh watcher collected-signatures-watcher",
"watcher:affirmation-request": "./scripts/start-worker.sh watcher affirmation-request-watcher", "watcher:affirmation-request": "./scripts/start-worker.sh watcher affirmation-request-watcher",
"watcher:transfer": "./scripts/start-worker.sh watcher transfer-watcher", "watcher:transfer": "./scripts/start-worker.sh watcher transfer-watcher",
"watcher:half-duplex-transfer": "./scripts/start-worker.sh watcher half-duplex-transfer-watcher",
"worker:swap-tokens": "./scripts/start-worker.sh worker swap-tokens-worker",
"worker:convert-to-chai": "./scripts/start-worker.sh worker convert-to-chai-worker", "worker:convert-to-chai": "./scripts/start-worker.sh worker convert-to-chai-worker",
"sender:home": "./scripts/start-worker.sh sender home-sender", "sender:home": "./scripts/start-worker.sh sender home-sender",
"sender:foreign": "./scripts/start-worker.sh sender foreign-sender", "sender:foreign": "./scripts/start-worker.sh sender foreign-sender",
"confirm:transfer": "./scripts/start-worker.sh confirmRelay transfer-watcher", "confirm:transfer": "./scripts/start-worker.sh confirmRelay transfer-watcher",
"dev": "concurrently -n 'watcher:signature-request,watcher:collected-signatures,watcher:affirmation-request,watcher:transfer,watcher:half-duplex-transfer, worker:swap-tokens, sender:home,sender:foreign' -c 'red,green,yellow,blue,white,gray,magenta,cyan' 'yarn watcher:signature-request' 'yarn watcher:collected-signatures' 'yarn watcher:affirmation-request' 'yarn watcher:transfer' 'yarn watcher:half-duplex-transfer' 'yarn worker:swap-tokens' 'yarn sender:home' 'yarn sender:foreign'", "dev": "concurrently -n 'watcher:signature-request,watcher:collected-signatures,watcher:affirmation-request,watcher:transfer, sender:home,sender:foreign' -c 'red,green,yellow,blue,magenta,cyan' 'yarn watcher:signature-request' 'yarn watcher:collected-signatures' 'yarn watcher:affirmation-request' 'yarn watcher:transfer' 'yarn sender:home' 'yarn sender:foreign'",
"test": "NODE_ENV=test mocha", "test": "NODE_ENV=test mocha",
"test:watch": "NODE_ENV=test mocha --watch --reporter=min", "test:watch": "NODE_ENV=test mocha --watch --reporter=min",
"coverage": "NODE_ENV=test nyc --reporter=text --reporter=html mocha", "coverage": "NODE_ENV=test nyc --reporter=text --reporter=html mocha",

@ -1,134 +0,0 @@
require('../../../env')
const promiseLimit = require('promise-limit')
const { HttpListProviderError } = require('http-list-provider')
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')
const { EXIT_CODES, MAX_CONCURRENT_EVENTS } = require('../../utils/constants')
const estimateGas = require('../processAffirmationRequests/estimateGas')
const limit = promiseLimit(MAX_CONCURRENT_EVENTS)
let validatorContract = null
function processTransfersBuilder(config) {
const homeBridge = new web3Home.eth.Contract(config.homeBridgeAbi, config.homeBridgeAddress)
const foreignBridge = new web3Foreign.eth.Contract(config.foreignBridgeAbi, config.foreignBridgeAddress)
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, blockNumber) {
const txToSend = []
if (validatorContract === null) {
rootLogger.debug('Getting validator contract address')
const validatorContractAddress = await homeBridge.methods.validatorContract().call()
rootLogger.debug({ validatorContractAddress }, 'Validator contract address obtained')
validatorContract = new web3Home.eth.Contract(BRIDGE_VALIDATORS_ABI, validatorContractAddress)
}
rootLogger.debug(`Processing ${transfers.length} Transfer events`)
const callbacks = transfers
.map(transfer => async () => {
const { from, value } = transfer.returnValues
const logger = rootLogger.child({
eventTransactionHash: transfer.transactionHash
})
logger.info({ from, value }, `Processing transfer ${transfer.transactionHash}`)
const block = await web3Foreign.eth.getBlock(blockNumber)
logger.debug({ blockNumber, timestamp: block.timestamp }, `Block obtained`)
const tokenSwapAllowed = await foreignBridge.methods.isTokenSwapAllowed(block.timestamp).call()
if (!tokenSwapAllowed) {
logger.info(
`Transfer event discarded because SCD Emergency Shutdown has happened ${transfer.transactionHash}`
)
return
}
const receipt = await web3Foreign.eth.getTransactionReceipt(transfer.transactionHash)
const existsAffirmationEvent = receipt.logs.some(
e => e.address === config.foreignBridgeAddress && e.topics[0] === userRequestForAffirmationHash
)
if (existsAffirmationEvent) {
logger.info(
`Transfer event discarded because a transaction with alternative receiver detected in transaction ${
transfer.transactionHash
}`
)
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')
gasEstimate = await estimateGas({
web3: web3Home,
homeBridge,
validatorContract,
recipient: from,
value,
txHash: transfer.transactionHash,
address: config.validatorAddress
})
logger.debug({ gasEstimate }, 'Gas estimated')
} catch (e) {
if (e instanceof HttpListProviderError) {
throw new Error('RPC Connection Error: submitSignature Gas Estimate cannot be obtained.')
} else if (e instanceof InvalidValidatorError) {
logger.fatal({ address: config.validatorAddress }, 'Invalid validator')
process.exit(EXIT_CODES.INCOMPATIBILITY)
} else if (e instanceof AlreadySignedError) {
logger.info(`Already signed transfer ${transfer.transactionHash}`)
return
} else if (e instanceof AlreadyProcessedError) {
logger.info(`transfer ${transfer.transactionHash} was already processed by other validators`)
return
} else {
logger.error(e, 'Unknown error while processing transaction')
throw e
}
}
const data = await homeBridge.methods
.executeAffirmation(from, value, transfer.transactionHash)
.encodeABI({ from: config.validatorAddress })
txToSend.push({
data,
gasEstimate,
transactionReference: transfer.transactionHash,
to: config.homeBridgeAddress
})
})
.map(promise => limit(promise))
await Promise.all(callbacks)
return txToSend
}
}
module.exports = processTransfersBuilder

@ -8,21 +8,6 @@ async function getTokensState(bridgeContract, logger) {
throw new Error(`Bridgeable token address cannot be obtained`) throw new Error(`Bridgeable token address cannot be obtained`)
} }
try {
logger.debug('Getting Half Duplex token address')
const halfDuplexErc20tokenAddress = await bridgeContract.methods.halfDuplexErc20token().call()
logger.debug({ address: halfDuplexErc20tokenAddress }, 'Half Duplex token address obtained')
if (halfDuplexErc20tokenAddress !== context.bridgeableTokenAddress) {
context.halfDuplexTokenAddress = halfDuplexErc20tokenAddress
} else {
logger.info('Migration to support two tokens was not applied')
context.idle = true
}
} catch (e) {
logger.info('Old version of contracts is used')
context.idle = true
}
return context return context
} }

@ -22,7 +22,6 @@ const processSignatureRequests = require('./events/processSignatureRequests')(co
const processCollectedSignatures = require('./events/processCollectedSignatures')(config) const processCollectedSignatures = require('./events/processCollectedSignatures')(config)
const processAffirmationRequests = require('./events/processAffirmationRequests')(config) const processAffirmationRequests = require('./events/processAffirmationRequests')(config)
const processTransfers = require('./events/processTransfers')(config) const processTransfers = require('./events/processTransfers')(config)
const processHalfDuplexTransfers = require('./events/processHalfDuplexTransfers')(config)
const processAMBSignatureRequests = require('./events/processAMBSignatureRequests')(config) const processAMBSignatureRequests = require('./events/processAMBSignatureRequests')(config)
const processAMBCollectedSignatures = require('./events/processAMBCollectedSignatures')(config) const processAMBCollectedSignatures = require('./events/processAMBCollectedSignatures')(config)
const processAMBAffirmationRequests = require('./events/processAMBAffirmationRequests')(config) const processAMBAffirmationRequests = require('./events/processAMBAffirmationRequests')(config)
@ -36,7 +35,6 @@ const web3Instance = config.web3
const bridgeContract = new web3Instance.eth.Contract(config.bridgeAbi, config.bridgeContractAddress) const bridgeContract = new web3Instance.eth.Contract(config.bridgeAbi, config.bridgeContractAddress)
let { eventContractAddress } = config let { eventContractAddress } = config
let eventContract = new web3Instance.eth.Contract(config.eventAbi, eventContractAddress) let eventContract = new web3Instance.eth.Contract(config.eventAbi, eventContractAddress)
let skipEvents = config.idle
const lastBlockRedisKey = `${config.id}:lastProcessedBlock` const lastBlockRedisKey = `${config.id}:lastProcessedBlock`
let lastProcessedBlock = BN.max(config.startBlock.sub(ONE), ZERO) let lastProcessedBlock = BN.max(config.startBlock.sub(ONE), ZERO)
@ -91,7 +89,7 @@ function updateLastProcessedBlock(lastBlockNumber) {
return redis.set(lastBlockRedisKey, lastProcessedBlock.toString()) return redis.set(lastBlockRedisKey, lastProcessedBlock.toString())
} }
function processEvents(events, blockNumber) { function processEvents(events) {
switch (config.id) { switch (config.id) {
case 'native-erc-signature-request': case 'native-erc-signature-request':
case 'erc-erc-signature-request': case 'erc-erc-signature-request':
@ -109,8 +107,6 @@ function processEvents(events, blockNumber) {
case 'erc-erc-transfer': case 'erc-erc-transfer':
case 'erc-native-transfer': case 'erc-native-transfer':
return processTransfers(events) return processTransfers(events)
case 'erc-native-half-duplex-transfer':
return processHalfDuplexTransfers(events, blockNumber)
case 'amb-signature-request': case 'amb-signature-request':
return processAMBSignatureRequests(events) return processAMBSignatureRequests(events)
case 'amb-collected-signatures': case 'amb-collected-signatures':
@ -130,12 +126,6 @@ async function checkConditions() {
state = await getTokensState(bridgeContract, logger) state = await getTokensState(bridgeContract, logger)
updateEventContract(state.bridgeableTokenAddress) updateEventContract(state.bridgeableTokenAddress)
break break
case 'erc-native-half-duplex-transfer':
logger.debug('Getting Half Duplex token address to listen Transfer events')
state = await getTokensState(bridgeContract, logger)
skipEvents = state.idle
updateEventContract(state.halfDuplexTokenAddress)
break
default: default:
} }
} }
@ -171,11 +161,6 @@ async function main({ sendToQueue, sendToWorker }) {
try { try {
await checkConditions() await checkConditions()
if (skipEvents) {
logger.debug('Watcher in idle mode, skipping getting events')
return
}
const lastBlockToProcess = await getLastBlockToProcess() const lastBlockToProcess = await getLastBlockToProcess()
if (lastBlockToProcess.lte(lastProcessedBlock)) { if (lastBlockToProcess.lte(lastProcessedBlock)) {
@ -200,7 +185,7 @@ async function main({ sendToQueue, sendToWorker }) {
await sendToWorker({ blockNumber: toBlock.toString() }) await sendToWorker({ blockNumber: toBlock.toString() })
} }
const job = await processEvents(events, toBlock.toString()) const job = await processEvents(events)
logger.info('Transactions to send:', job.length) logger.info('Transactions to send:', job.length)
if (job.length) { if (job.length) {

@ -7,7 +7,6 @@ const { connectWorkerToQueue } = require('./services/amqpClient')
const config = require(path.join('../config/', process.argv[2])) const config = require(path.join('../config/', process.argv[2]))
const swapTokens = require('./workers/swapTokens')(config)
const convertToChai = require('./workers/convertToChai')(config) const convertToChai = require('./workers/convertToChai')(config)
async function initialize() { async function initialize() {
@ -38,9 +37,7 @@ async function initialize() {
} }
async function run(blockNumber) { async function run(blockNumber) {
if (config.id === 'erc-native-swap-tokens') { if (config.id === 'erc-native-convert-to-chai') {
return swapTokens(blockNumber)
} else if (config.id === 'erc-native-convert-to-chai') {
return convertToChai(blockNumber) return convertToChai(blockNumber)
} else { } else {
return [] return []

@ -1,111 +0,0 @@
require('../../env')
const { HttpListProviderError } = require('http-list-provider')
const rootLogger = require('../services/logger')
const { web3Foreign } = require('../services/web3')
const { BRIDGE_VALIDATORS_ABI, ERC20_ABI } = require('../../../commons')
let validatorContract = null
let halfDuplexTokenContract = null
function swapTokensBuilder(config) {
const foreignBridge = new web3Foreign.eth.Contract(config.foreignBridgeAbi, config.foreignBridgeAddress)
return async function swapTokens(blockNumber) {
const txToSend = []
const logger = rootLogger.child({
blockNumber: blockNumber.toString()
})
logger.debug(`Starting swap tokens operation`)
if (validatorContract === null) {
logger.debug('Getting validator contract address')
const validatorContractAddress = await foreignBridge.methods.validatorContract().call()
logger.debug({ validatorContractAddress }, 'Validator contract address obtained')
validatorContract = new web3Foreign.eth.Contract(BRIDGE_VALIDATORS_ABI, validatorContractAddress)
}
logger.debug(`Checking if is validator duty`)
const validatorDuty = await validatorContract.methods.isValidatorDuty(config.validatorAddress).call()
if (!validatorDuty) {
logger.info(`Token swap discarded because is not validator duty`)
return txToSend
}
logger.debug(`Checking if half duplex token balance is above the threshold`)
const hdTokenBalanceAboveMinBalance = await foreignBridge.methods.isHDTokenBalanceAboveMinBalance().call()
if (!hdTokenBalanceAboveMinBalance) {
logger.info(`Token swap discarded because half duplex balance is below the threshold`)
return txToSend
}
const block = await web3Foreign.eth.getBlock(blockNumber)
logger.debug({ timestamp: block.timestamp }, `Block obtained`)
logger.debug(`Checking if SCD Emergency Shutdown has happened`)
const tokenSwapAllowed = await foreignBridge.methods.isTokenSwapAllowed(block.timestamp).call()
if (!tokenSwapAllowed) {
logger.info(`Token swap discarded because SCD Emergency Shutdown has happened`)
return txToSend
}
let gasEstimate
try {
logger.debug(`Estimate gas`)
gasEstimate = await foreignBridge.methods.swapTokens().estimateGas({
from: config.validatorAddress
})
logger.debug({ gasEstimate }, 'Gas estimated')
} catch (e) {
if (e instanceof HttpListProviderError) {
const errorMsg = 'RPC Connection Error: swapTokens Gas Estimate cannot be obtained.'
logger.error(e, errorMsg)
throw new Error(errorMsg)
} else {
if (halfDuplexTokenContract === null) {
logger.debug('Getting half duplex token contract address')
const halfDuplexErc20Token = await foreignBridge.methods.halfDuplexErc20token().call()
logger.debug({ halfDuplexErc20Token }, 'Half duplex token contract address obtained')
halfDuplexTokenContract = new web3Foreign.eth.Contract(ERC20_ABI, halfDuplexErc20Token)
}
const balance = web3Foreign.utils.toBN(
await halfDuplexTokenContract.methods.balanceOf(config.foreignBridgeAddress).call()
)
logger.debug({ balance: balance.toString() }, 'Half duplex token bridge balance obtained')
if (balance.isZero()) {
logger.info(`Gas estimate failed because half duplex token balance is zero. Tokens swap is discarded.`)
return txToSend
}
logger.error(e, 'Unknown error while processing transaction')
throw e
}
}
// generate data
const data = await foreignBridge.methods.swapTokens().encodeABI()
// push to job
txToSend.push({
data,
gasEstimate,
transactionReference: `swap tokens operation for block number ${blockNumber.toString()}`,
to: config.foreignBridgeAddress
})
return txToSend
}
}
module.exports = swapTokensBuilder