Remove half duplex erc20 token support from oracle (#413)
This commit is contained in:
parent
c2f6b5e8ba
commit
bea91c0e6e
@ -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
|
|
Loading…
Reference in New Issue
Block a user