Merge the develop branch to the master branch, preparation to v2.0.0-rc1
This commit is contained in:
commit
8ae0fa82d5
@ -245,7 +245,7 @@ jobs:
|
||||
- tokenbridge-orb/yarn-install-cached-on-machine
|
||||
- run:
|
||||
name: Prepare the infrastructure
|
||||
command: e2e-commons/up.sh deploy << parameters.scenario-name >>
|
||||
command: e2e-commons/up.sh deploy << parameters.scenario-name >> blocks
|
||||
no_output_timeout: 50m
|
||||
- tokenbridge-orb/wait-for-oracle:
|
||||
redis-key: << parameters.redis-key >>
|
||||
@ -256,7 +256,6 @@ jobs:
|
||||
name: Run the ui-e2e tests
|
||||
command: |
|
||||
nvm use default;
|
||||
node ./e2e-commons/scripts/blocks.js &
|
||||
cd ui-e2e; yarn mocha -g "<< parameters.ui-e2e-grep >>" -b ./test.js
|
||||
- when:
|
||||
condition: << parameters.oracle-e2e-script >>
|
||||
|
@ -66,11 +66,13 @@ Clone the repository:
|
||||
git clone https://github.com/poanetwork/tokenbridge
|
||||
```
|
||||
|
||||
Initialize submodules, install dependencies, compile the Smart Contracts:
|
||||
If there is no need to build docker images for the TokenBridge components (oracle, monitor, UI), initialize submodules, install dependencies, compile the Smart Contracts:
|
||||
```
|
||||
yarn initialize
|
||||
```
|
||||
|
||||
Then refer to the corresponding README files to get information about particular TokenBridge component.
|
||||
|
||||
## Linting
|
||||
|
||||
Running linter for all JS projects:
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 7e17921ffc56287678eb54eadd325a7406821ed9
|
||||
Subproject commit 026dbfdac8eb067af078a69483f474051a8a6379
|
@ -32,6 +32,9 @@
|
||||
group: "root"
|
||||
mode: "0755"
|
||||
|
||||
- name: Upgrade pip version
|
||||
shell: pip3 install --upgrade pip
|
||||
|
||||
- name: Install python docker library
|
||||
shell: pip3 install docker docker-compose setuptools
|
||||
|
||||
|
@ -52,6 +52,7 @@
|
||||
"foreignToken": "0x7cc4b1851c35959d34e635a470f6b5c43ba3c9c9",
|
||||
"halfDuplexToken": "0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359",
|
||||
"saiTop": "0x9b0ccf7C8994E19F39b2B4CF708e0A7DF65fA8a3",
|
||||
"chaiToken": "0x06af07097c9eeb7fd685c692751d5c66db49c215",
|
||||
"ui": "http://localhost:3002",
|
||||
"monitor": "http://monitor-erc20-native:3012/bridge"
|
||||
},
|
||||
|
@ -97,8 +97,7 @@ services:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: monitor/Dockerfile
|
||||
args:
|
||||
DOT_ENV_PATH: e2e-commons/components-envs/monitor.env
|
||||
env_file: ../e2e-commons/components-envs/monitor.env
|
||||
entrypoint: yarn check-and-start
|
||||
ports:
|
||||
- "3010:3010"
|
||||
@ -108,8 +107,7 @@ services:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: monitor/Dockerfile
|
||||
args:
|
||||
DOT_ENV_PATH: e2e-commons/components-envs/monitor-erc20.env
|
||||
env_file: ../e2e-commons/components-envs/monitor-erc20.env
|
||||
entrypoint: yarn check-and-start
|
||||
ports:
|
||||
- "3011:3011"
|
||||
@ -119,8 +117,7 @@ services:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: monitor/Dockerfile
|
||||
args:
|
||||
DOT_ENV_PATH: e2e-commons/components-envs/monitor-erc20-native.env
|
||||
env_file: ../e2e-commons/components-envs/monitor-erc20-native.env
|
||||
entrypoint: yarn check-and-start
|
||||
ports:
|
||||
- "3012:3012"
|
||||
@ -130,8 +127,7 @@ services:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: monitor/Dockerfile
|
||||
args:
|
||||
DOT_ENV_PATH: e2e-commons/components-envs/monitor-amb.env
|
||||
env_file: ../e2e-commons/components-envs/monitor-amb.env
|
||||
entrypoint: yarn check-and-start
|
||||
ports:
|
||||
- "3013:3013"
|
||||
@ -144,3 +140,10 @@ services:
|
||||
command: "true"
|
||||
networks:
|
||||
- ultimate
|
||||
blocks:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: Dockerfile.e2e
|
||||
entrypoint: node e2e-commons/scripts/blocks.js
|
||||
networks:
|
||||
- ultimate
|
||||
|
@ -1,8 +1,7 @@
|
||||
const Web3 = require('web3')
|
||||
const { generateNewBlock } = require('../utils')
|
||||
|
||||
const homeWeb3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8541'))
|
||||
const foreignWeb3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8542'))
|
||||
const homeWeb3 = new Web3(new Web3.providers.HttpProvider('http://parity1:8545'))
|
||||
const foreignWeb3 = new Web3(new Web3.providers.HttpProvider('http://parity2:8545'))
|
||||
const {user, blockGenerator} = require('../constants.json');
|
||||
|
||||
homeWeb3.eth.accounts.wallet.add(user.privateKey)
|
||||
@ -10,10 +9,24 @@ foreignWeb3.eth.accounts.wallet.add(user.privateKey)
|
||||
homeWeb3.eth.accounts.wallet.add(blockGenerator.privateKey)
|
||||
foreignWeb3.eth.accounts.wallet.add(blockGenerator.privateKey)
|
||||
|
||||
function generateNewBlock(web3, address) {
|
||||
return web3.eth.sendTransaction({
|
||||
from: address,
|
||||
to: '0x0000000000000000000000000000000000000000',
|
||||
gasPrice: '1',
|
||||
gas: '21000',
|
||||
value: '1'
|
||||
})
|
||||
}
|
||||
|
||||
function main() {
|
||||
setTimeout(async () => {
|
||||
generateNewBlock(homeWeb3, blockGenerator.address)
|
||||
generateNewBlock(foreignWeb3, blockGenerator.address)
|
||||
try {
|
||||
generateNewBlock(homeWeb3, blockGenerator.address)
|
||||
} catch {} // in case of Transaction with the same hash was already imported.
|
||||
try {
|
||||
generateNewBlock(foreignWeb3, blockGenerator.address)
|
||||
} catch {} // in case of Transaction with the same hash was already imported.
|
||||
main()
|
||||
}, 1000)
|
||||
}
|
||||
|
@ -6,6 +6,9 @@ CONTRACTS_PATH="../../contracts"
|
||||
DEPLOY_PATH="$CONTRACTS_PATH/deploy"
|
||||
ENVS_PATH="../contracts-envs"
|
||||
|
||||
# mock bridge validators contract with the one with deterministic isValidatorDuty
|
||||
mv "$CONTRACTS_PATH/build/contracts/BridgeValidatorsDeterministic.json" "$CONTRACTS_PATH/build/contracts/BridgeValidators.json"
|
||||
|
||||
echo -e "\n\n############ Deploying native-to-erc ############\n"
|
||||
cp "$ENVS_PATH/native-to-erc.env" "$DEPLOY_PATH/.env"
|
||||
cd "$DEPLOY_PATH"
|
||||
|
@ -23,6 +23,7 @@ startValidator () {
|
||||
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-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:affirmation-request
|
||||
@ -47,6 +48,7 @@ while [ "$1" != "" ]; do
|
||||
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-amb yarn watcher:signature-request
|
||||
docker-compose run -d oracle-amb yarn watcher:collected-signatures
|
||||
docker-compose run -d oracle-amb yarn watcher:affirmation-request
|
||||
@ -81,7 +83,7 @@ while [ "$1" != "" ]; do
|
||||
fi
|
||||
|
||||
if [ "$1" == "blocks" ]; then
|
||||
node ./scripts/blocks.js &
|
||||
docker-compose up -d blocks
|
||||
fi
|
||||
|
||||
if [ "$1" == "monitor" ]; then
|
||||
|
@ -1,13 +1,18 @@
|
||||
function generateNewBlock(web3, address) {
|
||||
return web3.eth.sendTransaction({
|
||||
from: address,
|
||||
to: '0x0000000000000000000000000000000000000000',
|
||||
gasPrice: '1',
|
||||
gas: '21000',
|
||||
value: '1'
|
||||
const promiseRetry = require('promise-retry')
|
||||
|
||||
async function uniformRetry(f) {
|
||||
return promiseRetry(f, {
|
||||
forever: true,
|
||||
factor: 1,
|
||||
minTimeout: 500
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
generateNewBlock
|
||||
async function sleep(timeout) {
|
||||
return new Promise(res => setTimeout(res, timeout))
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
uniformRetry,
|
||||
sleep
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
cd $(dirname $0)
|
||||
|
||||
../e2e-commons/up.sh deploy monitor
|
||||
../e2e-commons/up.sh deploy blocks monitor
|
||||
|
||||
./wait-for-monitor.sh
|
||||
nohup ./periodically-check-all.sh < /dev/null > /dev/null 2>&1 &
|
||||
|
@ -1,7 +1,15 @@
|
||||
const assert = require('assert')
|
||||
const axios = require('axios')
|
||||
const { ercToNativeBridge, user, foreignRPC, validator } = require('../../e2e-commons/constants.json')
|
||||
const { waitUntil, sendTokens, addValidator } = require('../utils')
|
||||
const {
|
||||
waitUntil,
|
||||
sendTokens,
|
||||
addValidator,
|
||||
initializeChaiToken,
|
||||
convertDaiToChai,
|
||||
setMinDaiTokenBalance,
|
||||
migrateToMCD
|
||||
} = require('../utils')
|
||||
|
||||
const baseUrl = ercToNativeBridge.monitor
|
||||
|
||||
@ -24,12 +32,45 @@ describe('ERC TO NATIVE with changing state of contracts', () => {
|
||||
assert((await axios.get(`${baseUrl}/validators`)).data.validatorsMatch === true)
|
||||
})
|
||||
|
||||
it('should change balanceDiff', async () => {
|
||||
it('should change balanceDiff', async function() {
|
||||
this.timeout(60000)
|
||||
await sendTokens(foreignRPC.URL, user, ercToNativeBridge.halfDuplexToken, ercToNativeBridge.foreign)
|
||||
|
||||
await waitUntil(async () => {
|
||||
;({ data } = await axios.get(`${baseUrl}`))
|
||||
return data.balanceDiff !== 0
|
||||
const { erc20Balance, halfDuplexErc20Balance, investedErc20Balance } = data.foreign
|
||||
return (
|
||||
data.balanceDiff === 0.01 &&
|
||||
erc20Balance === '0.01' &&
|
||||
halfDuplexErc20Balance === undefined &&
|
||||
investedErc20Balance === undefined
|
||||
)
|
||||
})
|
||||
|
||||
await migrateToMCD(foreignRPC.URL, ercToNativeBridge.foreign)
|
||||
|
||||
await waitUntil(async () => {
|
||||
;({ data } = await axios.get(`${baseUrl}`))
|
||||
const { erc20Balance, halfDuplexErc20Balance, investedErc20Balance } = data.foreign
|
||||
return (
|
||||
data.balanceDiff === 0.01 &&
|
||||
erc20Balance === '0.01' &&
|
||||
halfDuplexErc20Balance === '0' &&
|
||||
investedErc20Balance === undefined
|
||||
)
|
||||
})
|
||||
|
||||
await sendTokens(foreignRPC.URL, user, ercToNativeBridge.halfDuplexToken, ercToNativeBridge.foreign)
|
||||
|
||||
await waitUntil(async () => {
|
||||
;({ data } = await axios.get(`${baseUrl}`))
|
||||
const { erc20Balance, halfDuplexErc20Balance, investedErc20Balance } = data.foreign
|
||||
return (
|
||||
data.balanceDiff === 0.02 &&
|
||||
erc20Balance === '0.01' &&
|
||||
halfDuplexErc20Balance === '0.01' &&
|
||||
investedErc20Balance === undefined
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@ -40,4 +81,52 @@ describe('ERC TO NATIVE with changing state of contracts', () => {
|
||||
return data.validatorsMatch === false
|
||||
})
|
||||
})
|
||||
|
||||
it('should consider chai token balance', async function() {
|
||||
this.timeout(60000)
|
||||
await initializeChaiToken(foreignRPC.URL, ercToNativeBridge.foreign)
|
||||
await sendTokens(foreignRPC.URL, user, ercToNativeBridge.foreignToken, ercToNativeBridge.foreign)
|
||||
|
||||
await waitUntil(async () => {
|
||||
;({ data } = await axios.get(`${baseUrl}`))
|
||||
const { erc20Balance, halfDuplexErc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
|
||||
return (
|
||||
data.balanceDiff === 0.03 &&
|
||||
erc20Balance === '0.02' &&
|
||||
halfDuplexErc20Balance === '0.01' &&
|
||||
investedErc20Balance === '0' &&
|
||||
accumulatedInterest === '0.001' // value of dsrBalance() is initially defined in genesis block as 0.001
|
||||
)
|
||||
})
|
||||
|
||||
await setMinDaiTokenBalance(foreignRPC.URL, ercToNativeBridge.foreign, '0.01')
|
||||
await convertDaiToChai(foreignRPC.URL, ercToNativeBridge.foreign)
|
||||
|
||||
await waitUntil(async () => {
|
||||
;({ data } = await axios.get(`${baseUrl}`))
|
||||
const { erc20Balance, halfDuplexErc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
|
||||
return (
|
||||
data.balanceDiff === 0.03 &&
|
||||
erc20Balance === '0.01' &&
|
||||
halfDuplexErc20Balance === '0.01' &&
|
||||
investedErc20Balance === '0.01' &&
|
||||
accumulatedInterest === '0.001'
|
||||
)
|
||||
})
|
||||
|
||||
await setMinDaiTokenBalance(foreignRPC.URL, ercToNativeBridge.foreign, '0.005')
|
||||
await convertDaiToChai(foreignRPC.URL, ercToNativeBridge.foreign)
|
||||
|
||||
await waitUntil(async () => {
|
||||
;({ data } = await axios.get(`${baseUrl}`))
|
||||
const { erc20Balance, halfDuplexErc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
|
||||
return (
|
||||
data.balanceDiff === 0.03 &&
|
||||
erc20Balance === '0.005' &&
|
||||
halfDuplexErc20Balance === '0.01' &&
|
||||
investedErc20Balance === '0.015' &&
|
||||
accumulatedInterest === '0.001'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -1,5 +1,12 @@
|
||||
const Web3 = require('web3')
|
||||
const { ERC677_BRIDGE_TOKEN_ABI, BRIDGE_VALIDATORS_ABI, FOREIGN_NATIVE_TO_ERC_ABI, BOX_ABI } = require('../commons')
|
||||
const {
|
||||
ERC677_BRIDGE_TOKEN_ABI,
|
||||
BRIDGE_VALIDATORS_ABI,
|
||||
FOREIGN_NATIVE_TO_ERC_ABI,
|
||||
FOREIGN_ERC_TO_NATIVE_ABI,
|
||||
BOX_ABI
|
||||
} = require('../commons')
|
||||
const { validator } = require('../e2e-commons/constants')
|
||||
|
||||
const waitUntil = async (predicate, step = 100, timeout = 20000) => {
|
||||
const stopTime = Date.now() + timeout
|
||||
@ -60,10 +67,57 @@ const addValidator = async (rpcUrl, account, bridgeAddress) => {
|
||||
})
|
||||
}
|
||||
|
||||
const migrateToMCD = async (rpcUrl, bridgeAddress) => {
|
||||
const web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl))
|
||||
web3.eth.accounts.wallet.add(validator.privateKey)
|
||||
const bridgeContract = new web3.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, bridgeAddress)
|
||||
await bridgeContract.methods.migrateToMCD().send({
|
||||
from: validator.address,
|
||||
gas: '4000000'
|
||||
})
|
||||
}
|
||||
|
||||
const initializeChaiToken = async (rpcUrl, bridgeAddress) => {
|
||||
const web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl))
|
||||
web3.eth.accounts.wallet.add(validator.privateKey)
|
||||
const bridgeContract = new web3.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, bridgeAddress)
|
||||
|
||||
await bridgeContract.methods.initializeChaiToken().send({
|
||||
from: validator.address,
|
||||
gas: '1000000'
|
||||
})
|
||||
}
|
||||
|
||||
const setMinDaiTokenBalance = async (rpcUrl, bridgeAddress, limit) => {
|
||||
const web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl))
|
||||
web3.eth.accounts.wallet.add(validator.privateKey)
|
||||
const bridgeContract = new web3.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, bridgeAddress)
|
||||
|
||||
await bridgeContract.methods.setMinDaiTokenBalance(web3.utils.toWei(limit)).send({
|
||||
from: validator.address,
|
||||
gas: '1000000'
|
||||
})
|
||||
}
|
||||
|
||||
const convertDaiToChai = async (rpcUrl, bridgeAddress) => {
|
||||
const web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl))
|
||||
web3.eth.accounts.wallet.add(validator.privateKey)
|
||||
const bridgeContract = new web3.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, bridgeAddress)
|
||||
|
||||
await bridgeContract.methods.convertDaiToChai().send({
|
||||
from: validator.address,
|
||||
gas: '1000000'
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
waitUntil,
|
||||
sendEther,
|
||||
sendTokens,
|
||||
addValidator,
|
||||
sendAMBMessage
|
||||
sendAMBMessage,
|
||||
migrateToMCD,
|
||||
initializeChaiToken,
|
||||
setMinDaiTokenBalance,
|
||||
convertDaiToChai
|
||||
}
|
||||
|
@ -15,9 +15,9 @@ RUN mv ./contracts/build ./ && rm -rf ./contracts/* ./contracts/.[!.]* && mv ./b
|
||||
COPY ./commons ./commons
|
||||
|
||||
COPY ./monitor ./monitor
|
||||
ARG DOT_ENV_PATH=./monitor/.env
|
||||
COPY ${DOT_ENV_PATH} ./monitor/.env
|
||||
|
||||
WORKDIR /mono/monitor
|
||||
CMD echo "To start the monitor run:" \
|
||||
"yarn check-and-start"
|
||||
CMD echo "To start the monitor web service run:" \
|
||||
"yarn start" \
|
||||
"To run monitor scripts run:" \
|
||||
"yarn check-all"
|
||||
|
@ -4,7 +4,12 @@ Tool for checking balances and unprocessed events in bridged networks.
|
||||
## Overview
|
||||
Please refer to the [POA TokenBridge](../README.md) overview first of all.
|
||||
|
||||
- Deployed version: https://bridge-monitoring.poa.net/
|
||||
- Deployed version serves several monitor configurations:
|
||||
* https://bridge-monitoring.poa.net/poa
|
||||
* https://bridge-monitoring.poa.net/xdai
|
||||
* https://bridge-monitoring.poa.net/wetc
|
||||
* https://bridge-monitoring.poa.net/amb-dai
|
||||
* https://bridge-monitoring.poa.net/amb-poa
|
||||
|
||||
This tool allows you to spin up a NODE.JS server to monitor for health of the TokenBridge contracts: check for the balance difference, discover inconsistency in the validators list, catch unhandled transactions.
|
||||
|
||||
@ -122,14 +127,19 @@ yarn start
|
||||
You can run web interface via [pm2](https://www.npmjs.com/package/pm2) or similar supervisor program.
|
||||
|
||||
Using Docker:
|
||||
```
|
||||
docker-compose up -d
|
||||
```
|
||||
* to run it very first time (or after changes related to the monitor code):
|
||||
```
|
||||
docker-compose -f docker-compose-build.yml -f docker-compose.yml up -d --build
|
||||
```
|
||||
* next time (or in case of usage of an official docker image)
|
||||
```
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
- The application will run on `http://localhost:MONITOR_PORT/MONITOR_BRIDGE_NAME`, where `MONITOR_PORT` and `MONITOR_BRIDGE_NAME` are specified in your `.env` file.
|
||||
- To enabled debug logging, set `DEBUG=1` variable in `.env`.
|
||||
|
||||
## Check balances of contracts and validators, get unprocessed events
|
||||
## Preparing statistic about balances of bridge contracts and validators, get unprocessed events
|
||||
|
||||
Using Yarn:
|
||||
```
|
||||
@ -138,13 +148,32 @@ yarn check-all
|
||||
|
||||
Using Docker:
|
||||
```
|
||||
docker-compose exec monitor yarn check-all
|
||||
docker run --rm --env-file .env -v $(pwd)/responses:/mono/monitor/responses \
|
||||
poanetwork/tokenbridge-monitor:latest /bin/bash -c 'yarn check-all'
|
||||
```
|
||||
|
||||
As soon as the process finishes, use the URL described above to get the statistic.
|
||||
|
||||
### Cron
|
||||
|
||||
You can create cron job to run workers (see `crontab.example` for reference):
|
||||
|
||||
## Ad-hoc monitoring
|
||||
|
||||
There is a possibility to get bridge statistics without running the web interface use the commands provided above. In this case the results will be located in the `responses` directory.
|
||||
|
||||
## Build the image without running the monitor
|
||||
|
||||
To build the image change the directory:
|
||||
```
|
||||
cd monitor
|
||||
```
|
||||
|
||||
And run the docker composer:
|
||||
```
|
||||
docker-compose -f docker-compose-build.yml build
|
||||
```
|
||||
|
||||
## Linting
|
||||
|
||||
Running linter:
|
||||
|
@ -2,4 +2,4 @@
|
||||
*/4 * * * * cd $HOME/tokenbridge/monitor; yarn check-all >>cronWorker.out 2>>cronWorker.err
|
||||
|
||||
# Docker:
|
||||
*/4 * * * * cd $HOME/tokenbridge/monitor; docker-compose exec monitor yarn check-all >>cronWorker.out 2>>cronWorker.err
|
||||
*/4 * * * * cd $HOME/tokenbridge/monitor; docker run --rm --env-file .env -v $(pwd)/responses:/mono/monitor/responses poanetwork/tokenbridge-monitor:latest /bin/bash -c 'yarn check-all' >>cronWorker.out 2>>cronWorker.err
|
||||
|
6
monitor/docker-compose-build.yml
Normal file
6
monitor/docker-compose-build.yml
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
version: '2.4'
|
||||
services:
|
||||
monitor:
|
||||
image: poanetwork/tokenbridge-monitor
|
||||
build: .
|
@ -83,7 +83,10 @@ async function main(bridgeMode) {
|
||||
const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
const erc20Address = await foreignBridge.methods.erc20token().call()
|
||||
const erc20Contract = new web3Foreign.eth.Contract(ERC20_ABI, erc20Address)
|
||||
let investedAmountInDai = 0
|
||||
let bridgeDsrBalance = 0
|
||||
let foreignHalfDuplexErc20Balance = 0
|
||||
let displayChaiToken = false
|
||||
let displayHalfDuplexToken = false
|
||||
let tokenSwapAllowed = false
|
||||
try {
|
||||
@ -103,6 +106,21 @@ async function main(bridgeMode) {
|
||||
logger.debug('Methods for half duplex token are not present')
|
||||
}
|
||||
|
||||
try {
|
||||
logger.debug('calling foreignBridge.methods.isChaiTokenEnabled')
|
||||
if (await foreignBridge.methods.isChaiTokenEnabled().call()) {
|
||||
displayChaiToken = true
|
||||
logger.debug('calling foreignBridge.methods.investedAmountInDai')
|
||||
investedAmountInDai = await foreignBridge.methods.investedAmountInDai().call()
|
||||
logger.debug('calling foreignBridge.methods.dsrBalance')
|
||||
bridgeDsrBalance = await foreignBridge.methods.dsrBalance().call()
|
||||
} else {
|
||||
logger.debug('Chai token is currently disabled')
|
||||
}
|
||||
} catch (e) {
|
||||
logger.debug('Methods for chai token are not present')
|
||||
}
|
||||
|
||||
logger.debug('calling erc20Contract.methods.balanceOf')
|
||||
const foreignErc20Balance = await erc20Contract.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||
|
||||
@ -119,11 +137,14 @@ async function main(bridgeMode) {
|
||||
const burntCoinsBN = new BN(burntCoins)
|
||||
const totalSupplyBN = mintedCoinsBN.minus(burntCoinsBN)
|
||||
const foreignErc20BalanceBN = new BN(foreignErc20Balance)
|
||||
const investedAmountInDaiBN = new BN(investedAmountInDai)
|
||||
const bridgeDsrBalanceBN = new BN(bridgeDsrBalance)
|
||||
const halfDuplexErc20BalanceBN =
|
||||
displayHalfDuplexToken && tokenSwapAllowed ? new BN(foreignHalfDuplexErc20Balance) : new BN(0)
|
||||
|
||||
const diff = foreignErc20BalanceBN
|
||||
.plus(halfDuplexErc20BalanceBN)
|
||||
.plus(investedAmountInDaiBN)
|
||||
.minus(totalSupplyBN)
|
||||
.toFixed()
|
||||
|
||||
@ -143,6 +164,11 @@ async function main(bridgeMode) {
|
||||
}
|
||||
}
|
||||
|
||||
if (displayChaiToken) {
|
||||
foreign.investedErc20Balance = Web3Utils.fromWei(investedAmountInDai)
|
||||
foreign.accumulatedInterest = Web3Utils.fromWei(bridgeDsrBalanceBN.minus(investedAmountInDaiBN).toString(10))
|
||||
}
|
||||
|
||||
logger.debug('Done')
|
||||
return {
|
||||
home: {
|
||||
|
@ -1,6 +1,6 @@
|
||||
cd $(dirname $0)
|
||||
|
||||
../e2e-commons/up.sh deploy oracle oracle-validator-2 oracle-validator-3
|
||||
../e2e-commons/up.sh deploy blocks oracle oracle-validator-2 oracle-validator-3
|
||||
|
||||
docker-compose -f ../e2e-commons/docker-compose.yml run e2e yarn workspace oracle-e2e run start
|
||||
rc=$?
|
||||
|
@ -1,8 +1,7 @@
|
||||
const Web3 = require('web3')
|
||||
const assert = require('assert')
|
||||
const promiseRetry = require('promise-retry')
|
||||
const { user, homeRPC, foreignRPC, amb, validator } = require('../../e2e-commons/constants.json')
|
||||
const { generateNewBlock } = require('../../e2e-commons/utils')
|
||||
const { uniformRetry } = require('../../e2e-commons/utils')
|
||||
const { BOX_ABI, HOME_AMB_ABI, FOREIGN_AMB_ABI } = require('../../commons')
|
||||
const { setRequiredSignatures } = require('./utils')
|
||||
|
||||
@ -59,7 +58,7 @@ describe('arbitrary message bridging', () => {
|
||||
const initialValue = await foreignBox.methods.value().call()
|
||||
assert(!toBN(initialValue).eq(toBN(newValue)), 'initial value should be different from new value')
|
||||
|
||||
const setValueTx = await homeBox.methods
|
||||
await homeBox.methods
|
||||
.setValueOnOtherNetwork(newValue, amb.home, amb.foreignBox)
|
||||
.send({
|
||||
from: user.address,
|
||||
@ -69,31 +68,8 @@ describe('arbitrary message bridging', () => {
|
||||
console.error(e)
|
||||
})
|
||||
|
||||
// Send a trivial transaction to generate a new block since the watcher
|
||||
// is configured to wait 1 confirmation block
|
||||
await generateNewBlock(homeWeb3, user.address)
|
||||
|
||||
// The bridge should create a new transaction with a CollectedSignatures
|
||||
// event so we generate another trivial transaction
|
||||
await promiseRetry(
|
||||
async retry => {
|
||||
const lastBlockNumber = await homeWeb3.eth.getBlockNumber()
|
||||
if (lastBlockNumber >= setValueTx.blockNumber + 2) {
|
||||
await generateNewBlock(homeWeb3, user.address)
|
||||
} else {
|
||||
retry()
|
||||
}
|
||||
},
|
||||
{
|
||||
forever: true,
|
||||
factor: 1,
|
||||
minTimeout: 500
|
||||
}
|
||||
)
|
||||
|
||||
// check that value changed and balance decreased
|
||||
await promiseRetry(async retry => {
|
||||
await generateNewBlock(homeWeb3, user.address)
|
||||
await uniformRetry(async retry => {
|
||||
const value = await foreignBox.methods.value().call()
|
||||
if (!toBN(value).eq(toBN(newValue))) {
|
||||
retry()
|
||||
@ -120,12 +96,8 @@ describe('arbitrary message bridging', () => {
|
||||
console.error(e)
|
||||
})
|
||||
|
||||
// Send a trivial transaction to generate a new block since the watcher
|
||||
// is configured to wait 1 confirmation block
|
||||
await generateNewBlock(foreignWeb3, user.address)
|
||||
|
||||
// check that value changed and balance decreased
|
||||
await promiseRetry(async retry => {
|
||||
await uniformRetry(async retry => {
|
||||
const value = await homeBox.methods.value().call()
|
||||
if (!toBN(value).eq(toBN(newValue))) {
|
||||
retry()
|
||||
|
@ -1,9 +1,8 @@
|
||||
const Web3 = require('web3')
|
||||
const assert = require('assert')
|
||||
const promiseRetry = require('promise-retry')
|
||||
const { user, secondUser, ercToErcBridge, homeRPC, foreignRPC, validator } = require('../../e2e-commons/constants.json')
|
||||
const { ERC677_BRIDGE_TOKEN_ABI, FOREIGN_ERC_TO_NATIVE_ABI, HOME_ERC_TO_ERC_ABI } = require('../../commons')
|
||||
const { generateNewBlock } = require('../../e2e-commons/utils')
|
||||
const { uniformRetry } = require('../../e2e-commons/utils')
|
||||
const { setRequiredSignatures } = require('./utils')
|
||||
|
||||
const homeWeb3 = new Web3(new Web3.providers.HttpProvider(homeRPC.URL))
|
||||
@ -76,12 +75,8 @@ describe('erc to erc', () => {
|
||||
console.error(e)
|
||||
})
|
||||
|
||||
// Send a trivial transaction to generate a new block since the watcher
|
||||
// is configured to wait 1 confirmation block
|
||||
await generateNewBlock(foreignWeb3, user.address)
|
||||
|
||||
// check that balance increases
|
||||
await promiseRetry(async retry => {
|
||||
await uniformRetry(async retry => {
|
||||
const balance = await erc677Token.methods.balanceOf(user.address).call()
|
||||
const recipientBalance = await erc677Token.methods.balanceOf(secondUser.address).call()
|
||||
assert(toBN(balance).isZero(), 'User balance should be the same')
|
||||
@ -103,12 +98,8 @@ describe('erc to erc', () => {
|
||||
console.error(e)
|
||||
})
|
||||
|
||||
// Send a trivial transaction to generate a new block since the watcher
|
||||
// is configured to wait 1 confirmation block
|
||||
await generateNewBlock(foreignWeb3, user.address)
|
||||
|
||||
// check that balance increases
|
||||
await promiseRetry(async retry => {
|
||||
await uniformRetry(async retry => {
|
||||
const balance = await erc677Token.methods.balanceOf(user.address).call()
|
||||
if (toBN(balance).isZero()) {
|
||||
retry()
|
||||
@ -125,7 +116,7 @@ describe('erc to erc', () => {
|
||||
assert(!toBN(balance).isZero(), 'Account should have tokens')
|
||||
|
||||
// send transaction to home bridge
|
||||
const depositTx = await erc677Token.methods
|
||||
await erc677Token.methods
|
||||
.transferAndCall(COMMON_HOME_BRIDGE_ADDRESS, homeWeb3.utils.toWei('0.01'), '0x')
|
||||
.send({
|
||||
from: user.address,
|
||||
@ -135,31 +126,8 @@ describe('erc to erc', () => {
|
||||
console.error(e)
|
||||
})
|
||||
|
||||
// Send a trivial transaction to generate a new block since the watcher
|
||||
// is configured to wait 1 confirmation block
|
||||
await generateNewBlock(homeWeb3, user.address)
|
||||
|
||||
// The bridge should create a new transaction with a CollectedSignatures
|
||||
// event so we generate another trivial transaction
|
||||
await promiseRetry(
|
||||
async retry => {
|
||||
const lastBlockNumber = await homeWeb3.eth.getBlockNumber()
|
||||
if (lastBlockNumber >= depositTx.blockNumber + 2) {
|
||||
await generateNewBlock(homeWeb3, user.address)
|
||||
} else {
|
||||
retry()
|
||||
}
|
||||
},
|
||||
{
|
||||
forever: true,
|
||||
factor: 1,
|
||||
minTimeout: 500
|
||||
}
|
||||
)
|
||||
|
||||
// check that balance increases
|
||||
await promiseRetry(async retry => {
|
||||
await generateNewBlock(homeWeb3, user.address)
|
||||
await uniformRetry(async retry => {
|
||||
const balance = await erc20Token.methods.balanceOf(user.address).call()
|
||||
if (toBN(balance).lte(toBN(originalBalance))) {
|
||||
retry()
|
||||
|
@ -10,7 +10,7 @@ const {
|
||||
foreignRPC
|
||||
} = require('../../e2e-commons/constants.json')
|
||||
const { ERC677_BRIDGE_TOKEN_ABI, FOREIGN_ERC_TO_NATIVE_ABI, SAI_TOP, HOME_ERC_TO_NATIVE_ABI } = require('../../commons')
|
||||
const { generateNewBlock } = require('../../e2e-commons/utils')
|
||||
const { uniformRetry, sleep } = require('../../e2e-commons/utils')
|
||||
const { setRequiredSignatures } = require('./utils')
|
||||
|
||||
const homeWeb3 = new Web3(new Web3.providers.HttpProvider(homeRPC.URL))
|
||||
@ -80,14 +80,9 @@ describe('erc to native', () => {
|
||||
console.error(e)
|
||||
})
|
||||
|
||||
// Send a trivial transaction to generate a new block since the watcher
|
||||
// is configured to wait 1 confirmation block
|
||||
await generateNewBlock(foreignWeb3, user.address)
|
||||
|
||||
// check that balance increases
|
||||
await promiseRetry(async (retry, number) => {
|
||||
const balance = await homeWeb3.eth.getBalance(user.address)
|
||||
await generateNewBlock(foreignWeb3, 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()
|
||||
@ -124,14 +119,9 @@ describe('erc to native', () => {
|
||||
console.error(e)
|
||||
})
|
||||
|
||||
// Send a trivial transaction to generate a new block since the watcher
|
||||
// is configured to wait 1 confirmation block
|
||||
await generateNewBlock(foreignWeb3, user.address)
|
||||
|
||||
// check that balance increases
|
||||
await promiseRetry(async (retry, number) => {
|
||||
const balance = await homeWeb3.eth.getBalance(user.address)
|
||||
await generateNewBlock(foreignWeb3, user.address)
|
||||
// retry at least 4 times to check transfer is not double processed by the two watchers
|
||||
if (toBN(balance).lte(toBN(AfterMigrateBalance)) || number < 4) {
|
||||
retry()
|
||||
@ -156,14 +146,9 @@ describe('erc to native', () => {
|
||||
console.error(e)
|
||||
})
|
||||
|
||||
// Send a trivial transaction to generate a new block since the watcher
|
||||
// is configured to wait 1 confirmation block
|
||||
await generateNewBlock(foreignWeb3, user.address)
|
||||
|
||||
// check that balance increases
|
||||
await promiseRetry(async (retry, number) => {
|
||||
const balance = await homeWeb3.eth.getBalance(user.address)
|
||||
await generateNewBlock(foreignWeb3, user.address)
|
||||
// retry at least 4 times to check transfer is not double processed by the two watchers
|
||||
if (toBN(balance).lte(toBN(afterMigrateAndTransferBalance)) || number < 4) {
|
||||
retry()
|
||||
@ -203,12 +188,8 @@ describe('erc to native', () => {
|
||||
console.error(e)
|
||||
})
|
||||
|
||||
// Send a trivial transaction to generate a new block since the watcher
|
||||
// is configured to wait 1 confirmation block
|
||||
await generateNewBlock(foreignWeb3, user.address)
|
||||
|
||||
// check that balance increases
|
||||
await promiseRetry(async retry => {
|
||||
await uniformRetry(async retry => {
|
||||
const balance = await homeWeb3.eth.getBalance(user.address)
|
||||
const secondUserbalance = await homeWeb3.eth.getBalance(secondUser.address)
|
||||
assert(toBN(balance).lte(toBN(originalBalanceOnHome)), 'User balance should be the same')
|
||||
@ -230,12 +211,8 @@ describe('erc to native', () => {
|
||||
console.error(e)
|
||||
})
|
||||
|
||||
// Send a trivial transaction to generate a new block since the watcher
|
||||
// is configured to wait 1 confirmation block
|
||||
await generateNewBlock(foreignWeb3, user.address)
|
||||
|
||||
// check that balance increases
|
||||
await promiseRetry(async retry => {
|
||||
await uniformRetry(async retry => {
|
||||
const balance = await homeWeb3.eth.getBalance(user.address)
|
||||
if (toBN(balance).lte(toBN(originalBalanceOnHome))) {
|
||||
retry()
|
||||
@ -260,12 +237,8 @@ describe('erc to native', () => {
|
||||
gas: '1000000'
|
||||
})
|
||||
|
||||
// Send a trivial transaction to generate a new block since the watcher
|
||||
// is configured to wait 1 confirmation block
|
||||
await generateNewBlock(foreignWeb3, user.address)
|
||||
|
||||
// check that balance increases
|
||||
await promiseRetry(async retry => {
|
||||
await uniformRetry(async retry => {
|
||||
const balance = await homeWeb3.eth.getBalance(user.address)
|
||||
if (toBN(balance).lte(toBN(originalBalanceOnHome))) {
|
||||
retry()
|
||||
@ -290,9 +263,9 @@ describe('erc to native', () => {
|
||||
gas: '1000000'
|
||||
})
|
||||
|
||||
await generateNewBlock(foreignWeb3, user.address)
|
||||
await sleep(2000)
|
||||
|
||||
await promiseRetry(async retry => {
|
||||
await uniformRetry(async retry => {
|
||||
const userBalance = await homeWeb3.eth.getBalance(user.address)
|
||||
const updatedBridgeErc20TokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||
|
||||
@ -351,12 +324,8 @@ describe('erc to native', () => {
|
||||
console.error(e)
|
||||
})
|
||||
|
||||
// Send a trivial transaction to generate a new block since the watcher
|
||||
// is configured to wait 1 confirmation block
|
||||
await generateNewBlock(foreignWeb3, user.address)
|
||||
|
||||
// check that balance increases
|
||||
await promiseRetry(async retry => {
|
||||
await uniformRetry(async retry => {
|
||||
const secondUserbalance = await homeWeb3.eth.getBalance(secondUser.address)
|
||||
const updatedBridgeErc20TokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||
const userbalance = await homeWeb3.eth.getBalance(user.address)
|
||||
@ -401,7 +370,7 @@ describe('erc to native', () => {
|
||||
|
||||
const valueToTransfer = foreignWeb3.utils.toWei('1', 'ether')
|
||||
|
||||
await generateNewBlock(foreignWeb3, user.address)
|
||||
await sleep(2000)
|
||||
|
||||
// this transfer won't trigger a call to swap tokens
|
||||
await halfDuplexToken.methods.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, valueToTransfer).send({
|
||||
@ -409,10 +378,6 @@ describe('erc to native', () => {
|
||||
gas: '1000000'
|
||||
})
|
||||
|
||||
// Send a trivial transaction to generate a new block since the watcher
|
||||
// is configured to wait 1 confirmation block
|
||||
await generateNewBlock(foreignWeb3, user.address)
|
||||
|
||||
// check that transfer and swap are not processed in the next blocks.
|
||||
await promiseRetry(async (retry, number) => {
|
||||
const balanceOnHome = await homeWeb3.eth.getBalance(user.address)
|
||||
@ -428,9 +393,6 @@ describe('erc to native', () => {
|
||||
)
|
||||
assert(toBN(currentBridgeErc20TokenBalance).eq(toBN(bridgeErc20TokenBalance)), 'erc20 balance should not change')
|
||||
|
||||
// generate new blocks
|
||||
await generateNewBlock(foreignWeb3, user.address)
|
||||
|
||||
// after several retries, the state is corrects
|
||||
if (number < 4) {
|
||||
retry()
|
||||
@ -450,9 +412,9 @@ describe('erc to native', () => {
|
||||
gas: '1000000'
|
||||
})
|
||||
|
||||
await generateNewBlock(foreignWeb3, user.address)
|
||||
await sleep(2000)
|
||||
|
||||
await promiseRetry(async retry => {
|
||||
await uniformRetry(async retry => {
|
||||
const userBalance = await homeWeb3.eth.getBalance(user.address)
|
||||
const updatedBridgeErc20TokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||
|
||||
@ -487,7 +449,7 @@ describe('erc to native', () => {
|
||||
assert(!toBN(balance).isZero(), 'Account should have tokens')
|
||||
|
||||
// send transaction to home bridge
|
||||
const depositTx = await homeWeb3.eth.sendTransaction({
|
||||
await homeWeb3.eth.sendTransaction({
|
||||
from: user.address,
|
||||
to: COMMON_HOME_BRIDGE_ADDRESS,
|
||||
gasPrice: '1',
|
||||
@ -495,35 +457,99 @@ describe('erc to native', () => {
|
||||
value: homeWeb3.utils.toWei('0.01')
|
||||
})
|
||||
|
||||
// Send a trivial transaction to generate a new block since the watcher
|
||||
// is configured to wait 1 confirmation block
|
||||
await generateNewBlock(homeWeb3, user.address)
|
||||
|
||||
// The bridge should create a new transaction with a CollectedSignatures
|
||||
// event so we generate another trivial transaction
|
||||
await promiseRetry(
|
||||
async retry => {
|
||||
const lastBlockNumber = await homeWeb3.eth.getBlockNumber()
|
||||
if (lastBlockNumber >= depositTx.blockNumber + 2) {
|
||||
await generateNewBlock(homeWeb3, user.address)
|
||||
} else {
|
||||
retry()
|
||||
}
|
||||
},
|
||||
{
|
||||
forever: true,
|
||||
factor: 1,
|
||||
minTimeout: 500
|
||||
}
|
||||
)
|
||||
|
||||
// check that balance increases
|
||||
await promiseRetry(async retry => {
|
||||
await generateNewBlock(homeWeb3, user.address)
|
||||
await uniformRetry(async retry => {
|
||||
const balance = await erc20Token.methods.balanceOf(user.address).call()
|
||||
if (toBN(balance).lte(toBN(originalBalance))) {
|
||||
retry()
|
||||
}
|
||||
})
|
||||
})
|
||||
it('should not invest dai when chai token is disabled', async () => {
|
||||
const bridgeDaiTokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||
|
||||
await foreignBridge.methods.setMinDaiTokenBalance(foreignWeb3.utils.toWei('2', 'ether')).send({
|
||||
from: validator.address,
|
||||
gas: '1000000'
|
||||
}) // set min limit for automatic investment to 2*2 dai
|
||||
|
||||
const valueToTransfer = foreignWeb3.utils.toWei('5', 'ether')
|
||||
|
||||
// this transfer won't trigger a call to convert to chai
|
||||
await erc20Token.methods.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, valueToTransfer).send({
|
||||
from: user.address,
|
||||
gas: '1000000'
|
||||
})
|
||||
|
||||
await promiseRetry(async (retry, number) => {
|
||||
if (number < 4) {
|
||||
retry()
|
||||
} else {
|
||||
const updatedBridgeDaiTokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||
assert(
|
||||
toBN(bridgeDaiTokenBalance)
|
||||
.add(toBN(valueToTransfer))
|
||||
.eq(toBN(updatedBridgeDaiTokenBalance)),
|
||||
'Dai tokens should not be when chai is disabled'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
it('should invest dai after enough tokens are collected on bridge account', async () => {
|
||||
await foreignBridge.methods.initializeChaiToken().send({
|
||||
from: validator.address,
|
||||
gas: '1000000'
|
||||
}) // initialize chai token
|
||||
await foreignBridge.methods.setMinDaiTokenBalance('0').send({
|
||||
from: validator.address,
|
||||
gas: '1000000'
|
||||
}) // set investing limit to 0
|
||||
await foreignBridge.methods.convertDaiToChai().send({
|
||||
from: validator.address,
|
||||
gas: '1000000'
|
||||
}) // convert all existing dai tokens on bridge account to chai, in order to start from zero balance
|
||||
await foreignBridge.methods.setMinDaiTokenBalance(foreignWeb3.utils.toWei('2', 'ether')).send({
|
||||
from: validator.address,
|
||||
gas: '1000000'
|
||||
}) // set investing limit to 2 dai, automatically invest should happen after 4 dai
|
||||
|
||||
const valueToTransfer = foreignWeb3.utils.toWei('3', 'ether')
|
||||
|
||||
// this transfer won't trigger a call to convert to chai
|
||||
await erc20Token.methods.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, valueToTransfer).send({
|
||||
from: user.address,
|
||||
gas: '1000000'
|
||||
})
|
||||
|
||||
await promiseRetry(async (retry, number) => {
|
||||
if (number < 4) {
|
||||
retry()
|
||||
} else {
|
||||
const bridgeDaiTokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||
assert(
|
||||
valueToTransfer === bridgeDaiTokenBalance,
|
||||
'Dai tokens should not be invested automatically before twice limit is reached'
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
// this transfer will trigger call to convert to chai
|
||||
await erc20Token.methods.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, valueToTransfer).send({
|
||||
from: user.address,
|
||||
gas: '1000000'
|
||||
})
|
||||
|
||||
await promiseRetry(async retry => {
|
||||
const updatedBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||
if (toBN(updatedBalance).gte(toBN(valueToTransfer).add(toBN(valueToTransfer)))) {
|
||||
retry()
|
||||
} else {
|
||||
const updatedBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||
assert(
|
||||
toBN(updatedBalance).eq(toBN(foreignWeb3.utils.toWei('2', 'ether'))),
|
||||
'Dai bridge balance should be equal to limit'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -1,6 +1,5 @@
|
||||
const Web3 = require('web3')
|
||||
const assert = require('assert')
|
||||
const promiseRetry = require('promise-retry')
|
||||
const {
|
||||
user,
|
||||
validator,
|
||||
@ -14,7 +13,7 @@ const {
|
||||
foreignRPC
|
||||
} = require('../../e2e-commons/constants.json')
|
||||
const { ERC677_BRIDGE_TOKEN_ABI, HOME_NATIVE_TO_ERC_ABI, FOREIGN_NATIVE_TO_ERC_ABI } = require('../../commons')
|
||||
const { generateNewBlock } = require('../../e2e-commons/utils')
|
||||
const { uniformRetry, sleep } = require('../../e2e-commons/utils')
|
||||
const { setRequiredSignatures } = require('./utils')
|
||||
|
||||
const homeWeb3 = new Web3(new Web3.providers.HttpProvider(homeRPC.URL))
|
||||
@ -24,6 +23,8 @@ const { toBN } = foreignWeb3.utils
|
||||
const COMMON_HOME_BRIDGE_ADDRESS = nativeToErcBridge.home
|
||||
const COMMON_FOREIGN_BRIDGE_ADDRESS = nativeToErcBridge.foreign
|
||||
|
||||
const validatorAddresses = [validator.address, secondValidator.address, thirdValidator.address]
|
||||
|
||||
homeWeb3.eth.accounts.wallet.add(user.privateKey)
|
||||
homeWeb3.eth.accounts.wallet.add(validator.privateKey)
|
||||
homeWeb3.eth.accounts.wallet.add(secondUser.privateKey)
|
||||
@ -43,8 +44,6 @@ const token = new foreignWeb3.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, nativeToErcB
|
||||
const homeBridge = new homeWeb3.eth.Contract(HOME_NATIVE_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
||||
const foreignBridge = new foreignWeb3.eth.Contract(FOREIGN_NATIVE_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
|
||||
const sleep = timeout => new Promise(res => setTimeout(res, timeout))
|
||||
|
||||
describe('native to erc', () => {
|
||||
before(async () => {
|
||||
// Set 2 required signatures for home bridge
|
||||
@ -75,7 +74,7 @@ describe('native to erc', () => {
|
||||
assert(toBN(balance).isZero(), 'Account should not have tokens yet')
|
||||
|
||||
// send transaction to home chain
|
||||
const depositTx = await homeWeb3.eth.sendTransaction({
|
||||
await homeWeb3.eth.sendTransaction({
|
||||
from: user.address,
|
||||
to: COMMON_HOME_BRIDGE_ADDRESS,
|
||||
gasPrice: '1',
|
||||
@ -83,30 +82,8 @@ describe('native to erc', () => {
|
||||
value: '1000000000000000000'
|
||||
})
|
||||
|
||||
// Send a trivial transaction to generate a new block since the watcher
|
||||
// is configured to wait 1 confirmation block
|
||||
await generateNewBlock(homeWeb3, user.address)
|
||||
|
||||
// The bridge should create a new transaction with a CollectedSignatures
|
||||
// event so we generate another trivial transaction
|
||||
await promiseRetry(
|
||||
async retry => {
|
||||
const lastBlockNumber = await homeWeb3.eth.getBlockNumber()
|
||||
if (lastBlockNumber >= depositTx.blockNumber + 2) {
|
||||
await generateNewBlock(homeWeb3, user.address)
|
||||
} else {
|
||||
retry()
|
||||
}
|
||||
},
|
||||
{
|
||||
forever: true,
|
||||
factor: 1,
|
||||
minTimeout: 500
|
||||
}
|
||||
)
|
||||
|
||||
// check that account has tokens in the foreign chain
|
||||
await promiseRetry(async retry => {
|
||||
await uniformRetry(async retry => {
|
||||
const balance = await token.methods.balanceOf(user.address).call()
|
||||
if (toBN(balance).isZero()) {
|
||||
retry()
|
||||
@ -128,12 +105,8 @@ describe('native to erc', () => {
|
||||
console.error(e)
|
||||
})
|
||||
|
||||
// Send a trivial transaction to generate a new block since the watcher
|
||||
// is configured to wait 1 confirmation block
|
||||
await generateNewBlock(foreignWeb3, user.address)
|
||||
|
||||
// check that balance increases
|
||||
await promiseRetry(async retry => {
|
||||
await uniformRetry(async retry => {
|
||||
const balance = await homeWeb3.eth.getBalance(user.address)
|
||||
if (toBN(balance).lte(toBN(originalBalance))) {
|
||||
retry()
|
||||
@ -150,8 +123,9 @@ describe('native to erc', () => {
|
||||
await sendAllBalance(homeWeb3, secondValidator.address, thirdUser.address)
|
||||
await sendAllBalance(homeWeb3, thirdValidator.address, fourthUser.address)
|
||||
|
||||
const nonces = await Promise.all(validatorAddresses.map(homeWeb3.eth.getTransactionCount))
|
||||
// send transaction to home chain
|
||||
const depositTx = await homeWeb3.eth.sendTransaction({
|
||||
await homeWeb3.eth.sendTransaction({
|
||||
from: user.address,
|
||||
to: COMMON_HOME_BRIDGE_ADDRESS,
|
||||
gasPrice: '1',
|
||||
@ -159,41 +133,20 @@ describe('native to erc', () => {
|
||||
value: '1000000000000000000'
|
||||
})
|
||||
|
||||
// Send a Tx to generate a new block
|
||||
await generateNewBlock(homeWeb3, user.address)
|
||||
|
||||
// wait two seconds, no new blocks should have been generated
|
||||
await sleep(2000)
|
||||
const lastBlockNumber = await homeWeb3.eth.getBlockNumber()
|
||||
const newNonces = await Promise.all(validatorAddresses.map(homeWeb3.eth.getTransactionCount))
|
||||
const balance = toBN(await token.methods.balanceOf(user.address).call())
|
||||
assert(lastBlockNumber === depositTx.blockNumber + 1, "Shouldn't have emitted a new block")
|
||||
assert.deepStrictEqual(nonces, newNonces, "Shouldn't sent new tx")
|
||||
assert(originalBalance.eq(balance), "Token balance shouldn't have changed")
|
||||
|
||||
// send funds back to validator
|
||||
await sendAllBalance(homeWeb3, secondUser.address, validator.address)
|
||||
await sendAllBalance(homeWeb3, thirdUser.address, secondValidator.address)
|
||||
const sendBalanceBackTx = await sendAllBalance(homeWeb3, fourthUser.address, thirdValidator.address)
|
||||
|
||||
// expect Deposit event to be processed
|
||||
await promiseRetry(
|
||||
async retry => {
|
||||
const lastBlockNumber = await homeWeb3.eth.getBlockNumber()
|
||||
// check that a new block was created since the last transaction
|
||||
if (lastBlockNumber >= sendBalanceBackTx.blockNumber + 1) {
|
||||
await generateNewBlock(homeWeb3, user.address)
|
||||
} else {
|
||||
retry()
|
||||
}
|
||||
},
|
||||
{
|
||||
forever: true,
|
||||
factor: 1,
|
||||
minTimeout: 500
|
||||
}
|
||||
)
|
||||
await sendAllBalance(homeWeb3, fourthUser.address, thirdValidator.address)
|
||||
|
||||
// check that token balance was incremented in foreign chain
|
||||
await promiseRetry(async retry => {
|
||||
await uniformRetry(async retry => {
|
||||
const balance = toBN(await token.methods.balanceOf(user.address).call())
|
||||
if (!balance.gt(originalBalance)) {
|
||||
retry()
|
||||
@ -209,7 +162,7 @@ describe('native to erc', () => {
|
||||
await sendAllBalance(foreignWeb3, validator.address, secondUser.address)
|
||||
await sendAllBalance(foreignWeb3, secondValidator.address, thirdUser.address)
|
||||
await sendAllBalance(foreignWeb3, thirdValidator.address, fourthUser.address)
|
||||
const foreignBlockNumber = await foreignWeb3.eth.getBlockNumber()
|
||||
const nonces = await Promise.all(validatorAddresses.map(foreignWeb3.eth.getTransactionCount))
|
||||
|
||||
// send transaction to home chain
|
||||
await homeWeb3.eth.sendTransaction({
|
||||
@ -220,30 +173,10 @@ describe('native to erc', () => {
|
||||
value: '1000000000000000000'
|
||||
})
|
||||
|
||||
// Send a Tx to generate a new block
|
||||
const lastHomeTx = await generateNewBlock(homeWeb3, user.address)
|
||||
|
||||
// wait for the deposit to be processed
|
||||
await promiseRetry(
|
||||
async retry => {
|
||||
const lastBlockNumber = await homeWeb3.eth.getBlockNumber()
|
||||
if (lastBlockNumber >= lastHomeTx.blockNumber + 1) {
|
||||
await generateNewBlock(homeWeb3, user.address)
|
||||
} else {
|
||||
retry()
|
||||
}
|
||||
},
|
||||
{
|
||||
forever: true,
|
||||
factor: 1,
|
||||
minTimeout: 500
|
||||
}
|
||||
)
|
||||
|
||||
// tokens shouldn't be generated in the foreign chain because the validator doesn't have funds
|
||||
await sleep(2000)
|
||||
const lastForeignBlockNumber = await foreignWeb3.eth.getBlockNumber()
|
||||
assert(lastForeignBlockNumber === foreignBlockNumber, "Shouldn't have emitted a new block")
|
||||
const newNonces = await Promise.all(validatorAddresses.map(foreignWeb3.eth.getTransactionCount))
|
||||
assert.deepStrictEqual(nonces, newNonces, "Shouldn't sent new tx")
|
||||
|
||||
// send funds back to validator
|
||||
await sendAllBalance(foreignWeb3, secondUser.address, validator.address)
|
||||
@ -251,7 +184,7 @@ describe('native to erc', () => {
|
||||
await sendAllBalance(foreignWeb3, fourthUser.address, thirdValidator.address)
|
||||
|
||||
// check that account has tokens in the foreign chain
|
||||
await promiseRetry(async retry => {
|
||||
await uniformRetry(async retry => {
|
||||
const balance = toBN(await token.methods.balanceOf(user.address).call())
|
||||
if (balance.eq(originalBalance)) {
|
||||
retry()
|
||||
|
@ -117,8 +117,18 @@ There are two options to run the TokenBridge processes:
|
||||
|
||||
### Docker
|
||||
|
||||
- While running the bridge containers for the first time use `ORACLE_VALIDATOR_ADDRESS=<validator address> ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=<validator address private key> docker-compose up -d --build`
|
||||
- For further launches use `ORACLE_VALIDATOR_ADDRESS=<validator address> ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=<validator address private key> docker-compose up --detach`
|
||||
- While running the bridge containers for the first time use
|
||||
```
|
||||
env ORACLE_VALIDATOR_ADDRESS=<validator address> \
|
||||
env ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=<validator address private key> \
|
||||
docker-compose -f docker-compose-build.yml -f docker-compose.yml up -d --build
|
||||
```
|
||||
- For further launches (or in case of usage an official docker image) use
|
||||
```
|
||||
env ORACLE_VALIDATOR_ADDRESS=<validator address> \
|
||||
env ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=<validator address private key> \
|
||||
docker-compose up --d
|
||||
```
|
||||
|
||||
All [watcher](#watcher) & [sender](#sender) services launch when `docker-compose` is called.
|
||||
|
||||
@ -144,6 +154,18 @@ In case you need to reset your bridge or setup a new one (with different configu
|
||||
|
||||
See the [UI instructions](../ui/README.md) to configure and use the optional Bridge UI.
|
||||
|
||||
### Build the image without running the oracle
|
||||
|
||||
To build the image change the directory:
|
||||
```
|
||||
cd oracle
|
||||
```
|
||||
|
||||
And run the docker composer:
|
||||
```
|
||||
docker-compose -f docker-compose-build.yml build
|
||||
```
|
||||
|
||||
## Rollback the Last Processed Block in Redis
|
||||
|
||||
If the bridge does not handle an event properly (i.e. a transaction stalls due to a low gas price), the Redis DB can be rolled back. You must identify which watcher needs to re-run. For example, if the validator signatures were collected but the transaction with signatures was not sent to the Foreign network, the `collected-signatures` watcher must look at the block where the corresponding `CollectedSignatures` event was raised.
|
||||
|
20
oracle/config/convert-to-chai-worker.config.js
Normal file
20
oracle/config/convert-to-chai-worker.config.js
Normal file
@ -0,0 +1,20 @@
|
||||
const baseConfig = require('./base.config')
|
||||
const { EXIT_CODES } = require('../src/utils/constants')
|
||||
|
||||
const id = `${baseConfig.id}-convert-to-chai`
|
||||
|
||||
const workerRequired = baseConfig.id === 'erc-native'
|
||||
|
||||
if (!workerRequired) {
|
||||
console.error(`Convert to chai 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: 'convert-to-chai',
|
||||
senderQueue: 'foreign',
|
||||
name: `worker-${id}`,
|
||||
id
|
||||
}
|
@ -29,6 +29,11 @@ if (!transferWatcherRequired) {
|
||||
process.exit(EXIT_CODES.WATCHER_NOT_REQUIRED)
|
||||
}
|
||||
|
||||
const workerQueueConfig = {}
|
||||
if (baseConfig.id === 'erc-native') {
|
||||
workerQueueConfig.workerQueue = 'convert-to-chai'
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
...baseConfig.bridgeConfig,
|
||||
...baseConfig.foreignConfig,
|
||||
@ -37,6 +42,7 @@ module.exports = {
|
||||
eventAbi: ERC20_ABI,
|
||||
eventFilter: { to: process.env.COMMON_FOREIGN_BRIDGE_ADDRESS },
|
||||
queue: 'home',
|
||||
...workerQueueConfig,
|
||||
name: `watcher-${id}`,
|
||||
id
|
||||
}
|
||||
|
6
oracle/docker-compose-build.yml
Normal file
6
oracle/docker-compose-build.yml
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
version: '2.4'
|
||||
services:
|
||||
oracle:
|
||||
image: poanetwork/tokenbridge-oracle
|
||||
build: .
|
@ -9,6 +9,7 @@ services:
|
||||
- net_rabbit_bridge_transfer
|
||||
- net_rabbit_bridge_half_duplex_transfer
|
||||
- net_rabbit_bridge_swap_tokens_worker
|
||||
- net_rabbit_bridge_convert_to_chai_worker
|
||||
redis:
|
||||
extends:
|
||||
file: docker-compose.yml
|
||||
@ -75,6 +76,18 @@ services:
|
||||
entrypoint: yarn worker:swap-tokens
|
||||
networks:
|
||||
- net_rabbit_bridge_swap_tokens_worker
|
||||
bridge_convert_to_chai_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:convert-to-chai
|
||||
networks:
|
||||
- net_rabbit_bridge_convert_to_chai_worker
|
||||
bridge_senderhome:
|
||||
extends:
|
||||
file: docker-compose.yml
|
||||
@ -121,3 +134,5 @@ networks:
|
||||
driver: bridge
|
||||
net_rabbit_bridge_senderforeign:
|
||||
driver: bridge
|
||||
net_rabbit_bridge_convert_to_chai_worker:
|
||||
driver: bridge
|
||||
|
@ -11,6 +11,7 @@
|
||||
"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",
|
||||
"sender:home": "./scripts/start-worker.sh sender home-sender",
|
||||
"sender:foreign": "./scripts/start-worker.sh sender foreign-sender",
|
||||
"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'",
|
||||
|
13
oracle/src/utils/chaiUtils.js
Normal file
13
oracle/src/utils/chaiUtils.js
Normal file
@ -0,0 +1,13 @@
|
||||
async function isChaiTokenEnabled(bridgeContract, logger) {
|
||||
logger.debug('Checking Chai availability')
|
||||
try {
|
||||
return await bridgeContract.methods.isChaiTokenEnabled().call()
|
||||
} catch (e) {
|
||||
logger.debug('Method isChaiTokenEnabled is not supported')
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isChaiTokenEnabled
|
||||
}
|
@ -9,6 +9,7 @@ const rpcUrlsManager = require('./services/getRpcUrlsManager')
|
||||
const { getRequiredBlockConfirmations, getEvents } = require('./tx/web3')
|
||||
const { checkHTTPS, watchdog } = require('./utils/utils')
|
||||
const { EXIT_CODES } = require('./utils/constants')
|
||||
const { isChaiTokenEnabled } = require('./utils/chaiUtils')
|
||||
|
||||
if (process.argv.length < 3) {
|
||||
logger.error('Please check the number of arguments, config file was not provided')
|
||||
@ -157,6 +158,15 @@ async function getLastBlockToProcess() {
|
||||
return lastBlockNumber.sub(requiredBlockConfirmations)
|
||||
}
|
||||
|
||||
async function isWorkerNeeded() {
|
||||
switch (config.id) {
|
||||
case 'erc-native-transfer':
|
||||
return isChaiTokenEnabled(bridgeContract, logger)
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
async function main({ sendToQueue, sendToWorker }) {
|
||||
try {
|
||||
await checkConditions()
|
||||
@ -186,7 +196,7 @@ async function main({ sendToQueue, sendToWorker }) {
|
||||
logger.info(`Found ${events.length} ${config.event} events`)
|
||||
|
||||
if (events.length) {
|
||||
if (sendToWorker) {
|
||||
if (sendToWorker && (await isWorkerNeeded())) {
|
||||
await sendToWorker({ blockNumber: toBlock.toString() })
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ const { connectWorkerToQueue } = require('./services/amqpClient')
|
||||
const config = require(path.join('../config/', process.argv[2]))
|
||||
|
||||
const swapTokens = require('./workers/swapTokens')(config)
|
||||
const convertToChai = require('./workers/convertToChai')(config)
|
||||
|
||||
async function initialize() {
|
||||
try {
|
||||
@ -39,6 +40,8 @@ async function initialize() {
|
||||
async function run(blockNumber) {
|
||||
if (config.id === 'erc-native-swap-tokens') {
|
||||
return swapTokens(blockNumber)
|
||||
} else if (config.id === 'erc-native-convert-to-chai') {
|
||||
return convertToChai(blockNumber)
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
|
80
oracle/src/workers/convertToChai.js
Normal file
80
oracle/src/workers/convertToChai.js
Normal file
@ -0,0 +1,80 @@
|
||||
require('../../env')
|
||||
const { HttpListProviderError } = require('http-list-provider')
|
||||
const rootLogger = require('../services/logger')
|
||||
const { web3Foreign } = require('../services/web3')
|
||||
|
||||
const { BRIDGE_VALIDATORS_ABI } = require('../../../commons')
|
||||
|
||||
let validatorContract = null
|
||||
|
||||
function convertToChaiBuilder(config) {
|
||||
const foreignBridge = new web3Foreign.eth.Contract(config.foreignBridgeAbi, config.foreignBridgeAddress)
|
||||
return async function convertToChai(blockNumber) {
|
||||
const txToSend = []
|
||||
|
||||
const logger = rootLogger.child({
|
||||
blockNumber: blockNumber.toString()
|
||||
})
|
||||
|
||||
logger.debug(`Starting convert to chai 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(`Convert to chai discarded because is not validator duty`)
|
||||
return txToSend
|
||||
}
|
||||
|
||||
logger.debug(`Checking if dai token balance is above the threshold`)
|
||||
const daiNeedsToBeInvested = await foreignBridge.methods.isDaiNeedsToBeInvested().call()
|
||||
|
||||
if (!daiNeedsToBeInvested) {
|
||||
logger.info(`Convert to chai discarded because dai balance is below the threshold or chai token is not set`)
|
||||
return txToSend
|
||||
}
|
||||
|
||||
let gasEstimate
|
||||
|
||||
try {
|
||||
logger.debug(`Estimate gas`)
|
||||
gasEstimate = await foreignBridge.methods.convertDaiToChai().estimateGas({
|
||||
from: config.validatorAddress
|
||||
})
|
||||
|
||||
logger.debug({ gasEstimate }, 'Gas estimated')
|
||||
} catch (e) {
|
||||
if (e instanceof HttpListProviderError) {
|
||||
const errorMsg = 'RPC Connection Error: convertToChai Gas Estimate cannot be obtained.'
|
||||
logger.error(e, errorMsg)
|
||||
throw new Error(errorMsg)
|
||||
} else {
|
||||
logger.error(e, 'Unknown error while processing transaction')
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
// generate data
|
||||
const data = await foreignBridge.methods.convertDaiToChai().encodeABI()
|
||||
|
||||
// push to job
|
||||
txToSend.push({
|
||||
data,
|
||||
gasEstimate,
|
||||
transactionReference: `convert to chai operation for block number ${blockNumber.toString()}`,
|
||||
to: config.foreignBridgeAddress
|
||||
})
|
||||
|
||||
return txToSend
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = convertToChaiBuilder
|
@ -136,6 +136,14 @@
|
||||
"0x0": "0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359",
|
||||
"0x1": "0xc4c7497fbe1a886841a195a5d622cd60053c1376"
|
||||
}
|
||||
},
|
||||
"06af07097c9eeb7fd685c692751d5c66db49c215": {
|
||||
"balance": "0",
|
||||
"code": "0x6080604052600436106100565763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633b4da69f811461005b5780636c25b3461461008e578063be22f546146100ce575b600080fd5b34801561006757600080fd5b5061008c73ffffffffffffffffffffffffffffffffffffffff6004351660243561010c565b005b34801561009a57600080fd5b506100bc73ffffffffffffffffffffffffffffffffffffffff600435166101c5565b60408051918252519081900360200190f35b3480156100da57600080fd5b506100e36101cc565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b60008054604080517f23b872dd00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101859052905173ffffffffffffffffffffffffffffffffffffffff909216926323b872dd926064808401936020939083900390910190829087803b15801561018d57600080fd5b505af11580156101a1573d6000803e3d6000fd5b505050506040513d60208110156101b757600080fd5b505060018054909101905550565b5060015490565b60005473ffffffffffffffffffffffffffffffffffffffff16815600a165627a7a72305820d01d11b7ea4dad7896e3fbb5d06966bf715276ebd69a35990fa39c3158ca489d0029",
|
||||
"storage": {
|
||||
"0x0": "0x7cC4B1851c35959D34e635A470F6b5C43bA3C9c9",
|
||||
"0x1": "0x38d7ea4c68000"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -3,7 +3,7 @@ const { By } = require('selenium-webdriver/lib/by')
|
||||
const { Page } = require('./Page.js')
|
||||
const { homeRPC, foreignRPC } = require('../e2e-commons/constants.json')
|
||||
|
||||
const IDMetaMask = 'nkbihfbeogaeaoehlefnkodbefgpgknn'
|
||||
const IDMetaMask = 'dapggmdndodedfoaljbglbkaicfpmkkm'
|
||||
const URL = 'chrome-extension://' + IDMetaMask + '//popup.html'
|
||||
const buttonSubmit = By.className('confirm btn-green')
|
||||
const buttonAccept = By.xpath('//*[@id="app-content"]/div/div[4]/div/button')
|
||||
|
Loading…
Reference in New Issue
Block a user