Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1122daf9a1 | ||
|
|
12269d7426 | ||
|
|
683fa0728d | ||
|
|
dd2075c351 | ||
|
|
ce29b95729 | ||
|
|
eb1069497a | ||
|
|
0228fc7d5f | ||
|
|
f8d85b14de | ||
|
|
5fa9d21246 | ||
|
|
611b8c539d | ||
|
|
389cea3c39 | ||
|
|
fbce0fc035 | ||
|
|
621b20d070 | ||
|
|
48752e8575 | ||
|
|
4efda98f2b | ||
|
|
aff8b777c5 | ||
|
|
74293959f3 | ||
|
|
46daeb6815 | ||
|
|
44ca0d71ce | ||
|
|
fbeb878cdb | ||
|
|
d17ea2ad2b | ||
|
|
4cc87ef61a | ||
|
|
125b66b86d | ||
|
|
7a0ed3f699 | ||
|
|
4e04f2ae1f | ||
|
|
dc377aeb9b | ||
|
|
48dd53622c | ||
|
|
6fe63ae9f4 | ||
|
|
4954c859c3 | ||
|
|
27f059db94 | ||
|
|
686c415a5c | ||
|
|
2e1b022512 | ||
|
|
f252ed2618 | ||
|
|
bea91c0e6e |
@@ -1,382 +0,0 @@
|
||||
version: 2.1
|
||||
|
||||
orbs:
|
||||
tokenbridge-orb:
|
||||
commands:
|
||||
install-chrome:
|
||||
steps:
|
||||
- run:
|
||||
name: Update dpkg
|
||||
command: |
|
||||
sudo apt-get clean
|
||||
sudo apt-get update
|
||||
sudo apt-get install dpkg
|
||||
- run:
|
||||
name: Install Chrome
|
||||
command: |
|
||||
wget -O chrome.deb https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_77.0.3865.120-1_amd64.deb
|
||||
sudo dpkg -i chrome.deb
|
||||
install-node:
|
||||
steps:
|
||||
- run:
|
||||
name: Install Node
|
||||
command: |
|
||||
export NVM_DIR="/opt/circleci/.nvm"
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
||||
|
||||
nvm install 10.16.3 && nvm alias default 10.16.3
|
||||
|
||||
echo 'export NVM_DIR="/opt/circleci/.nvm"' >> $BASH_ENV
|
||||
echo ' [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $BASH_ENV
|
||||
install-yarn:
|
||||
steps:
|
||||
- run:
|
||||
name: Install Yarn
|
||||
command: |
|
||||
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
|
||||
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
|
||||
sudo apt-get update && sudo apt-get -y install yarn
|
||||
wait-for-oracle:
|
||||
parameters:
|
||||
redis-key:
|
||||
type: string
|
||||
steps:
|
||||
- run:
|
||||
name: Install redis tools
|
||||
command: sudo apt-get install -y redis-tools
|
||||
- run:
|
||||
name: Wait for the Oracle to start
|
||||
command: |
|
||||
set +e
|
||||
i=0
|
||||
while [[ $(redis-cli GET << parameters.redis-key >> ) ]]; do
|
||||
((i++))
|
||||
if [ "$i" -gt 30 ]
|
||||
then
|
||||
exit -1
|
||||
fi
|
||||
|
||||
echo "Sleeping..."
|
||||
sleep 3
|
||||
done
|
||||
init-repo:
|
||||
steps:
|
||||
- checkout
|
||||
- run: git submodule update --init
|
||||
executors:
|
||||
docker-node:
|
||||
docker:
|
||||
- image: circleci/node:10.15
|
||||
machine-with-dlc:
|
||||
machine:
|
||||
image: ubuntu-1604:202007-01
|
||||
docker_layer_caching: true
|
||||
classic-machine-without-dlc:
|
||||
machine:
|
||||
image: circleci/classic:latest
|
||||
machine-without-dlc:
|
||||
machine:
|
||||
image: ubuntu-1604:202007-01
|
||||
|
||||
jobs:
|
||||
initialize:
|
||||
executor: tokenbridge-orb/docker-node
|
||||
steps:
|
||||
- tokenbridge-orb/init-repo
|
||||
- restore_cache:
|
||||
name: Restore Yarn Package Cache
|
||||
keys:
|
||||
- yarn-{{ checksum "package.json" }}-{{ checksum "yarn.lock" }}
|
||||
- run: git submodule status > submodule.status
|
||||
- restore_cache:
|
||||
name: Restore contracts submodule with compiled contracts
|
||||
keys:
|
||||
- contracts-{{ checksum "submodule.status" }}
|
||||
- run: yarn install --frozen-lockfile
|
||||
- save_cache:
|
||||
name: Save Yarn Package Cache
|
||||
key: yarn-{{ checksum "package.json" }}-{{ checksum "yarn.lock" }}
|
||||
paths:
|
||||
- ~/.cache/yarn
|
||||
- run: touch install_deploy.log; test -d contracts/build/contracts || yarn install:deploy &> install_deploy.log
|
||||
- store_artifacts:
|
||||
path: install_deploy.log
|
||||
- run: test -d contracts/build/contracts || yarn compile:contracts
|
||||
- save_cache:
|
||||
name: Save contracts submodule with compiled contracts
|
||||
key: contracts-{{ checksum "submodule.status" }}
|
||||
paths:
|
||||
- contracts
|
||||
- save_cache:
|
||||
name: Save initialized project for subsequent jobs
|
||||
key: initialize-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/project
|
||||
initialize-root:
|
||||
executor: tokenbridge-orb/docker-node
|
||||
steps:
|
||||
- checkout
|
||||
- run: sudo su - -c 'export CI=true && cd /home/circleci/project && yarn initialize && yarn test'
|
||||
build:
|
||||
executor: tokenbridge-orb/docker-node
|
||||
steps:
|
||||
- restore_cache:
|
||||
key: initialize-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn run build
|
||||
lint:
|
||||
executor: tokenbridge-orb/docker-node
|
||||
steps:
|
||||
- restore_cache:
|
||||
key: initialize-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn run lint
|
||||
test:
|
||||
executor: tokenbridge-orb/docker-node
|
||||
steps:
|
||||
- restore_cache:
|
||||
key: initialize-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn run test
|
||||
build-e2e-images:
|
||||
executor: tokenbridge-orb/machine-without-dlc
|
||||
steps:
|
||||
- tokenbridge-orb/init-repo
|
||||
- run:
|
||||
command: |
|
||||
docker login -u ${DOCKER_LOGIN} -p ${DOCKER_PASSWORD}
|
||||
cd e2e-commons
|
||||
docker-compose build oracle monitor ui alm e2e molecule_runner
|
||||
docker-compose push oracle monitor ui alm e2e molecule_runner
|
||||
oracle-e2e:
|
||||
executor: tokenbridge-orb/machine-without-dlc
|
||||
steps:
|
||||
- tokenbridge-orb/init-repo
|
||||
- run: ./oracle-e2e/run-tests.sh
|
||||
ui-e2e:
|
||||
executor: tokenbridge-orb/machine-without-dlc
|
||||
steps:
|
||||
- tokenbridge-orb/install-node
|
||||
- tokenbridge-orb/install-yarn
|
||||
- tokenbridge-orb/install-chrome
|
||||
- restore_cache:
|
||||
key: initialize-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn run ui-e2e
|
||||
monitor-e2e:
|
||||
executor: tokenbridge-orb/machine-without-dlc
|
||||
steps:
|
||||
- tokenbridge-orb/init-repo
|
||||
- run: ./monitor-e2e/run-tests.sh
|
||||
alm-e2e:
|
||||
executor: tokenbridge-orb/machine-without-dlc
|
||||
steps:
|
||||
- tokenbridge-orb/install-node
|
||||
- tokenbridge-orb/install-yarn
|
||||
- restore_cache:
|
||||
key: initialize-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn run alm-e2e
|
||||
cover:
|
||||
executor: tokenbridge-orb/docker-node
|
||||
steps:
|
||||
- restore_cache:
|
||||
key: initialize-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn workspace ui run coverage
|
||||
- run: yarn workspace ui run coveralls
|
||||
deployment-oracle:
|
||||
executor: tokenbridge-orb/machine-without-dlc
|
||||
steps:
|
||||
- tokenbridge-orb/init-repo
|
||||
- run:
|
||||
name: Run the scenario
|
||||
command: deployment-e2e/molecule.sh oracle
|
||||
no_output_timeout: 40m
|
||||
deployment-ui:
|
||||
executor: tokenbridge-orb/machine-without-dlc
|
||||
steps:
|
||||
- tokenbridge-orb/init-repo
|
||||
- run:
|
||||
name: Run the scenario
|
||||
command: deployment-e2e/molecule.sh ui
|
||||
no_output_timeout: 40m
|
||||
deployment-monitor:
|
||||
executor: tokenbridge-orb/machine-without-dlc
|
||||
steps:
|
||||
- tokenbridge-orb/init-repo
|
||||
- run:
|
||||
name: Run the scenario
|
||||
command: deployment-e2e/molecule.sh monitor
|
||||
no_output_timeout: 40m
|
||||
deployment-repo:
|
||||
executor: tokenbridge-orb/machine-without-dlc
|
||||
steps:
|
||||
- tokenbridge-orb/init-repo
|
||||
- run:
|
||||
name: Run the scenario
|
||||
command: deployment-e2e/molecule.sh repo
|
||||
no_output_timeout: 40m
|
||||
deployment-multiple:
|
||||
executor: tokenbridge-orb/machine-without-dlc
|
||||
steps:
|
||||
- tokenbridge-orb/init-repo
|
||||
- run:
|
||||
name: Run the scenario
|
||||
command: deployment-e2e/molecule.sh multiple
|
||||
no_output_timeout: 40m
|
||||
ultimate:
|
||||
executor: tokenbridge-orb/classic-machine-without-dlc
|
||||
parameters:
|
||||
scenario-name:
|
||||
description: "Molecule scenario name used to create the infrastructure"
|
||||
type: string
|
||||
redis-key:
|
||||
description: "Redis key checked for non-emptiness to assert if Oracle is running"
|
||||
type: string
|
||||
ui-e2e-grep:
|
||||
description: "Mocha grep string used to run ui-e2e tests specific to given type of bridge"
|
||||
default: ''
|
||||
type: string
|
||||
oracle-e2e-script:
|
||||
description: "Yarn script string used to run oracle-e2e tests specific to given type of bridge"
|
||||
default: ''
|
||||
type: string
|
||||
steps:
|
||||
- tokenbridge-orb/install-node
|
||||
- tokenbridge-orb/install-chrome
|
||||
- tokenbridge-orb/install-yarn
|
||||
- restore_cache:
|
||||
key: initialize-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
name: Prepare the infrastructure
|
||||
command: e2e-commons/up.sh deploy << parameters.scenario-name >> blocks
|
||||
no_output_timeout: 50m
|
||||
- tokenbridge-orb/wait-for-oracle:
|
||||
redis-key: << parameters.redis-key >>
|
||||
- when:
|
||||
condition: << parameters.ui-e2e-grep >>
|
||||
steps:
|
||||
- run:
|
||||
name: Run the ui-e2e tests
|
||||
command: |
|
||||
nvm use default;
|
||||
cd ui-e2e; yarn mocha -g "<< parameters.ui-e2e-grep >>" -b ./test.js
|
||||
- when:
|
||||
condition: << parameters.oracle-e2e-script >>
|
||||
steps:
|
||||
- run:
|
||||
name: Run the oracle-e2e tests
|
||||
command: cd e2e-commons && docker-compose run e2e yarn workspace oracle-e2e run << parameters.oracle-e2e-script >>
|
||||
workflows:
|
||||
tokenbridge:
|
||||
jobs:
|
||||
- initialize
|
||||
- initialize-root:
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
- build:
|
||||
requires:
|
||||
- initialize
|
||||
- lint:
|
||||
requires:
|
||||
- initialize
|
||||
- test:
|
||||
requires:
|
||||
- initialize
|
||||
- cover:
|
||||
requires:
|
||||
- initialize
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
- build-e2e-images
|
||||
- oracle-e2e:
|
||||
requires:
|
||||
- build-e2e-images
|
||||
- ui-e2e:
|
||||
requires:
|
||||
- build-e2e-images
|
||||
- initialize
|
||||
- monitor-e2e:
|
||||
requires:
|
||||
- build-e2e-images
|
||||
- alm-e2e:
|
||||
requires:
|
||||
- build-e2e-images
|
||||
- initialize
|
||||
- deployment-oracle:
|
||||
requires:
|
||||
- build-e2e-images
|
||||
- deployment-ui:
|
||||
requires:
|
||||
- build-e2e-images
|
||||
- deployment-monitor:
|
||||
requires:
|
||||
- build-e2e-images
|
||||
- deployment-repo:
|
||||
requires:
|
||||
- build-e2e-images
|
||||
- deployment-multiple:
|
||||
requires:
|
||||
- build-e2e-images
|
||||
- ultimate:
|
||||
requires:
|
||||
- build-e2e-images
|
||||
- initialize
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
name: "ultimate: native to erc"
|
||||
scenario-name: native-to-erc
|
||||
redis-key: native-erc-collected-signatures:lastProcessedBlock
|
||||
ui-e2e-grep: "NATIVE TO ERC"
|
||||
- ultimate:
|
||||
requires:
|
||||
- build-e2e-images
|
||||
- initialize
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
name: "ultimate: erc to native"
|
||||
scenario-name: erc-to-native
|
||||
redis-key: erc-native-collected-signatures:lastProcessedBlock
|
||||
ui-e2e-grep: "ERC TO NATIVE"
|
||||
- ultimate:
|
||||
requires:
|
||||
- build-e2e-images
|
||||
- initialize
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
name: "ultimate: erc to erc"
|
||||
scenario-name: erc-to-erc
|
||||
redis-key: erc-erc-collected-signatures:lastProcessedBlock
|
||||
ui-e2e-grep: "ERC TO ERC"
|
||||
- ultimate:
|
||||
requires:
|
||||
- build-e2e-images
|
||||
- initialize
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
name: "ultimate: amb"
|
||||
scenario-name: amb
|
||||
redis-key: amb-collected-signatures:lastProcessedBlock
|
||||
oracle-e2e-script: "amb"
|
||||
- ultimate:
|
||||
requires:
|
||||
- build-e2e-images
|
||||
- initialize
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
name: "ultimate: amb stake erc to erc"
|
||||
scenario-name: ultimate-amb-stake-erc-to-erc
|
||||
redis-key: amb-collected-signatures:lastProcessedBlock
|
||||
ui-e2e-grep: "AMB-STAKE-ERC-TO-ERC"
|
||||
@@ -8,9 +8,17 @@
|
||||
**/docs
|
||||
**/*.md
|
||||
|
||||
monitor/**/*.env*
|
||||
oracle/**/*.env*
|
||||
!**/.env.example
|
||||
|
||||
contracts/test
|
||||
contracts/build
|
||||
oracle/test
|
||||
monitor/test
|
||||
monitor/responses
|
||||
monitor/cache/*
|
||||
commons/test
|
||||
oracle/**/*.png
|
||||
oracle/**/*.jpg
|
||||
audit
|
||||
|
||||
253
.github/workflows/main.yml
vendored
Normal file
253
.github/workflows/main.yml
vendored
Normal file
@@ -0,0 +1,253 @@
|
||||
name: tokenbridge
|
||||
|
||||
on: [push]
|
||||
|
||||
env:
|
||||
DOCKER_REGISTRY: docker.pkg.github.com
|
||||
DOCKER_REPO: poanetwork/tokenbridge
|
||||
DOCKER_IMAGE_BASE: docker.pkg.github.com/poanetwork/tokenbridge
|
||||
|
||||
jobs:
|
||||
initialize:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
cache_key: ${{ steps.get_cache_key.outputs.cache_key }}
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Set cache key
|
||||
id: get_cache_key
|
||||
run: |
|
||||
git submodule status > submodule.status
|
||||
echo "::set-output name=cache_key::cache-repo-${{ hashFiles('yarn.lock', 'package.json', 'submodule.status') }}"
|
||||
- uses: actions/cache@v2
|
||||
id: cache-repo
|
||||
with:
|
||||
path: |
|
||||
**/node_modules
|
||||
contracts/build
|
||||
key: ${{ steps.get_cache_key.outputs.cache_key }}
|
||||
- name: Install dependencies and compile contracts
|
||||
if: ${{ !steps.cache-repo.outputs.cache-hit }}
|
||||
run: |
|
||||
yarn install --frozen-lockfile
|
||||
yarn run install:deploy
|
||||
yarn run compile:contracts
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- initialize
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
task: [build, lint, test]
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions/cache@v2
|
||||
id: cache-repo
|
||||
with:
|
||||
path: |
|
||||
**/node_modules
|
||||
contracts/build
|
||||
key: ${{ needs.initialize.outputs.cache_key }}
|
||||
- name: yarn run ${{ matrix.task }}
|
||||
run: ${{ steps.cache-repo.outputs.cache-hit }} && yarn run ${{ matrix.task }}
|
||||
ui-coverage:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- initialize
|
||||
if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags')
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions/cache@v2
|
||||
id: cache-repo
|
||||
with:
|
||||
path: |
|
||||
**/node_modules
|
||||
contracts/build
|
||||
key: ${{ needs.initialize.outputs.cache_key }}
|
||||
- name: yarn workspace ui run coverage
|
||||
run: ${{ steps.cache-repo.outputs.cache-hit }} && yarn workspace ui run coverage
|
||||
- uses: coverallsapp/github-action@master
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
path-to-lcov: ./ui/coverage/lcov.info
|
||||
build-e2e-images:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Evaluate e2e docker images tags
|
||||
run: |
|
||||
git submodule status > submodule.status
|
||||
echo "E2E_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}" >> $GITHUB_ENV
|
||||
echo "ORACLE_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}" >> $GITHUB_ENV
|
||||
echo "MONITOR_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}" >> $GITHUB_ENV
|
||||
echo "UI_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'ui') }}" >> $GITHUB_ENV
|
||||
echo "ALM_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}" >> $GITHUB_ENV
|
||||
- name: Rebuild and push updated images
|
||||
run: |
|
||||
function check_if_image_exists() {
|
||||
curl -fsSlL -H 'Authorization: bearer ${{ github.token }}' "https://${DOCKER_REGISTRY}/v2/${DOCKER_REPO}/tokenbridge-e2e-$1/manifests/$2" > /dev/null
|
||||
}
|
||||
updated=()
|
||||
if ! check_if_image_exists e2e ${E2E_TAG}; then updated+=("e2e"); fi
|
||||
if ! check_if_image_exists oracle ${ORACLE_TAG}; then updated+=("oracle"); fi
|
||||
if ! check_if_image_exists monitor ${MONITOR_TAG}; then updated+=("monitor"); fi
|
||||
if ! check_if_image_exists ui ${UI_TAG}; then updated+=("ui"); fi
|
||||
if ! check_if_image_exists alm ${ALM_TAG}; then updated+=("alm"); fi
|
||||
if [ ${#updated[@]} -gt 0 ]; then
|
||||
echo "Updated services: ${updated[@]}"
|
||||
cd e2e-commons
|
||||
docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }}
|
||||
docker-compose build ${updated[@]}
|
||||
docker-compose push ${updated[@]}
|
||||
else
|
||||
echo "Nothing relevant was changed in the source"
|
||||
fi
|
||||
build-molecule-runner:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Evaluate e2e molecule runner tag
|
||||
run: echo "MOLECULE_RUNNER_TAG=${{ hashFiles('./deployment-e2e/Dockerfile') }}" >> $GITHUB_ENV
|
||||
- name: Rebuild and push molecule runner e2e image
|
||||
run: |
|
||||
function check_if_image_exists() {
|
||||
curl -fsSlL -H 'Authorization: bearer ${{ github.token }}' "https://${DOCKER_REGISTRY}/v2/${DOCKER_REPO}/tokenbridge-e2e-$1/manifests/$2" > /dev/null
|
||||
}
|
||||
if check_if_image_exists molecule_runner ${MOLECULE_RUNNER_TAG}; then
|
||||
echo "Image already exists"
|
||||
else
|
||||
cd e2e-commons
|
||||
docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }}
|
||||
docker-compose build molecule_runner
|
||||
docker-compose push molecule_runner
|
||||
fi
|
||||
e2e:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- initialize
|
||||
- build-e2e-images
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
task: [oracle-e2e, monitor-e2e, alm-e2e, 'ui-e2e:ci']
|
||||
include:
|
||||
- task: alm-e2e
|
||||
use-cache: true
|
||||
- task: 'ui-e2e:ci'
|
||||
use-cache: true
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Evaluate e2e docker images tags
|
||||
run: |
|
||||
git submodule status > submodule.status
|
||||
echo "E2E_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}" >> $GITHUB_ENV
|
||||
echo "ORACLE_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}" >> $GITHUB_ENV
|
||||
echo "MONITOR_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}" >> $GITHUB_ENV
|
||||
echo "UI_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'ui') }}" >> $GITHUB_ENV
|
||||
echo "ALM_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}" >> $GITHUB_ENV
|
||||
- if: ${{ matrix.use-cache }}
|
||||
uses: actions/cache@v2
|
||||
id: cache-repo
|
||||
with:
|
||||
path: |
|
||||
**/node_modules
|
||||
contracts/build
|
||||
key: ${{ needs.initialize.outputs.cache_key }}
|
||||
- name: Login to docker registry
|
||||
run: docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }}
|
||||
- name: yarn run ${{ matrix.task }}
|
||||
run: ${{ !matrix.use-cache || steps.cache-repo.outputs.cache-hit }} && yarn run ${{ matrix.task }}
|
||||
deployment:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- build-molecule-runner
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
task: [oracle, ui, monitor, multiple, repo]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Evaluate e2e molecule runner tag
|
||||
run: echo "MOLECULE_RUNNER_TAG=${{ hashFiles('./deployment-e2e/Dockerfile') }}" >> $GITHUB_ENV
|
||||
- name: Login to docker registry
|
||||
run: docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }}
|
||||
- run: deployment-e2e/molecule.sh ${{ matrix.task }}
|
||||
ultimate:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- initialize
|
||||
- build-e2e-images
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/tags')
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
task: [amb, erc-to-erc, erc-to-native, native-to-erc, amb-stake-erc-to-erc]
|
||||
include:
|
||||
- task: erc-to-erc
|
||||
ui-e2e-grep: 'ERC TO ERC'
|
||||
- task: erc-to-native
|
||||
ui-e2e-grep: 'ERC TO NATIVE'
|
||||
- task: native-to-erc
|
||||
ui-e2e-grep: 'NATIVE TO ERC'
|
||||
- task: amb-stake-erc-to-erc
|
||||
ui-e2e-grep: 'AMB-STAKE-ERC-TO-ERC'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Evaluate e2e docker images tags
|
||||
run: |
|
||||
git submodule status > submodule.status
|
||||
echo "E2E_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}" >> $GITHUB_ENV
|
||||
echo "ORACLE_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}" >> $GITHUB_ENV
|
||||
echo "MONITOR_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}" >> $GITHUB_ENV
|
||||
echo "UI_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'ui') }}" >> $GITHUB_ENV
|
||||
echo "ALM_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}" >> $GITHUB_ENV
|
||||
echo "MOLECULE_RUNNER_TAG=${{ hashFiles('./deployment-e2e/Dockerfile') }}" >> $GITHUB_ENV
|
||||
- uses: actions/cache@v2
|
||||
id: cache-repo
|
||||
with:
|
||||
path: |
|
||||
**/node_modules
|
||||
contracts/build
|
||||
key: ${{ needs.initialize.outputs.cache_key }}
|
||||
- name: Login to docker registry
|
||||
run: docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }}
|
||||
- name: Deploy contracts
|
||||
run: ${{ steps.cache-repo.outputs.cache-hit }} && e2e-commons/up.sh deploy blocks
|
||||
- name: Pull e2e oracle image
|
||||
run: docker-compose -f ./e2e-commons/docker-compose.yml pull oracle
|
||||
- name: Deploy oracle and ui
|
||||
run: deployment-e2e/molecule.sh ultimate-${{ matrix.task }}
|
||||
- name: Reset docker socket permissions
|
||||
run: sudo chown -R $USER:docker /var/run/docker.sock
|
||||
- name: Run ui e2e tests
|
||||
if: ${{ matrix.ui-e2e-grep }}
|
||||
run: cd ui-e2e && xvfb-run yarn mocha -g "${{ matrix.ui-e2e-grep }}" -b ./test.js
|
||||
- name: Run oracle e2e tests
|
||||
if: ${{ !matrix.ui-e2e-grep }}
|
||||
run: docker-compose -f ./e2e-commons/docker-compose.yml run e2e yarn workspace oracle-e2e run ${{ matrix.task }}
|
||||
10
.gitignore
vendored
10
.gitignore
vendored
@@ -10,11 +10,8 @@ dist
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
*.env*
|
||||
!.env.example
|
||||
.idea
|
||||
.nyc_output
|
||||
logs/
|
||||
@@ -49,5 +46,6 @@ __pycache__
|
||||
|
||||
#monitor
|
||||
monitor/responses/*
|
||||
monitor/configs/*.env
|
||||
monitor/cache/*
|
||||
!monitor/cache/.gitkeep
|
||||
!monitor/.gitkeep
|
||||
|
||||
@@ -12,7 +12,7 @@ COMMON_HOME_GAS_PRICE_SUPPLIER_URL | The URL used to get a JSON response from th
|
||||
COMMON_HOME_GAS_PRICE_SPEED_TYPE | Assuming the gas price oracle responds with the following JSON structure: `{"fast": 20.0, "block_time": 12.834, "health": true, "standard": 6.0, "block_number": 6470469, "instant": 71.0, "slow": 1.889}`, this parameter specifies the desirable transaction speed. The speed type can be omitted when `COMMON_HOME_GAS_PRICE_SUPPLIER_URL` is not used. | `instant` / `fast` / `standard` / `slow`
|
||||
COMMON_HOME_GAS_PRICE_FALLBACK | The gas price (in Wei) that is used if both the oracle and the fall back gas price specified in the Home Bridge contract are not available. | integer
|
||||
COMMON_HOME_GAS_PRICE_FACTOR | A value that will multiply the gas price of the oracle to convert it to gwei. If the oracle API returns gas prices in gwei then this can be set to `1`. Also, it could be used to intentionally pay more gas than suggested by the oracle to guarantee the transaction verification. E.g. `1.25` or `1.5`. | integer
|
||||
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL | The URL used to get a JSON response from the gas price prediction oracle for the Foreign network. The provided gas price is used to send the validator's transactions to the RPC node. If the Foreign network is Ethereum Foundation mainnet, the oracle URL can be: https://gasprice.poa.network. Otherwise this parameter can be omitted. | URL
|
||||
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL | The URL used to get a JSON response from the gas price prediction oracle for the Foreign network. The provided gas price is used to send the validator's transactions to the RPC node. If the Foreign network is Ethereum Foundation mainnet, the oracle URL can be: https://gasprice.poa.network. Otherwise this parameter can be omitted. Set to `gas-price-oracle` if you want to use npm `gas-price-oracle` package for retrieving gas price from multiple sources. | URL
|
||||
COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE | Assuming the gas price oracle responds with the following JSON structure: `{"fast": 20.0, "block_time": 12.834, "health": true, "standard": 6.0, "block_number": 6470469, "instant": 71.0, "slow": 1.889}`, this parameter specifies the desirable transaction speed. The speed type can be omitted when `COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL`is not used. | `instant` / `fast` / `standard` / `slow`
|
||||
COMMON_FOREIGN_GAS_PRICE_FALLBACK | The gas price (in Wei) used if both the oracle and fall back gas price specified in the Foreign Bridge contract are not available. | integer
|
||||
COMMON_FOREIGN_GAS_PRICE_FACTOR | A value that will multiply the gas price of the oracle to convert it to gwei. If the oracle API returns gas prices in gwei then this can be set to `1`. Also, it could be used to intentionally pay more gas than suggested by the oracle to guarantee the transaction verification. E.g. `1.25` or `1.5`. | integer
|
||||
@@ -22,7 +22,7 @@ COMMON_FOREIGN_GAS_PRICE_FACTOR | A value that will multiply the gas price of th
|
||||
|
||||
name | description | value
|
||||
--- | --- | ---
|
||||
ORACLE_BRIDGE_MODE | The bridge mode. The bridge starts listening to a different set of events based on this parameter. | NATIVE_TO_ERC / ERC_TO_ERC / ERC_TO_NATIVE
|
||||
ORACLE_BRIDGE_MODE | The bridge mode. The bridge starts listening to a different set of events based on this parameter. | NATIVE_TO_ERC / ERC_TO_ERC / ERC_TO_NATIVE / ARBITRARY_MESSAGE
|
||||
ORACLE_ALLOW_HTTP_FOR_RPC | **Only use in test environments - must be omitted in production environments.**. If this parameter is specified and set to `yes`, RPC URLs can be specified in form of HTTP links. A warning that the connection is insecure will be written to the logs. | `yes` / `no`
|
||||
ORACLE_HOME_RPC_POLLING_INTERVAL | The interval in milliseconds used to request the RPC node in the Home network for new blocks. The interval should match the average production time for a new block. | integer
|
||||
ORACLE_FOREIGN_RPC_POLLING_INTERVAL | The interval in milliseconds used to request the RPC node in the Foreign network for new blocks. The interval should match the average production time for a new block. | integer
|
||||
@@ -37,6 +37,11 @@ ORACLE_MAX_PROCESSING_TIME | The workers processes will be killed if this amount
|
||||
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY | The private key of the bridge validator used to sign confirmations before sending transactions to the bridge contracts. The validator account is calculated automatically from the private key. Every bridge instance (set of watchers and senders) must have its own unique private key. The specified private key is used to sign transactions on both sides of the bridge. | hexidecimal without "0x"
|
||||
ORACLE_VALIDATOR_ADDRESS | The public address of the bridge validator | hexidecimal with "0x"
|
||||
ORACLE_TX_REDUNDANCY | If set to `true`, instructs oracle to send `eth_sendRawTransaction` requests through all available RPC urls defined in `COMMON_HOME_RPC_URL` and `COMMON_FOREIGN_RPC_URL` variables instead of using first available one
|
||||
ORACLE_HOME_TO_FOREIGN_ALLOWANCE_LIST | Filename with a list of addresses, separated by newlines. If set, determines the privileged set of accounts whose requests will be automatically processed by the CollectedSignatures watcher. | string
|
||||
ORACLE_HOME_TO_FOREIGN_BLOCK_LIST | Filename with a list of addresses, separated by newlines. If set, determines the blocked set of accounts whose requests will not be automatically processed by the CollectedSignatures watcher. Has a lower priority than the `ORACLE_HOME_TO_FOREIGN_ALLOWANCE_LIST` | string
|
||||
ORACLE_HOME_TO_FOREIGN_CHECK_SENDER | If set to `true`, instructs the oracle to do an extra check for transaction origin in the block/allowance list. `false` by default. | `true` / `false`
|
||||
ORACLE_ALWAYS_RELAY_SIGNATURES | If set to `true`, the oracle will always relay signatures even if it was not the last who finilized the signatures collecting process. The default is `false`. | `true` / `false`
|
||||
ORACLE_RPC_REQUEST_TIMEOUT | Timeout in milliseconds for a single RPC request. Default value is `ORACLE_*_RPC_POLLING_INTERVAL * 2`. | integer
|
||||
|
||||
|
||||
## UI configuration
|
||||
@@ -73,4 +78,7 @@ MONITOR_VALIDATOR_FOREIGN_TX_LIMIT | Average gas usage of a transaction sent by
|
||||
MONITOR_TX_NUMBER_THRESHOLD | If estimated number of transaction is equal to or below this value, the monitor will report that the validator has less funds than it is required. | integer
|
||||
MONITOR_PORT | The port for the Monitor. | integer
|
||||
MONITOR_BRIDGE_NAME | The name to be used in the url path for the bridge | string
|
||||
MONITOR_CACHE_EVENTS | If set to true, monitor will cache obtained events for other workers runs
|
||||
MONITOR_CACHE_EVENTS | If set to true, monitor will cache obtained events for other workers runs | `true` / `false`
|
||||
MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST | File with a list of addresses, separated by newlines. If set, determines the privileged set of accounts whose requests should be automatically processed by the CollectedSignatures watcher. | string
|
||||
MONITOR_HOME_TO_FOREIGN_BLOCK_LIST | File with a list of addresses, separated by newlines. If set, determines the set of accounts whose requests should be marked as unclaimed. Has a lower priority than the `MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST`. | string
|
||||
MONITOR_HOME_TO_FOREIGN_CHECK_SENDER | If set to `true`, instructs the oracle to do an extra check for transaction origin in the block/allowance list. `false` by default. | `true` / `false`
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:8 as contracts
|
||||
FROM node:10 as contracts
|
||||
|
||||
WORKDIR /mono
|
||||
|
||||
@@ -11,11 +11,12 @@ COPY ./contracts/truffle-config.js ./
|
||||
COPY ./contracts/contracts ./contracts
|
||||
RUN npm run compile
|
||||
|
||||
FROM node:8
|
||||
FROM node:10
|
||||
|
||||
WORKDIR /mono
|
||||
COPY package.json .
|
||||
COPY --from=contracts /mono/contracts/build ./contracts/build
|
||||
COPY commons/package.json ./commons/
|
||||
COPY oracle-e2e/package.json ./oracle-e2e/
|
||||
COPY monitor-e2e/package.json ./monitor-e2e/
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[](https://circleci.com/gh/poanetwork/tokenbridge)
|
||||

|
||||
[](https://gitter.im/poanetwork/poa-bridge?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://www.gnu.org/licenses/lgpl-3.0)
|
||||
|
||||
@@ -110,4 +110,4 @@ This project is licensed under the GNU Lesser General Public License v3.0. See t
|
||||
|
||||
## References
|
||||
|
||||
* [TokenBridge Documentation](http://www.tokenbridge.net/)
|
||||
* [TokenBridge Documentation](https://docs.tokenbridge.net/)
|
||||
|
||||
@@ -19,6 +19,6 @@
|
||||
"eslint-plugin-jest": "^23.18.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.9"
|
||||
"node": ">= 10.18"
|
||||
}
|
||||
}
|
||||
|
||||
0
alm-e2e/run-tests.sh
Normal file → Executable file
0
alm-e2e/run-tests.sh
Normal file → Executable file
@@ -1,4 +1,4 @@
|
||||
FROM node:8 as contracts
|
||||
FROM node:10 as contracts
|
||||
|
||||
WORKDIR /mono
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ export const CONFIRMATIONS_STATUS_DESCRIPTION_HOME: { [key: string]: string } =
|
||||
EXECUTION_PENDING:
|
||||
'The specified transaction was included in a block\nand the validators collected signatures. The\nvalidator’s transaction with collected signatures was\nsent but is not yet added to a block.',
|
||||
EXECUTION_WAITING:
|
||||
'The specified transaction was included in a block\nand the validators collected signatures. Either\n1. One of the validators is waiting for chain finalization.\n2. A validator skipped its duty to relay signatures.\nCheck status again after a few blocks. If the issue still persists contact to the validators by messaging on %linkhttps://forum.poa.network/c/support',
|
||||
'The specified transaction was included in a block\nand the validators collected signatures. Either\n1. One of the validators is waiting for chain finalization.\n2. A validator skipped its duty to relay signatures.\n3. The execution transaction is still pending (e.g. due to the gas price spike).\nCheck status again after a few blocks. If the issue still persists contact to the validators by messaging on %linkhttps://forum.poa.network/c/support',
|
||||
FAILED:
|
||||
'The specified transaction was included in a block,\nbut transactions with signatures sent by a majority of\nvalidators failed. The cross-chain relay request will\nnot be processed. Contact to the validators by\nmessaging on %linkhttps://forum.poa.network/c/support',
|
||||
PENDING:
|
||||
|
||||
@@ -351,7 +351,7 @@ describe('getConfirmationsForTx', () => {
|
||||
{ validator: validator1, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS },
|
||||
{ validator: validator2, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS },
|
||||
{ validator: validator3, status: VALIDATOR_CONFIRMATION_STATUS.FAILED, txHash: '0x123', timestamp: 123 },
|
||||
{ validator: validator4, status: VALIDATOR_CONFIRMATION_STATUS.UNDEFINED }
|
||||
{ validator: validator4, status: VALIDATOR_CONFIRMATION_STATUS.NOT_REQUIRED }
|
||||
])
|
||||
)
|
||||
expect(setResult.mock.calls[1][0]).toEqual(
|
||||
|
||||
Binary file not shown.
@@ -2600,6 +2600,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
|
||||
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
|
||||
|
||||
"@types/mocha@^7.0.2":
|
||||
version "7.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-7.0.2.tgz#b17f16cf933597e10d6d78eae3251e692ce8b0ce"
|
||||
integrity sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==
|
||||
|
||||
"@types/node@*", "@types/node@>= 8":
|
||||
version "13.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.0.tgz#390ea202539c61c8fa6ba4428b57e05bc36dc47b"
|
||||
@@ -3215,6 +3220,11 @@ are-we-there-yet@~1.1.2:
|
||||
delegates "^1.0.0"
|
||||
readable-stream "^2.0.6"
|
||||
|
||||
arg@^4.1.0:
|
||||
version "4.1.3"
|
||||
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
|
||||
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
|
||||
|
||||
argparse@^1.0.7:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
|
||||
@@ -3340,6 +3350,11 @@ assert@^1.1.1:
|
||||
object-assign "^4.1.1"
|
||||
util "0.10.3"
|
||||
|
||||
assertion-error@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b"
|
||||
integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==
|
||||
|
||||
assign-symbols@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
|
||||
@@ -3435,6 +3450,13 @@ axios@^0.18.0:
|
||||
follow-redirects "1.5.10"
|
||||
is-buffer "^2.0.2"
|
||||
|
||||
axios@^0.19.0:
|
||||
version "0.19.2"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
|
||||
integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==
|
||||
dependencies:
|
||||
follow-redirects "1.5.10"
|
||||
|
||||
axobject-query@^2.0.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.1.2.tgz#2bdffc0371e643e5f03ba99065d5179b9ca79799"
|
||||
@@ -3799,6 +3821,11 @@ browser-resolve@^1.11.3:
|
||||
dependencies:
|
||||
resolve "1.1.7"
|
||||
|
||||
browser-stdout@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
|
||||
integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
|
||||
|
||||
browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48"
|
||||
@@ -4188,6 +4215,18 @@ caseless@~0.12.0:
|
||||
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
|
||||
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
|
||||
|
||||
chai@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5"
|
||||
integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==
|
||||
dependencies:
|
||||
assertion-error "^1.1.0"
|
||||
check-error "^1.0.2"
|
||||
deep-eql "^3.0.1"
|
||||
get-func-name "^2.0.0"
|
||||
pathval "^1.1.0"
|
||||
type-detect "^4.0.5"
|
||||
|
||||
chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.1, chalk@^2.4.2:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||
@@ -4213,6 +4252,11 @@ chardet@^0.7.0:
|
||||
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
|
||||
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
|
||||
|
||||
check-error@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
|
||||
integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=
|
||||
|
||||
check-types@^8.0.3:
|
||||
version "8.0.3"
|
||||
resolved "https://registry.yarnpkg.com/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552"
|
||||
@@ -4446,6 +4490,11 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@2.15.1:
|
||||
version "2.15.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
|
||||
integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==
|
||||
|
||||
commander@2.17.x:
|
||||
version "2.17.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
|
||||
@@ -5241,6 +5290,13 @@ dedent@^0.7.0:
|
||||
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
|
||||
integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=
|
||||
|
||||
deep-eql@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df"
|
||||
integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==
|
||||
dependencies:
|
||||
type-detect "^4.0.0"
|
||||
|
||||
deep-equal@^1.0.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a"
|
||||
@@ -5413,6 +5469,16 @@ diff-sequences@^24.9.0:
|
||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5"
|
||||
integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==
|
||||
|
||||
diff@3.5.0:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
|
||||
integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
|
||||
|
||||
diff@^4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
|
||||
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
|
||||
|
||||
diffie-hellman@^5.0.0:
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
|
||||
@@ -7093,6 +7159,11 @@ get-caller-file@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||
|
||||
get-func-name@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
|
||||
integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=
|
||||
|
||||
get-own-enumerable-property-symbols@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664"
|
||||
@@ -7227,6 +7298,18 @@ glob-to-regexp@^0.3.0:
|
||||
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
|
||||
integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=
|
||||
|
||||
glob@7.1.2:
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
|
||||
integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.0.4"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
|
||||
version "7.1.6"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
|
||||
@@ -7360,6 +7443,11 @@ graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.
|
||||
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
|
||||
integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=
|
||||
|
||||
growl@1.10.5:
|
||||
version "1.10.5"
|
||||
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
|
||||
integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
|
||||
|
||||
growly@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
|
||||
@@ -7518,6 +7606,11 @@ hdkey@^1.1.1:
|
||||
safe-buffer "^5.1.1"
|
||||
secp256k1 "^3.0.1"
|
||||
|
||||
he@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
|
||||
integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
|
||||
|
||||
he@1.2.x:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
||||
@@ -9592,6 +9685,11 @@ make-dir@^2.0.0, make-dir@^2.1.0:
|
||||
pify "^4.0.1"
|
||||
semver "^5.6.0"
|
||||
|
||||
make-error@^1.1.1:
|
||||
version "1.3.6"
|
||||
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
|
||||
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
|
||||
|
||||
make-fetch-happen@^5.0.0:
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz#aa8387104f2687edca01c8687ee45013d02d19bd"
|
||||
@@ -9943,6 +10041,11 @@ minimist-options@^3.0.1:
|
||||
arrify "^1.0.1"
|
||||
is-plain-obj "^1.1.0"
|
||||
|
||||
minimist@0.0.8:
|
||||
version "0.0.8"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
|
||||
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
|
||||
|
||||
minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||
@@ -10007,6 +10110,13 @@ mkdirp@*:
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||
|
||||
mkdirp@0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
|
||||
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
|
||||
dependencies:
|
||||
minimist "0.0.8"
|
||||
|
||||
mkdirp@^0.5.0, mkdirp@^0.5.1:
|
||||
version "0.5.5"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
|
||||
@@ -10021,6 +10131,23 @@ mkdirp@~0.5.0, mkdirp@~0.5.1:
|
||||
dependencies:
|
||||
minimist "^1.2.5"
|
||||
|
||||
mocha@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6"
|
||||
integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==
|
||||
dependencies:
|
||||
browser-stdout "1.3.1"
|
||||
commander "2.15.1"
|
||||
debug "3.1.0"
|
||||
diff "3.5.0"
|
||||
escape-string-regexp "1.0.5"
|
||||
glob "7.1.2"
|
||||
growl "1.10.5"
|
||||
he "1.1.1"
|
||||
minimatch "3.0.4"
|
||||
mkdirp "0.5.1"
|
||||
supports-color "5.4.0"
|
||||
|
||||
mock-fs@^4.1.0:
|
||||
version "4.11.0"
|
||||
resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.11.0.tgz#0828107e4b843a6ba855ecebfe3c6e073b69db92"
|
||||
@@ -10967,6 +11094,11 @@ path-type@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
|
||||
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
|
||||
|
||||
pathval@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0"
|
||||
integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA=
|
||||
|
||||
pbkdf2@^3.0.3:
|
||||
version "3.0.17"
|
||||
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6"
|
||||
@@ -13271,6 +13403,14 @@ source-map-support@0.5.6:
|
||||
buffer-from "^1.0.0"
|
||||
source-map "^0.6.0"
|
||||
|
||||
source-map-support@^0.5.17:
|
||||
version "0.5.19"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
|
||||
integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
|
||||
dependencies:
|
||||
buffer-from "^1.0.0"
|
||||
source-map "^0.6.0"
|
||||
|
||||
source-map-support@^0.5.6, source-map-support@~0.5.10, source-map-support@~0.5.12:
|
||||
version "0.5.16"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042"
|
||||
@@ -13712,6 +13852,13 @@ stylis@^3.5.0:
|
||||
resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe"
|
||||
integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==
|
||||
|
||||
supports-color@5.4.0:
|
||||
version "5.4.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54"
|
||||
integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==
|
||||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
supports-color@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
|
||||
@@ -14076,6 +14223,17 @@ tryer@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"
|
||||
integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==
|
||||
|
||||
ts-node@^8.8.2:
|
||||
version "8.10.2"
|
||||
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d"
|
||||
integrity sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==
|
||||
dependencies:
|
||||
arg "^4.1.0"
|
||||
diff "^4.0.1"
|
||||
make-error "^1.1.1"
|
||||
source-map-support "^0.5.17"
|
||||
yn "3.1.1"
|
||||
|
||||
ts-pnp@1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.1.2.tgz#be8e4bfce5d00f0f58e0666a82260c34a57af552"
|
||||
@@ -14122,6 +14280,11 @@ type-check@~0.3.2:
|
||||
dependencies:
|
||||
prelude-ls "~1.1.2"
|
||||
|
||||
type-detect@^4.0.0, type-detect@^4.0.5:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
|
||||
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
|
||||
|
||||
type-fest@^0.3.0:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1"
|
||||
@@ -14167,6 +14330,11 @@ typescript@3.5.3:
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977"
|
||||
integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==
|
||||
|
||||
typescript@^3.5.2:
|
||||
version "3.9.7"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
|
||||
integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
|
||||
|
||||
uglify-js@3.4.x:
|
||||
version "3.4.10"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f"
|
||||
@@ -15481,3 +15649,8 @@ yauzl@^2.4.2:
|
||||
dependencies:
|
||||
buffer-crc32 "~0.2.3"
|
||||
fd-slicer "~1.1.0"
|
||||
|
||||
yn@3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
|
||||
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
],
|
||||
"rules": {
|
||||
"no-unused-expressions": "off",
|
||||
"import/no-extraneous-dependencies": "off"
|
||||
"import/no-extraneous-dependencies": "off",
|
||||
"no-bitwise": "off"
|
||||
},
|
||||
"env": {
|
||||
"mocha": true
|
||||
|
||||
@@ -13,7 +13,6 @@ const REWARDABLE_VALIDATORS_ABI = require('../contracts/build/contracts/Rewardab
|
||||
const HOME_AMB_ABI = require('../contracts/build/contracts/HomeAMB').abi
|
||||
const FOREIGN_AMB_ABI = require('../contracts/build/contracts/ForeignAMB').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 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
|
||||
@@ -136,7 +135,6 @@ module.exports = {
|
||||
OLD_AMB_USER_REQUEST_FOR_AFFIRMATION_ABI,
|
||||
OLD_AMB_USER_REQUEST_FOR_SIGNATURE_ABI,
|
||||
BOX_ABI,
|
||||
SAI_TOP,
|
||||
HOME_STAKE_ERC_TO_ERC_ABI,
|
||||
FOREIGN_STAKE_ERC_TO_ERC_ABI
|
||||
}
|
||||
|
||||
@@ -6,17 +6,30 @@ function addTxHashToData({ encodedData, transactionHash }) {
|
||||
return encodedData.slice(0, 2) + strip0x(transactionHash) + encodedData.slice(2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the datatype byte from the AMB message.
|
||||
* First (the most significant bit) denotes if the message should be forwarded to the manual lane.
|
||||
* @param dataType: number datatype of the received AMB message.
|
||||
* @return {{manualLane: boolean}}
|
||||
*/
|
||||
const decodeAMBDataType = dataType => ({
|
||||
manualLane: (dataType & 128) === 128
|
||||
})
|
||||
|
||||
function parseAMBMessage(message) {
|
||||
message = strip0x(message)
|
||||
|
||||
const messageId = `0x${message.slice(0, 64)}`
|
||||
const sender = `0x${message.slice(64, 104)}`
|
||||
const executor = `0x${message.slice(104, 144)}`
|
||||
const dataType = parseInt(message.slice(156, 158), 16)
|
||||
|
||||
return {
|
||||
sender,
|
||||
executor,
|
||||
messageId
|
||||
messageId,
|
||||
dataType,
|
||||
decodedDataType: decodeAMBDataType(dataType)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"test": "NODE_ENV=test mocha"
|
||||
},
|
||||
"dependencies": {
|
||||
"gas-price-oracle": "^0.1.5",
|
||||
"web3-utils": "1.0.0-beta.34"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
const { toWei, toBN } = require('web3-utils')
|
||||
const { GasPriceOracle } = require('gas-price-oracle')
|
||||
const { BRIDGE_MODES, FEE_MANAGER_MODE, ERC_TYPES } = require('./constants')
|
||||
const { REWARDABLE_VALIDATORS_ABI } = require('./abis')
|
||||
|
||||
const gasPriceOracle = new GasPriceOracle()
|
||||
|
||||
function decodeBridgeMode(bridgeModeHash) {
|
||||
switch (bridgeModeHash) {
|
||||
case '0x92a8d7fe':
|
||||
@@ -161,18 +164,18 @@ const getPastEvents = async (
|
||||
} catch (e) {
|
||||
if (e.message.includes('query returned more than') && toBlock !== 'latest') {
|
||||
const middle = toBN(fromBlock)
|
||||
.add(toBlock)
|
||||
.add(toBN(toBlock))
|
||||
.divRound(toBN(2))
|
||||
const middlePlusOne = middle.add(toBN(1))
|
||||
|
||||
const firstHalfEvents = await getPastEvents(contract, {
|
||||
...options,
|
||||
options,
|
||||
event,
|
||||
fromBlock,
|
||||
toBlock: middle
|
||||
})
|
||||
const secondHalfEvents = await getPastEvents(contract, {
|
||||
...options,
|
||||
options,
|
||||
event,
|
||||
fromBlock: middlePlusOne,
|
||||
toBlock
|
||||
@@ -235,8 +238,13 @@ const normalizeGasPrice = (oracleGasPrice, factor, limits = null) => {
|
||||
// we use built-in 'fetch' on browser side, and `node-fetch` package in Node.
|
||||
const gasPriceFromSupplier = async (fetchFn, options = {}) => {
|
||||
try {
|
||||
const response = await fetchFn()
|
||||
const json = await response.json()
|
||||
let json
|
||||
if (fetchFn) {
|
||||
const response = await fetchFn()
|
||||
json = await response.json()
|
||||
} else {
|
||||
json = await gasPriceOracle.fetchGasPricesOffChain()
|
||||
}
|
||||
const oracleGasPrice = json[options.speedType]
|
||||
|
||||
if (!oracleGasPrice) {
|
||||
|
||||
@@ -65,6 +65,20 @@ const homeV1Abi = [
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function'
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
name: 'requiredBlockConfirmations',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function'
|
||||
}
|
||||
]
|
||||
|
||||
@@ -154,6 +168,20 @@ const foreignViAbi = [
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function'
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
name: 'requiredBlockConfirmations',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function'
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
Submodule contracts updated: f405ba9e56...835742dfd8
@@ -13,7 +13,7 @@ git push
|
||||
Alternatively, if there are no changes except the playbooks, you can use the `master` branch:
|
||||
|
||||
```
|
||||
CIRCLE_BRANCH=master ./molecule.sh <scenario_name>
|
||||
./molecule.sh <scenario_name>
|
||||
```
|
||||
|
||||
In this case `master` branch will be used as a codebase for Monitor, UI, Oracle and Contracts deployed by your local playbook.
|
||||
@@ -21,7 +21,7 @@ In this case `master` branch will be used as a codebase for Monitor, UI, Oracle
|
||||
## Run the tests
|
||||
|
||||
```
|
||||
CIRCLE_BRANCH=master ./molecule.sh <scenario_name>
|
||||
./molecule.sh <scenario_name>
|
||||
```
|
||||
|
||||
Available scenarios:
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
cd ./e2e-commons
|
||||
set -e # exit when any command fails
|
||||
|
||||
docker-compose pull molecule_runner
|
||||
if [ -z "$CI" ]; then
|
||||
docker-compose build molecule_runner
|
||||
else
|
||||
docker-compose pull molecule_runner
|
||||
fi
|
||||
docker network create --driver bridge ultimate || true
|
||||
while [ "$1" != "" ]; do
|
||||
docker-compose run molecule_runner /bin/bash -c "molecule test --scenario-name $1"
|
||||
|
||||
@@ -6,12 +6,10 @@
|
||||
- name: stop the service
|
||||
shell: service poabridge stop
|
||||
|
||||
- name: Build current oracle image
|
||||
shell: docker build -t oracle:ultimate-testing --file oracle/Dockerfile .
|
||||
- name: ReTag current oracle image
|
||||
shell: docker tag $(docker images --format '{{ '{{' }}.Repository{{ '}}' }}:{{ '{{' }}.Tag{{ '}}' }}' | grep -m 1 tokenbridge-e2e-oracle) oracle:ultimate-testing
|
||||
delegate_to: 127.0.0.1
|
||||
become: false
|
||||
args:
|
||||
chdir: "{{ lookup('env', 'PWD') }}/.."
|
||||
|
||||
- name: Replace oracle image
|
||||
replace:
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
copy:
|
||||
src: ../../../../{{ item }}
|
||||
dest: "{{ bridge_path }}/"
|
||||
mode: '0640'
|
||||
with_items:
|
||||
- monorepo.tar.gz
|
||||
- contracts.tar.gz
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
template:
|
||||
src: .env.j2
|
||||
dest: "{{ bridge_path }}/monitor/.env"
|
||||
owner: "{{ compose_service_user }}"
|
||||
mode: '0640'
|
||||
when: skip_task != true
|
||||
|
||||
- name: Copy docker-compose file
|
||||
@@ -45,3 +47,5 @@
|
||||
template:
|
||||
src: config.env.j2
|
||||
dest: "{{ bridge_path }}/monitor/configs/{{ MONITOR_BRIDGE_NAME }}.env"
|
||||
owner: "{{ compose_service_user }}"
|
||||
mode: '0640'
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
template:
|
||||
src: .env.j2
|
||||
dest: "{{ bridge_path }}/oracle/.env"
|
||||
owner: "{{ compose_service_user }}"
|
||||
mode: '0640'
|
||||
|
||||
- name: Copy docker-compose files
|
||||
copy:
|
||||
|
||||
@@ -3,3 +3,5 @@
|
||||
template:
|
||||
src: .env.j2
|
||||
dest: "{{ bridge_path }}/ui/.env"
|
||||
owner: "{{ compose_service_user }}"
|
||||
mode: '0640'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
ARG DOCKER_LOGIN
|
||||
ARG CIRCLE_BRANCH
|
||||
FROM ${DOCKER_LOGIN}/tokenbridge-e2e-ui:${CIRCLE_BRANCH}
|
||||
ARG DOCKER_IMAGE_BASE
|
||||
ARG UI_TAG
|
||||
FROM ${DOCKER_IMAGE_BASE}/tokenbridge-e2e-ui:${UI_TAG}
|
||||
|
||||
ARG DOT_ENV_PATH
|
||||
|
||||
|
||||
0
e2e-commons/access-lists/allowance_list.txt
Normal file
0
e2e-commons/access-lists/allowance_list.txt
Normal file
2
e2e-commons/access-lists/block_list.txt
Normal file
2
e2e-commons/access-lists/block_list.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
0xc9e38bfdB9c635F0796ad83CC8705dc379F41c04
|
||||
0x612E8bd50A7b1F009F43f2b8679E9B8eD91eb5CE
|
||||
17
e2e-commons/build.sh
Executable file
17
e2e-commons/build.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
cd $(dirname $0)
|
||||
set -e # exit when any command fails
|
||||
|
||||
docker-compose build e2e
|
||||
while [ "$1" != "" ]; do
|
||||
if [ "$1" == "oracle" ]; then
|
||||
docker-compose build oracle
|
||||
elif [ "$1" == "monitor" ]; then
|
||||
docker-compose build monitor
|
||||
elif [ "$1" == "ui" ]; then
|
||||
docker-compose build ui
|
||||
elif [ "$1" == "alm" ]; then
|
||||
docker-compose build alm
|
||||
fi
|
||||
shift
|
||||
done
|
||||
@@ -23,3 +23,4 @@ ORACLE_FOREIGN_RPC_POLLING_INTERVAL=500
|
||||
ORACLE_ALLOW_HTTP_FOR_RPC=yes
|
||||
ORACLE_HOME_START_BLOCK=1
|
||||
ORACLE_FOREIGN_START_BLOCK=1
|
||||
ORACLE_HOME_TO_FOREIGN_BLOCK_LIST=/mono/oracle/access-lists/block_list.txt
|
||||
|
||||
@@ -23,3 +23,4 @@ ORACLE_FOREIGN_RPC_POLLING_INTERVAL=500
|
||||
ORACLE_ALLOW_HTTP_FOR_RPC=yes
|
||||
ORACLE_HOME_START_BLOCK=1
|
||||
ORACLE_FOREIGN_START_BLOCK=1
|
||||
ORACLE_HOME_TO_FOREIGN_BLOCK_LIST=/mono/oracle/access-lists/block_list.txt
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
"address": "0x3CC5baAB679eC0732C175760079Bf48F564ad26B",
|
||||
"privateKey": "0xedb53ee050631b7914d5f1a66c2f0d2df3ec85a9ed2a9616b16a7b1b7a10b8d1"
|
||||
},
|
||||
"blockedUser": {
|
||||
"address": "0xc9e38bfdB9c635F0796ad83CC8705dc379F41c04",
|
||||
"privateKey": "0x65df4ea787916f6ed9660f0b0fe36858a65735ad0dcd34527497f4ce32e53883"
|
||||
},
|
||||
"validator": {
|
||||
"address": "0xaaB52d66283F7A1D5978bcFcB55721ACB467384b",
|
||||
"privateKey": "0x8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9"
|
||||
@@ -50,8 +54,6 @@
|
||||
"home": "0x488Af810997eD1730cB3a3918cD83b3216E6eAda",
|
||||
"foreign": "0x488Af810997eD1730cB3a3918cD83b3216E6eAda",
|
||||
"foreignToken": "0x7cc4b1851c35959d34e635a470f6b5c43ba3c9c9",
|
||||
"halfDuplexToken": "0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359",
|
||||
"saiTop": "0x9b0ccf7C8994E19F39b2B4CF708e0A7DF65fA8a3",
|
||||
"chaiToken": "0x06af07097c9eeb7fd685c692751d5c66db49c215",
|
||||
"ui": "http://localhost:3002",
|
||||
"monitor": "http://monitor-erc20-native:3012/bridge"
|
||||
@@ -61,6 +63,7 @@
|
||||
"foreign": "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0",
|
||||
"homeBox": "0x6C4EaAb8756d53Bf599FFe2347FAFF1123D6C8A1",
|
||||
"foreignBox": "0x6C4EaAb8756d53Bf599FFe2347FAFF1123D6C8A1",
|
||||
"blockedHomeBox": "0x612E8bd50A7b1F009F43f2b8679E9B8eD91eb5CE",
|
||||
"monitor": "http://monitor-amb:3013/bridge"
|
||||
},
|
||||
"ambStakeErcToErc": {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
version: '3'
|
||||
version: '3.8'
|
||||
networks:
|
||||
ultimate:
|
||||
external: true
|
||||
@@ -27,7 +26,7 @@ services:
|
||||
networks:
|
||||
- ultimate
|
||||
oracle:
|
||||
image: ${DOCKER_LOGIN}/tokenbridge-e2e-oracle:${CIRCLE_BRANCH}
|
||||
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-oracle:${ORACLE_TAG:-local}
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: oracle/Dockerfile
|
||||
@@ -38,10 +37,7 @@ services:
|
||||
networks:
|
||||
- ultimate
|
||||
oracle-erc20:
|
||||
image: ${DOCKER_LOGIN}/tokenbridge-e2e-oracle:${CIRCLE_BRANCH}
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: oracle/Dockerfile
|
||||
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-oracle:${ORACLE_TAG:-local}
|
||||
env_file: ../e2e-commons/components-envs/oracle-erc20.env
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
@@ -49,29 +45,29 @@ services:
|
||||
networks:
|
||||
- ultimate
|
||||
oracle-erc20-native:
|
||||
image: ${DOCKER_LOGIN}/tokenbridge-e2e-oracle:${CIRCLE_BRANCH}
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: oracle/Dockerfile
|
||||
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-oracle:${ORACLE_TAG:-local}
|
||||
env_file: ../e2e-commons/components-envs/oracle-erc20-native.env
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
command: "true"
|
||||
volumes:
|
||||
- '../e2e-commons/access-lists/block_list.txt:/mono/oracle/access-lists/block_list.txt'
|
||||
- '../e2e-commons/access-lists/allowance_list.txt:/mono/oracle/access-lists/allowance_list.txt'
|
||||
networks:
|
||||
- ultimate
|
||||
oracle-amb:
|
||||
image: ${DOCKER_LOGIN}/tokenbridge-e2e-oracle:${CIRCLE_BRANCH}
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: oracle/Dockerfile
|
||||
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-oracle:${ORACLE_TAG:-local}
|
||||
env_file: ../e2e-commons/components-envs/oracle-amb.env
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
command: "true"
|
||||
volumes:
|
||||
- '../e2e-commons/access-lists/block_list.txt:/mono/oracle/access-lists/block_list.txt'
|
||||
- '../e2e-commons/access-lists/allowance_list.txt:/mono/oracle/access-lists/allowance_list.txt'
|
||||
networks:
|
||||
- ultimate
|
||||
ui:
|
||||
image: ${DOCKER_LOGIN}/tokenbridge-e2e-ui:${CIRCLE_BRANCH}
|
||||
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-ui:${UI_TAG:-local}
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: ui/Dockerfile
|
||||
@@ -85,8 +81,8 @@ services:
|
||||
context: ..
|
||||
dockerfile: e2e-commons/Dockerfile.ui
|
||||
args:
|
||||
DOCKER_LOGIN: ${DOCKER_LOGIN}
|
||||
CIRCLE_BRANCH: ${CIRCLE_BRANCH}
|
||||
DOCKER_IMAGE_BASE: ${DOCKER_IMAGE_BASE:-tokenbridge}
|
||||
UI_TAG: ${UI_TAG:-local}
|
||||
DOT_ENV_PATH: e2e-commons/components-envs/ui-erc20.env
|
||||
command: "true"
|
||||
networks:
|
||||
@@ -96,8 +92,8 @@ services:
|
||||
context: ..
|
||||
dockerfile: e2e-commons/Dockerfile.ui
|
||||
args:
|
||||
DOCKER_LOGIN: ${DOCKER_LOGIN}
|
||||
CIRCLE_BRANCH: ${CIRCLE_BRANCH}
|
||||
DOCKER_IMAGE_BASE: ${DOCKER_IMAGE_BASE:-tokenbridge}
|
||||
UI_TAG: ${UI_TAG:-local}
|
||||
DOT_ENV_PATH: e2e-commons/components-envs/ui-erc20-native.env
|
||||
command: "true"
|
||||
networks:
|
||||
@@ -107,14 +103,14 @@ services:
|
||||
context: ..
|
||||
dockerfile: e2e-commons/Dockerfile.ui
|
||||
args:
|
||||
DOCKER_LOGIN: ${DOCKER_LOGIN}
|
||||
CIRCLE_BRANCH: ${CIRCLE_BRANCH}
|
||||
DOCKER_IMAGE_BASE: ${DOCKER_IMAGE_BASE:-tokenbridge}
|
||||
UI_TAG: ${UI_TAG:-local}
|
||||
DOT_ENV_PATH: e2e-commons/components-envs/ui-amb-stake-erc20-erc20.env
|
||||
command: "true"
|
||||
networks:
|
||||
- ultimate
|
||||
alm:
|
||||
image: ${DOCKER_LOGIN}/tokenbridge-e2e-alm:${CIRCLE_BRANCH}
|
||||
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-alm:${ALM_TAG:-local}
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: alm/Dockerfile
|
||||
@@ -124,7 +120,7 @@ services:
|
||||
networks:
|
||||
- ultimate
|
||||
monitor:
|
||||
image: ${DOCKER_LOGIN}/tokenbridge-e2e-monitor:${CIRCLE_BRANCH}
|
||||
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-monitor:${MONITOR_TAG:-local}
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: monitor/Dockerfile
|
||||
@@ -135,10 +131,7 @@ services:
|
||||
networks:
|
||||
- ultimate
|
||||
monitor-erc20:
|
||||
image: ${DOCKER_LOGIN}/tokenbridge-e2e-monitor:${CIRCLE_BRANCH}
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: monitor/Dockerfile
|
||||
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-monitor:${MONITOR_TAG:-local}
|
||||
env_file: ../e2e-commons/components-envs/monitor-erc20.env
|
||||
entrypoint: yarn check-and-start
|
||||
ports:
|
||||
@@ -146,10 +139,7 @@ services:
|
||||
networks:
|
||||
- ultimate
|
||||
monitor-erc20-native:
|
||||
image: ${DOCKER_LOGIN}/tokenbridge-e2e-monitor:${CIRCLE_BRANCH}
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: monitor/Dockerfile
|
||||
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-monitor:${MONITOR_TAG:-local}
|
||||
env_file: ../e2e-commons/components-envs/monitor-erc20-native.env
|
||||
entrypoint: yarn check-and-start
|
||||
ports:
|
||||
@@ -157,10 +147,7 @@ services:
|
||||
networks:
|
||||
- ultimate
|
||||
monitor-amb:
|
||||
image: ${DOCKER_LOGIN}/tokenbridge-e2e-monitor:${CIRCLE_BRANCH}
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: monitor/Dockerfile
|
||||
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-monitor:${MONITOR_TAG:-local}
|
||||
env_file: ../e2e-commons/components-envs/monitor-amb.env
|
||||
entrypoint: yarn check-and-start
|
||||
ports:
|
||||
@@ -168,7 +155,7 @@ services:
|
||||
networks:
|
||||
- ultimate
|
||||
e2e:
|
||||
image: ${DOCKER_LOGIN}/tokenbridge-e2e-e2e:${CIRCLE_BRANCH}
|
||||
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-e2e:${E2E_TAG:-local}
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: Dockerfile.e2e
|
||||
@@ -176,15 +163,12 @@ services:
|
||||
networks:
|
||||
- ultimate
|
||||
blocks:
|
||||
image: ${DOCKER_LOGIN}/tokenbridge-e2e-e2e:${CIRCLE_BRANCH}
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: Dockerfile.e2e
|
||||
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-e2e:${E2E_TAG:-local}
|
||||
entrypoint: node e2e-commons/scripts/blocks.js
|
||||
networks:
|
||||
- ultimate
|
||||
molecule_runner:
|
||||
image: ${DOCKER_LOGIN}/tokenbridge-e2e-molecule_runner:${CIRCLE_BRANCH}
|
||||
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-molecule_runner:${MOLECULE_RUNNER_TAG:-local}
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: deployment-e2e/Dockerfile
|
||||
|
||||
@@ -53,3 +53,8 @@ node deploy.js
|
||||
cd - > /dev/null
|
||||
node setupStakeTokens.js
|
||||
cd - > /dev/null
|
||||
|
||||
echo -e "\n\n############ Deploying one more test contract for amb ############\n"
|
||||
cd "$DEPLOY_PATH"
|
||||
node src/utils/deployTestBox.js
|
||||
cd - > /dev/null
|
||||
|
||||
@@ -4,30 +4,42 @@ set -e # exit when any command fails
|
||||
|
||||
./down.sh
|
||||
docker-compose build parity1 parity2
|
||||
test -n "$NODOCKERPULL" || ./pull.sh $@
|
||||
|
||||
if [ -z "$CI" ]; then
|
||||
./build.sh $@
|
||||
else
|
||||
./pull.sh $@
|
||||
fi
|
||||
|
||||
docker network create --driver bridge ultimate || true
|
||||
docker-compose up -d parity1 parity2 e2e
|
||||
|
||||
startValidator () {
|
||||
docker-compose $1 run -d --name $4 redis
|
||||
docker-compose $1 run -d --name $5 rabbit
|
||||
docker-compose $1 run $2 $3 -d oracle yarn watcher:signature-request
|
||||
docker-compose $1 run $2 $3 -d oracle yarn watcher:collected-signatures
|
||||
docker-compose $1 run $2 $3 -d oracle yarn watcher:affirmation-request
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:signature-request
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:collected-signatures
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:affirmation-request
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:transfer
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:signature-request
|
||||
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: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
|
||||
if [[ -z "$MODE" || "$MODE" == native-to-erc ]]; then
|
||||
docker-compose $1 run $2 $3 -d oracle yarn watcher:signature-request
|
||||
docker-compose $1 run $2 $3 -d oracle yarn watcher:collected-signatures
|
||||
docker-compose $1 run $2 $3 -d oracle yarn watcher:affirmation-request
|
||||
fi
|
||||
if [[ -z "$MODE" || "$MODE" == erc-to-erc ]]; then
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:signature-request
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:collected-signatures
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:affirmation-request
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:transfer
|
||||
fi
|
||||
if [[ -z "$MODE" || "$MODE" == erc-to-native ]]; then
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:signature-request
|
||||
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:transfer
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn worker:convert-to-chai
|
||||
fi
|
||||
if [[ -z "$MODE" || "$MODE" == amb ]]; then
|
||||
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
|
||||
fi
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn sender:home
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn sender:foreign
|
||||
}
|
||||
@@ -44,27 +56,7 @@ startAMBValidator () {
|
||||
|
||||
while [ "$1" != "" ]; do
|
||||
if [ "$1" == "oracle" ]; then
|
||||
docker-compose up -d redis rabbit
|
||||
|
||||
docker-compose run -d oracle yarn watcher:signature-request
|
||||
docker-compose run -d oracle yarn watcher:collected-signatures
|
||||
docker-compose run -d oracle yarn watcher:affirmation-request
|
||||
docker-compose run -d oracle-erc20 yarn watcher:signature-request
|
||||
docker-compose run -d oracle-erc20 yarn watcher:collected-signatures
|
||||
docker-compose run -d oracle-erc20 yarn watcher:affirmation-request
|
||||
docker-compose run -d oracle-erc20 yarn watcher:transfer
|
||||
docker-compose run -d oracle-erc20-native yarn watcher:signature-request
|
||||
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: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
|
||||
docker-compose run -d oracle yarn sender:home
|
||||
docker-compose run -d oracle yarn sender:foreign
|
||||
startValidator "" "" "" "redis" "rabbit"
|
||||
fi
|
||||
|
||||
if [ "$1" == "oracle-validator-2" ]; then
|
||||
@@ -108,27 +100,23 @@ while [ "$1" != "" ]; do
|
||||
fi
|
||||
|
||||
if [ "$1" == "monitor" ]; then
|
||||
docker-compose up -d monitor monitor-erc20 monitor-erc20-native monitor-amb
|
||||
fi
|
||||
|
||||
if [ "$1" == "native-to-erc" ]; then
|
||||
../deployment-e2e/molecule.sh ultimate-native-to-erc
|
||||
fi
|
||||
|
||||
if [ "$1" == "erc-to-native" ]; then
|
||||
../deployment-e2e/molecule.sh ultimate-erc-to-native
|
||||
fi
|
||||
|
||||
if [ "$1" == "erc-to-erc" ]; then
|
||||
../deployment-e2e/molecule.sh ultimate-erc-to-erc
|
||||
fi
|
||||
|
||||
if [ "$1" == "amb" ]; then
|
||||
../deployment-e2e/molecule.sh ultimate-amb
|
||||
fi
|
||||
|
||||
if [ "$1" == "ultimate-amb-stake-erc-to-erc" ]; then
|
||||
../deployment-e2e/molecule.sh ultimate-amb-stake-erc-to-erc
|
||||
case "$MODE" in
|
||||
amb)
|
||||
docker-compose up -d monitor-amb
|
||||
;;
|
||||
native-to-erc)
|
||||
docker-compose up -d monitor
|
||||
;;
|
||||
erc-to-erc)
|
||||
docker-compose up -d monitor-erc20
|
||||
;;
|
||||
erc-to-native)
|
||||
docker-compose up -d monitor-erc20-native
|
||||
;;
|
||||
*)
|
||||
docker-compose up -d monitor monitor-erc20 monitor-erc20-native monitor-amb
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ "$1" == "alm-e2e" ]; then
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "mocha --timeout 30000",
|
||||
"start": "mocha --timeout 120000",
|
||||
"lint": "eslint . --ignore-path ../.eslintignore"
|
||||
},
|
||||
"author": "",
|
||||
@@ -14,7 +14,7 @@
|
||||
"axios": "0.19.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.9"
|
||||
"node": ">= 10.18"
|
||||
},
|
||||
"devDependencies": {}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
while true; do
|
||||
sleep 3
|
||||
COMPOSE_INTERACTIVE_NO_CLI=1 nohup docker-compose -f ../e2e-commons/docker-compose.yml exec monitor yarn check-all
|
||||
COMPOSE_INTERACTIVE_NO_CLI=1 nohup docker-compose -f ../e2e-commons/docker-compose.yml exec monitor-erc20 yarn check-all
|
||||
COMPOSE_INTERACTIVE_NO_CLI=1 nohup docker-compose -f ../e2e-commons/docker-compose.yml exec monitor-erc20-native yarn check-all
|
||||
COMPOSE_INTERACTIVE_NO_CLI=1 nohup docker-compose -f ../e2e-commons/docker-compose.yml exec monitor-amb yarn check-all
|
||||
docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor yarn check-all
|
||||
pid1=$!
|
||||
docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20 yarn check-all
|
||||
pid2=$!
|
||||
docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20-native yarn check-all
|
||||
pid3=$!
|
||||
docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-amb yarn check-all
|
||||
pid4=$!
|
||||
|
||||
wait $pid1
|
||||
wait $pid2
|
||||
wait $pid3
|
||||
wait $pid4
|
||||
done
|
||||
|
||||
@@ -1,12 +1,28 @@
|
||||
cd $(dirname $0)
|
||||
|
||||
../e2e-commons/up.sh deploy blocks monitor
|
||||
mode="$1"
|
||||
case "$mode" in
|
||||
amb)
|
||||
script=./test/amb.js
|
||||
;;
|
||||
native-to-erc)
|
||||
script=./test/nativeToErc.js
|
||||
;;
|
||||
erc-to-erc)
|
||||
script=./test/ercToErc.js
|
||||
;;
|
||||
erc-to-native)
|
||||
script=./test/ercToNative.js
|
||||
;;
|
||||
esac
|
||||
|
||||
./wait-for-monitor.sh
|
||||
MODE="$mode" ../e2e-commons/up.sh deploy blocks monitor
|
||||
|
||||
MODE="$mode" ./wait-for-monitor.sh
|
||||
nohup ./periodically-check-all.sh < /dev/null > /dev/null 2>&1 &
|
||||
checkPID=$!
|
||||
|
||||
docker-compose -f ../e2e-commons/docker-compose.yml run e2e yarn workspace monitor-e2e run start
|
||||
docker-compose -f ../e2e-commons/docker-compose.yml run e2e yarn workspace monitor-e2e run start $script
|
||||
rc=$?
|
||||
|
||||
../e2e-commons/down.sh
|
||||
|
||||
@@ -25,6 +25,7 @@ describe('AMB', () => {
|
||||
|
||||
describe('general', async () => {
|
||||
it('should contain fromHomeToForeignDiff', () => assert(data.fromHomeToForeignDiff === 0))
|
||||
it('should contain fromHomeToForeignPBUDiff', () => assert(data.fromHomeToForeignPBUDiff === 0))
|
||||
it('should contain fromForeignToHomeDiff', () => assert(data.fromForeignToHomeDiff === 0))
|
||||
it('should contain lastChecked', () => assert(data.lastChecked >= 0))
|
||||
it('should contain timeDiff', () => assert(data.timeDiff >= 0))
|
||||
@@ -114,7 +115,16 @@ describe('AMB', () => {
|
||||
|
||||
await waitUntil(async () => {
|
||||
;({ data } = await axios.get(`${baseUrl}`))
|
||||
return data.fromHomeToForeignDiff !== 0
|
||||
return data.fromHomeToForeignDiff === 1 && data.fromHomeToForeignPBUDiff === 0
|
||||
})
|
||||
})
|
||||
it('should change fromHomeToForeignPBUDiff', async () => {
|
||||
// send message
|
||||
await sendAMBMessage(homeRPC.URL, user, amb.homeBox, amb.home, amb.foreignBox, true)
|
||||
|
||||
await waitUntil(async () => {
|
||||
;({ data } = await axios.get(`${baseUrl}`))
|
||||
return data.fromHomeToForeignDiff === 1 && data.fromHomeToForeignPBUDiff === 1
|
||||
})
|
||||
})
|
||||
it('should change validatorsMatch', async () => {
|
||||
|
||||
@@ -37,6 +37,9 @@ describe('ERC TO NATIVE with changing state of contracts', () => {
|
||||
|
||||
await waitUntil(async () => {
|
||||
;({ data } = await axios.get(`${baseUrl}`))
|
||||
if (!data.foreign) {
|
||||
return false
|
||||
}
|
||||
const { erc20Balance, investedErc20Balance } = data.foreign
|
||||
return data.balanceDiff === 0.01 && erc20Balance === '0.01' && investedErc20Balance === undefined
|
||||
})
|
||||
@@ -51,12 +54,15 @@ describe('ERC TO NATIVE with changing state of contracts', () => {
|
||||
})
|
||||
|
||||
it('should consider chai token balance', async function() {
|
||||
this.timeout(60000)
|
||||
this.timeout(120000)
|
||||
await initializeChaiToken(foreignRPC.URL, ercToNativeBridge.foreign)
|
||||
await sendTokens(foreignRPC.URL, user, ercToNativeBridge.foreignToken, ercToNativeBridge.foreign)
|
||||
|
||||
await waitUntil(async () => {
|
||||
;({ data } = await axios.get(`${baseUrl}`))
|
||||
if (!data.foreign) {
|
||||
return false
|
||||
}
|
||||
const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
|
||||
return (
|
||||
data.balanceDiff === 0.02 &&
|
||||
@@ -71,6 +77,9 @@ describe('ERC TO NATIVE with changing state of contracts', () => {
|
||||
|
||||
await waitUntil(async () => {
|
||||
;({ data } = await axios.get(`${baseUrl}`))
|
||||
if (!data.foreign) {
|
||||
return false
|
||||
}
|
||||
const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
|
||||
return (
|
||||
data.balanceDiff === 0.02 &&
|
||||
@@ -85,6 +94,9 @@ describe('ERC TO NATIVE with changing state of contracts', () => {
|
||||
|
||||
await waitUntil(async () => {
|
||||
;({ data } = await axios.get(`${baseUrl}`))
|
||||
if (!data.foreign) {
|
||||
return false
|
||||
}
|
||||
const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
|
||||
return (
|
||||
data.balanceDiff === 0.02 &&
|
||||
|
||||
@@ -8,7 +8,7 @@ const {
|
||||
} = require('../commons')
|
||||
const { validator } = require('../e2e-commons/constants')
|
||||
|
||||
const waitUntil = async (predicate, step = 100, timeout = 20000) => {
|
||||
const waitUntil = async (predicate, step = 100, timeout = 60000) => {
|
||||
const stopTime = Date.now() + timeout
|
||||
while (Date.now() <= stopTime) {
|
||||
const result = await predicate()
|
||||
@@ -44,12 +44,16 @@ const sendTokens = async (rpcUrl, account, tokenAddress, recipientAddress) => {
|
||||
})
|
||||
}
|
||||
|
||||
const sendAMBMessage = async (rpcUrl, account, boxAddress, bridgeAddress, boxOtherSideAddress) => {
|
||||
const sendAMBMessage = async (rpcUrl, account, boxAddress, bridgeAddress, boxOtherSideAddress, manualLane = false) => {
|
||||
const web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl))
|
||||
web3.eth.accounts.wallet.add(account.privateKey)
|
||||
const homeBox = new web3.eth.Contract(BOX_ABI, boxAddress)
|
||||
|
||||
await homeBox.methods.setValueOnOtherNetwork(3, bridgeAddress, boxOtherSideAddress).send({
|
||||
await homeBox.methods[manualLane ? 'setValueOnOtherNetworkUsingManualLane' : 'setValueOnOtherNetwork'](
|
||||
3,
|
||||
bridgeAddress,
|
||||
boxOtherSideAddress
|
||||
).send({
|
||||
from: account.address,
|
||||
gas: '400000'
|
||||
})
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
FILES=(getBalances.json validators.json eventsStats.json alerts.json)
|
||||
|
||||
check_files_exist() {
|
||||
rc=0
|
||||
for f in "${FILES[@]}"; do
|
||||
command="test -f responses/bridge/$f"
|
||||
(docker-compose -f ../e2e-commons/docker-compose.yml exec monitor /bin/bash -c "$command") || rc=1
|
||||
(docker-compose -f ../e2e-commons/docker-compose.yml exec monitor-erc20 /bin/bash -c "$command") || rc=1
|
||||
(docker-compose -f ../e2e-commons/docker-compose.yml exec monitor-erc20-native /bin/bash -c "$command") || rc=1
|
||||
(docker-compose -f ../e2e-commons/docker-compose.yml exec monitor-amb /bin/bash -c "$command") || rc=1
|
||||
if [[ -z "$MODE" || "$MODE" == native-to-erc ]]; then
|
||||
(docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor /bin/bash -c "$command") || rc=1
|
||||
fi
|
||||
if [[ -z "$MODE" || "$MODE" == erc-to-erc ]]; then
|
||||
(docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20 /bin/bash -c "$command") || rc=1
|
||||
fi
|
||||
if [[ -z "$MODE" || "$MODE" == erc-to-native ]]; then
|
||||
(docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20-native /bin/bash -c "$command") || rc=1
|
||||
fi
|
||||
if [[ -z "$MODE" || "$MODE" == amb ]]; then
|
||||
(docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-amb /bin/bash -c "$command") || rc=1
|
||||
fi
|
||||
done
|
||||
return $rc
|
||||
}
|
||||
|
||||
@@ -22,3 +22,6 @@ COMMON_FOREIGN_GAS_PRICE_FACTOR=1
|
||||
MONITOR_TX_NUMBER_THRESHOLD=100
|
||||
MONITOR_PORT=3003
|
||||
MONITOR_CACHE_EVENTS=true
|
||||
|
||||
MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST=
|
||||
MONITOR_HOME_TO_FOREIGN_BLOCK_LIST=
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:8 as contracts
|
||||
FROM node:10 as contracts
|
||||
|
||||
WORKDIR /mono
|
||||
|
||||
@@ -11,7 +11,7 @@ COPY ./contracts/truffle-config.js ./
|
||||
COPY ./contracts/contracts ./contracts
|
||||
RUN npm run compile
|
||||
|
||||
FROM node:8
|
||||
FROM node:10
|
||||
|
||||
WORKDIR /mono
|
||||
COPY package.json .
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
require('dotenv').config()
|
||||
const Web3 = require('web3')
|
||||
const logger = require('./logger')('alerts')
|
||||
const eventsInfo = require('./utils/events')
|
||||
const { getBlockNumber } = require('./utils/contract')
|
||||
const { processedMsgNotDelivered, eventWithoutReference } = require('./utils/message')
|
||||
const { BRIDGE_MODES } = require('../commons')
|
||||
|
||||
const { COMMON_HOME_RPC_URL, COMMON_FOREIGN_RPC_URL } = process.env
|
||||
|
||||
const homeProvider = new Web3.providers.HttpProvider(COMMON_HOME_RPC_URL)
|
||||
const web3Home = new Web3(homeProvider)
|
||||
|
||||
const foreignProvider = new Web3.providers.HttpProvider(COMMON_FOREIGN_RPC_URL)
|
||||
const web3Foreign = new Web3(foreignProvider)
|
||||
const { web3Home, web3Foreign, getHomeBlockNumber, getForeignBlockNumber } = require('./utils/web3')
|
||||
|
||||
async function main() {
|
||||
const {
|
||||
@@ -33,7 +24,8 @@ async function main() {
|
||||
xAffirmations = foreignToHomeConfirmations.filter(eventWithoutReference(foreignToHomeRequests))
|
||||
}
|
||||
logger.debug('building misbehavior blocks')
|
||||
const [homeBlockNumber, foreignBlockNumber] = await getBlockNumber(web3Home, web3Foreign)
|
||||
const homeBlockNumber = await getHomeBlockNumber()
|
||||
const foreignBlockNumber = await getForeignBlockNumber()
|
||||
|
||||
const baseRange = [false, false, false, false, false]
|
||||
const xSignaturesMisbehavior = buildRangesObject(
|
||||
@@ -73,21 +65,21 @@ async function main() {
|
||||
|
||||
/**
|
||||
* Finds the location for the blockNumber in a specific range starting from currentBlockNumber
|
||||
* @param {BN} currentBlockNumber
|
||||
* @param {Number} currentBlockNumber
|
||||
* @returns {function({blockNumber?: *}): boolean[]}
|
||||
*/
|
||||
const findMisbehaviorRange = currentBlockNumber => ({ blockNumber }) => {
|
||||
const minus60 = currentBlockNumber.sub(Web3.utils.toBN(60))
|
||||
const minus180 = currentBlockNumber.sub(Web3.utils.toBN(180))
|
||||
const minus720 = currentBlockNumber.sub(Web3.utils.toBN(720))
|
||||
const minus17280 = currentBlockNumber.sub(Web3.utils.toBN(17280))
|
||||
const minus60 = currentBlockNumber - 60
|
||||
const minus180 = currentBlockNumber - 180
|
||||
const minus720 = currentBlockNumber - 720
|
||||
const minus17280 = currentBlockNumber - 17280
|
||||
|
||||
return [
|
||||
minus60.lte(blockNumber),
|
||||
minus180.lte(blockNumber) && minus60.gt(blockNumber),
|
||||
minus720.lte(blockNumber) && minus180.gt(blockNumber),
|
||||
minus17280.lte(blockNumber) && minus720.gt(blockNumber),
|
||||
minus17280.gt(blockNumber)
|
||||
minus60 <= blockNumber,
|
||||
minus180 <= blockNumber && minus60 > blockNumber,
|
||||
minus720 <= blockNumber && minus180 > blockNumber,
|
||||
minus17280 <= blockNumber && minus720 > blockNumber,
|
||||
minus17280 > blockNumber
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
0
monitor/cache/.gitkeep
vendored
Normal file
0
monitor/cache/.gitkeep
vendored
Normal file
@@ -1,21 +1,21 @@
|
||||
require('dotenv').config()
|
||||
const Web3 = require('web3')
|
||||
const BN = require('bignumber.js')
|
||||
const logger = require('./logger')('checkWorker')
|
||||
const { getBridgeMode } = require('../commons')
|
||||
const getBalances = require('./getBalances')
|
||||
const getShortEventStats = require('./getShortEventStats')
|
||||
const validators = require('./validators')
|
||||
const getEventsInfo = require('./utils/events')
|
||||
const { writeFile, createDir } = require('./utils/file')
|
||||
const { saveCache } = require('./utils/web3Cache')
|
||||
const { web3Home } = require('./utils/web3')
|
||||
|
||||
const { COMMON_HOME_BRIDGE_ADDRESS, COMMON_HOME_RPC_URL, MONITOR_BRIDGE_NAME } = process.env
|
||||
const { COMMON_HOME_BRIDGE_ADDRESS, MONITOR_BRIDGE_NAME } = process.env
|
||||
|
||||
const MONITOR_VALIDATOR_HOME_TX_LIMIT = Number(process.env.MONITOR_VALIDATOR_HOME_TX_LIMIT) || 0
|
||||
const MONITOR_VALIDATOR_FOREIGN_TX_LIMIT = Number(process.env.MONITOR_VALIDATOR_FOREIGN_TX_LIMIT) || 0
|
||||
const MONITOR_TX_NUMBER_THRESHOLD = Number(process.env.MONITOR_TX_NUMBER_THRESHOLD) || 100
|
||||
|
||||
const homeProvider = new Web3.providers.HttpProvider(COMMON_HOME_RPC_URL)
|
||||
const web3Home = new Web3(homeProvider)
|
||||
|
||||
const { HOME_ERC_TO_ERC_ABI } = require('../commons')
|
||||
|
||||
async function checkWorker() {
|
||||
@@ -24,16 +24,22 @@ async function checkWorker() {
|
||||
const homeBridge = new web3Home.eth.Contract(HOME_ERC_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
||||
const bridgeMode = await getBridgeMode(homeBridge)
|
||||
logger.debug('Bridge mode:', bridgeMode)
|
||||
logger.debug('calling getEventsInfo()')
|
||||
const eventsInfo = await getEventsInfo(bridgeMode)
|
||||
logger.debug('calling getBalances()')
|
||||
const balances = await getBalances(bridgeMode)
|
||||
const balances = await getBalances(bridgeMode, eventsInfo)
|
||||
logger.debug('calling getShortEventStats()')
|
||||
const events = await getShortEventStats(bridgeMode)
|
||||
const events = await getShortEventStats(bridgeMode, eventsInfo)
|
||||
const home = Object.assign({}, balances.home, events.home)
|
||||
const foreign = Object.assign({}, balances.foreign, events.foreign)
|
||||
const status = Object.assign({}, balances, events, { home }, { foreign })
|
||||
if (status.balanceDiff && status.unclaimedBalance) {
|
||||
status.balanceDiff = new BN(status.balanceDiff).minus(status.unclaimedBalance).toFixed()
|
||||
}
|
||||
if (!status) throw new Error('status is empty: ' + JSON.stringify(status))
|
||||
status.health = true
|
||||
writeFile(`/responses/${MONITOR_BRIDGE_NAME}/getBalances.json`, status)
|
||||
saveCache()
|
||||
|
||||
logger.debug('calling validators()')
|
||||
const vBalances = await validators(bridgeMode)
|
||||
|
||||
@@ -3,6 +3,7 @@ const logger = require('./logger')('checkWorker2')
|
||||
const eventsStats = require('./eventsStats')
|
||||
const alerts = require('./alerts')
|
||||
const { writeFile, createDir } = require('./utils/file')
|
||||
const { saveCache } = require('./utils/web3Cache')
|
||||
|
||||
const { MONITOR_BRIDGE_NAME } = process.env
|
||||
|
||||
@@ -26,6 +27,7 @@ async function checkWorker2() {
|
||||
_alerts.ok = !_alerts.executeAffirmations.mostRecentTxHash && !_alerts.executeSignatures.mostRecentTxHash
|
||||
_alerts.health = true
|
||||
writeFile(`/responses/${MONITOR_BRIDGE_NAME}/alerts.json`, _alerts)
|
||||
saveCache()
|
||||
logger.debug('Done x2')
|
||||
} catch (e) {
|
||||
logger.error(e)
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
require('dotenv').config()
|
||||
const Web3 = require('web3')
|
||||
const logger = require('./logger')('checkWorker3')
|
||||
const stuckTransfers = require('./stuckTransfers')
|
||||
const { writeFile, createDir } = require('./utils/file')
|
||||
const { web3Home } = require('./utils/web3')
|
||||
|
||||
const { MONITOR_BRIDGE_NAME, COMMON_HOME_BRIDGE_ADDRESS, COMMON_HOME_RPC_URL } = process.env
|
||||
const { MONITOR_BRIDGE_NAME, COMMON_HOME_BRIDGE_ADDRESS } = process.env
|
||||
const { getBridgeMode, HOME_NATIVE_TO_ERC_ABI, BRIDGE_MODES } = require('../commons')
|
||||
|
||||
const homeProvider = new Web3.providers.HttpProvider(COMMON_HOME_RPC_URL)
|
||||
const web3Home = new Web3(homeProvider)
|
||||
|
||||
async function checkWorker3() {
|
||||
try {
|
||||
const homeBridge = new web3Home.eth.Contract(HOME_NATIVE_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
||||
|
||||
@@ -3,4 +3,6 @@ version: '2.4'
|
||||
services:
|
||||
monitor:
|
||||
image: poanetwork/tokenbridge-monitor
|
||||
build: .
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: ./monitor/Dockerfile
|
||||
|
||||
@@ -4,11 +4,12 @@ services:
|
||||
monitor:
|
||||
image: poanetwork/tokenbridge-monitor:latest
|
||||
ports:
|
||||
- "${MONITOR_PORT}:${MONITOR_PORT}"
|
||||
- "${MONITOR_PORT}:${MONITOR_PORT}"
|
||||
env_file: ./.env
|
||||
environment:
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
volumes:
|
||||
- ./responses:/mono/monitor/responses
|
||||
- ./cache:/mono/monitor/cache
|
||||
restart: unless-stopped
|
||||
entrypoint: "yarn start"
|
||||
|
||||
@@ -1,8 +1,20 @@
|
||||
require('dotenv').config()
|
||||
const eventsInfo = require('./utils/events')
|
||||
const { processedMsgNotDelivered, deliveredMsgNotProcessed, eventWithoutReference } = require('./utils/message')
|
||||
const {
|
||||
processedMsgNotDelivered,
|
||||
deliveredMsgNotProcessed,
|
||||
eventWithoutReference,
|
||||
unclaimedHomeToForeignRequests
|
||||
} = require('./utils/message')
|
||||
const { getHomeTxSender } = require('./utils/web3Cache')
|
||||
const { BRIDGE_MODES } = require('../commons')
|
||||
|
||||
const {
|
||||
MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST,
|
||||
MONITOR_HOME_TO_FOREIGN_BLOCK_LIST,
|
||||
MONITOR_HOME_TO_FOREIGN_CHECK_SENDER
|
||||
} = process.env
|
||||
|
||||
async function main() {
|
||||
const {
|
||||
homeToForeignRequests,
|
||||
@@ -33,17 +45,30 @@ async function main() {
|
||||
lastChecked: Math.floor(Date.now() / 1000)
|
||||
}
|
||||
} else {
|
||||
const onlyInHomeDeposits = homeToForeignRequests.filter(eventWithoutReference(homeToForeignConfirmations))
|
||||
let onlyInHomeDeposits = homeToForeignRequests.filter(eventWithoutReference(homeToForeignConfirmations))
|
||||
const onlyInForeignDeposits = homeToForeignConfirmations.filter(eventWithoutReference(homeToForeignRequests))
|
||||
|
||||
const onlyInHomeWithdrawals = foreignToHomeConfirmations.filter(eventWithoutReference(foreignToHomeRequests))
|
||||
const onlyInForeignWithdrawals = foreignToHomeRequests.filter(eventWithoutReference(foreignToHomeConfirmations))
|
||||
|
||||
const unclaimedStats = {}
|
||||
if (MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST || MONITOR_HOME_TO_FOREIGN_BLOCK_LIST) {
|
||||
const unclaimedFilter = unclaimedHomeToForeignRequests()
|
||||
if (MONITOR_HOME_TO_FOREIGN_CHECK_SENDER === 'true') {
|
||||
for (let i = 0; i < onlyInHomeDeposits.length; i++) {
|
||||
onlyInHomeDeposits[i].sender = await getHomeTxSender(onlyInHomeDeposits[i].transactionHash)
|
||||
}
|
||||
}
|
||||
unclaimedStats.unclaimedHomeDeposits = onlyInHomeDeposits.filter(unclaimedFilter)
|
||||
onlyInHomeDeposits = onlyInHomeDeposits.filter(e => !unclaimedFilter(e))
|
||||
}
|
||||
|
||||
return {
|
||||
onlyInHomeDeposits,
|
||||
onlyInForeignDeposits,
|
||||
onlyInHomeWithdrawals,
|
||||
onlyInForeignWithdrawals,
|
||||
...unclaimedStats,
|
||||
lastChecked: Math.floor(Date.now() / 1000)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
require('dotenv').config()
|
||||
const BN = require('bignumber.js')
|
||||
const Web3 = require('web3')
|
||||
const Web3Utils = require('web3').utils
|
||||
const logger = require('./logger')('getBalances')
|
||||
const { BRIDGE_MODES } = require('../commons')
|
||||
const { web3Home, web3Foreign, getHomeBlockNumber } = require('./utils/web3')
|
||||
|
||||
const Web3Utils = Web3.utils
|
||||
|
||||
const {
|
||||
COMMON_HOME_RPC_URL,
|
||||
COMMON_FOREIGN_RPC_URL,
|
||||
COMMON_HOME_BRIDGE_ADDRESS,
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS
|
||||
} = process.env
|
||||
|
||||
const homeProvider = new Web3.providers.HttpProvider(COMMON_HOME_RPC_URL)
|
||||
const web3Home = new Web3(homeProvider)
|
||||
|
||||
const foreignProvider = new Web3.providers.HttpProvider(COMMON_FOREIGN_RPC_URL)
|
||||
const web3Foreign = new Web3(foreignProvider)
|
||||
const { COMMON_HOME_BRIDGE_ADDRESS, COMMON_FOREIGN_BRIDGE_ADDRESS } = process.env
|
||||
|
||||
const {
|
||||
ERC20_ABI,
|
||||
@@ -30,21 +18,50 @@ const {
|
||||
FOREIGN_NATIVE_TO_ERC_ABI
|
||||
} = require('../commons')
|
||||
|
||||
async function main(bridgeMode) {
|
||||
async function main(bridgeMode, eventsInfo) {
|
||||
const {
|
||||
homeToForeignConfirmations,
|
||||
foreignToHomeConfirmations,
|
||||
homeDelayedBlockNumber,
|
||||
foreignDelayedBlockNumber
|
||||
} = eventsInfo
|
||||
|
||||
// Events in the ./utils/events.js are fetched for different block ranges,
|
||||
// In order to be consistent with the balance values, the following values might be needed
|
||||
|
||||
// Foreign balance should represent all UserRequestForAffirmation events up to block `N - requiredBlockConfirmation()`
|
||||
// and all RelayedMessage events up to block `N`.
|
||||
// This constant tells the difference between bridge balance at block `N - requiredBlockConfirmation() + 1`
|
||||
// and the actual value monitor is interested in.
|
||||
const lateForeignConfirmationsTotalValue = BN.sum(
|
||||
0,
|
||||
...homeToForeignConfirmations.filter(e => e.blockNumber > foreignDelayedBlockNumber).map(e => e.value)
|
||||
)
|
||||
// Home balance should represent all UserRequestForSignature events up to block `M - requiredBlockConfirmation()`
|
||||
// and all AffirmationCompleted events up to block `M`.
|
||||
// This constant tells the difference between bridge balance at block `M - requiredBlockConfirmation() + 1`
|
||||
// and the actual value monitor is interested in.
|
||||
const lateHomeConfirmationsTotalValue = BN.sum(
|
||||
0,
|
||||
...foreignToHomeConfirmations.filter(e => e.blockNumber > homeDelayedBlockNumber).map(e => e.value)
|
||||
)
|
||||
|
||||
if (bridgeMode === BRIDGE_MODES.ERC_TO_ERC) {
|
||||
const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
const erc20Address = await foreignBridge.methods.erc20token().call()
|
||||
const erc20Contract = new web3Foreign.eth.Contract(ERC20_ABI, erc20Address)
|
||||
logger.debug('calling erc20Contract.methods.balanceOf')
|
||||
const foreignErc20Balance = await erc20Contract.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||
const foreignErc20Balance = await erc20Contract.methods
|
||||
.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
.call({}, foreignDelayedBlockNumber)
|
||||
const homeBridge = new web3Home.eth.Contract(HOME_ERC_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
||||
logger.debug('calling homeBridge.methods.erc677token')
|
||||
const tokenAddress = await homeBridge.methods.erc677token().call()
|
||||
const tokenContract = new web3Home.eth.Contract(ERC677_ABI, tokenAddress)
|
||||
logger.debug('calling tokenContract.methods.totalSupply()')
|
||||
const totalSupply = await tokenContract.methods.totalSupply().call()
|
||||
const foreignBalanceBN = new BN(foreignErc20Balance)
|
||||
const foreignTotalSupplyBN = new BN(totalSupply)
|
||||
const totalSupply = await tokenContract.methods.totalSupply().call({}, homeDelayedBlockNumber)
|
||||
const foreignBalanceBN = new BN(foreignErc20Balance).plus(lateForeignConfirmationsTotalValue)
|
||||
const foreignTotalSupplyBN = new BN(totalSupply).plus(lateHomeConfirmationsTotalValue)
|
||||
const diff = foreignBalanceBN.minus(foreignTotalSupplyBN).toString(10)
|
||||
logger.debug('Done')
|
||||
return {
|
||||
@@ -61,12 +78,12 @@ async function main(bridgeMode) {
|
||||
logger.debug('calling web3Home.eth.getBalance')
|
||||
const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_NATIVE_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
const erc20Address = await foreignBridge.methods.erc677token().call()
|
||||
const homeBalance = await web3Home.eth.getBalance(COMMON_HOME_BRIDGE_ADDRESS)
|
||||
const homeBalance = await web3Home.eth.getBalance(COMMON_HOME_BRIDGE_ADDRESS, homeDelayedBlockNumber)
|
||||
const tokenContract = new web3Foreign.eth.Contract(ERC20_ABI, erc20Address)
|
||||
logger.debug('calling tokenContract.methods.totalSupply()')
|
||||
const totalSupply = await tokenContract.methods.totalSupply().call()
|
||||
const homeBalanceBN = new BN(homeBalance)
|
||||
const foreignTotalSupplyBN = new BN(totalSupply)
|
||||
const totalSupply = await tokenContract.methods.totalSupply().call({}, foreignDelayedBlockNumber)
|
||||
const homeBalanceBN = new BN(homeBalance).plus(lateHomeConfirmationsTotalValue)
|
||||
const foreignTotalSupplyBN = new BN(totalSupply).plus(lateForeignConfirmationsTotalValue)
|
||||
const diff = homeBalanceBN.minus(foreignTotalSupplyBN).toString(10)
|
||||
logger.debug('Done')
|
||||
return {
|
||||
@@ -103,21 +120,25 @@ async function main(bridgeMode) {
|
||||
}
|
||||
|
||||
logger.debug('calling erc20Contract.methods.balanceOf')
|
||||
const foreignErc20Balance = await erc20Contract.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||
const foreignErc20Balance = await erc20Contract.methods
|
||||
.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
.call({}, foreignDelayedBlockNumber)
|
||||
|
||||
const homeBridge = new web3Home.eth.Contract(HOME_ERC_TO_NATIVE_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
||||
logger.debug('calling homeBridge.methods.blockRewardContract')
|
||||
const blockRewardAddress = await homeBridge.methods.blockRewardContract().call()
|
||||
const blockRewardContract = new web3Home.eth.Contract(BLOCK_REWARD_ABI, blockRewardAddress)
|
||||
const homeBlockNumber = await getHomeBlockNumber()
|
||||
logger.debug('calling blockReward.methods.mintedTotally')
|
||||
const mintedCoins = await blockRewardContract.methods.mintedTotallyByBridge(COMMON_HOME_BRIDGE_ADDRESS).call()
|
||||
const mintedCoins = await blockRewardContract.methods
|
||||
.mintedTotallyByBridge(COMMON_HOME_BRIDGE_ADDRESS)
|
||||
.call({}, homeBlockNumber)
|
||||
logger.debug('calling homeBridge.methods.totalBurntCoins')
|
||||
const burntCoins = await homeBridge.methods.totalBurntCoins().call()
|
||||
|
||||
const burntCoins = await homeBridge.methods.totalBurntCoins().call({}, homeDelayedBlockNumber)
|
||||
const mintedCoinsBN = new BN(mintedCoins)
|
||||
const burntCoinsBN = new BN(burntCoins)
|
||||
const totalSupplyBN = mintedCoinsBN.minus(burntCoinsBN)
|
||||
const foreignErc20BalanceBN = new BN(foreignErc20Balance)
|
||||
const foreignErc20BalanceBN = new BN(foreignErc20Balance).plus(lateForeignConfirmationsTotalValue)
|
||||
const investedAmountInDaiBN = new BN(investedAmountInDai)
|
||||
const bridgeDsrBalanceBN = new BN(bridgeDsrBalance)
|
||||
|
||||
|
||||
@@ -1,18 +1,36 @@
|
||||
require('dotenv').config()
|
||||
const eventsInfo = require('./utils/events')
|
||||
const BN = require('bignumber.js')
|
||||
const Web3Utils = require('web3').utils
|
||||
const {
|
||||
eventWithoutReference,
|
||||
deliveredMsgNotProcessed,
|
||||
unclaimedHomeToForeignRequests,
|
||||
manuallyProcessedAMBHomeToForeignRequests
|
||||
} = require('./utils/message')
|
||||
const { BRIDGE_MODES } = require('../commons')
|
||||
const { getHomeTxSender } = require('./utils/web3Cache')
|
||||
|
||||
async function main(bridgeMode) {
|
||||
const {
|
||||
MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST,
|
||||
MONITOR_HOME_TO_FOREIGN_BLOCK_LIST,
|
||||
MONITOR_HOME_TO_FOREIGN_CHECK_SENDER
|
||||
} = process.env
|
||||
|
||||
async function main(bridgeMode, eventsInfo) {
|
||||
const {
|
||||
homeToForeignConfirmations,
|
||||
homeToForeignRequests,
|
||||
foreignToHomeConfirmations,
|
||||
foreignToHomeRequests
|
||||
} = await eventsInfo(bridgeMode)
|
||||
} = eventsInfo
|
||||
|
||||
if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) {
|
||||
const onlyInHomeRequests = homeToForeignRequests.filter(deliveredMsgNotProcessed(homeToForeignConfirmations))
|
||||
const manuallyProcessedRequests = onlyInHomeRequests.filter(manuallyProcessedAMBHomeToForeignRequests())
|
||||
return {
|
||||
fromHomeToForeignDiff: homeToForeignRequests.length - homeToForeignConfirmations.length,
|
||||
fromHomeToForeignDiff:
|
||||
homeToForeignRequests.length - homeToForeignConfirmations.length - manuallyProcessedRequests.length,
|
||||
fromHomeToForeignPBUDiff: manuallyProcessedRequests.length,
|
||||
fromForeignToHomeDiff: foreignToHomeConfirmations.length - foreignToHomeRequests.length,
|
||||
home: {
|
||||
toForeign: homeToForeignRequests.length,
|
||||
@@ -24,9 +42,26 @@ async function main(bridgeMode) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
const stats = {
|
||||
depositsDiff: homeToForeignRequests.length - homeToForeignConfirmations.length,
|
||||
withdrawalDiff: foreignToHomeConfirmations.length - foreignToHomeRequests.length,
|
||||
withdrawalDiff: foreignToHomeConfirmations.length - foreignToHomeRequests.length
|
||||
}
|
||||
if (MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST || MONITOR_HOME_TO_FOREIGN_BLOCK_LIST) {
|
||||
const onlyInHomeDeposits = homeToForeignRequests.filter(eventWithoutReference(homeToForeignConfirmations))
|
||||
if (MONITOR_HOME_TO_FOREIGN_CHECK_SENDER === 'true') {
|
||||
for (let i = 0; i < onlyInHomeDeposits.length; i++) {
|
||||
onlyInHomeDeposits[i].sender = await getHomeTxSender(onlyInHomeDeposits[i].transactionHash)
|
||||
}
|
||||
}
|
||||
|
||||
const unclaimedPool = onlyInHomeDeposits.filter(unclaimedHomeToForeignRequests())
|
||||
|
||||
stats.depositsDiff -= unclaimedPool.length
|
||||
stats.unclaimedDiff = unclaimedPool.length
|
||||
stats.unclaimedBalance = Web3Utils.fromWei(BN.sum(0, ...unclaimedPool.map(e => e.value)).toFixed())
|
||||
}
|
||||
return {
|
||||
...stats,
|
||||
home: {
|
||||
deposits: homeToForeignRequests.length,
|
||||
withdrawals: foreignToHomeConfirmations.length
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
require('dotenv').config()
|
||||
const express = require('express')
|
||||
const cors = require('cors')
|
||||
const { readFile } = require('./utils/file')
|
||||
|
||||
const app = express()
|
||||
const bridgeRouter = express.Router({ mergeParams: true })
|
||||
|
||||
app.use(cors())
|
||||
|
||||
app.get('/favicon.ico', (req, res) => res.sendStatus(204))
|
||||
app.use('/:bridgeName', bridgeRouter)
|
||||
|
||||
|
||||
@@ -14,14 +14,15 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"bignumber.js": "^6.0.0",
|
||||
"bignumber.js": "^9.0.1",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^5.0.1",
|
||||
"express": "^4.16.3",
|
||||
"node-fetch": "^2.1.2",
|
||||
"web3": "1.0.0-beta.34"
|
||||
"web3": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.9"
|
||||
"node": ">= 10.18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^4.2.0"
|
||||
|
||||
@@ -2,17 +2,21 @@
|
||||
|
||||
CONFIGDIR="configs"
|
||||
RESPONSESDIR="responses"
|
||||
ACLDIR="access-lists"
|
||||
ALLOWANCEFILE="allowance_list.txt"
|
||||
BLOCKFILE="block_list.txt"
|
||||
CACHEDIR="cache"
|
||||
IMAGETAG="latest"
|
||||
|
||||
cd $(dirname $0)/..
|
||||
|
||||
if /usr/local/bin/docker-compose ps | grep -q -i 'monitor'; then
|
||||
tstart=`date +"%s"`
|
||||
|
||||
|
||||
for file in ${CONFIGDIR}/*.env
|
||||
do
|
||||
echo "${file} handling..."
|
||||
|
||||
|
||||
bridgename=`source ${file} && echo ${MONITOR_BRIDGE_NAME}`
|
||||
reportdir=${RESPONSESDIR}"/"${bridgename}
|
||||
if [ ! -d ${reportdir} ]; then
|
||||
@@ -26,10 +30,18 @@ if /usr/local/bin/docker-compose ps | grep -q -i 'monitor'; then
|
||||
fi
|
||||
done
|
||||
|
||||
alist=`source ${file} && echo ${MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST}`
|
||||
blist=`source ${file} && echo ${MONITOR_HOME_TO_FOREIGN_BLOCK_LIST}`
|
||||
al_param="$(pwd)/${ACLDIR}/${bridgename}/${ALLOWANCEFILE}:/mono/monitor/access-lists/allowance_list.txt"
|
||||
bl_param="$(pwd)/${ACLDIR}/${bridgename}/${BLOCKFILE}:/mono/monitor/access-lists/block_list.txt"
|
||||
|
||||
containername=${bridgename}"-checker"
|
||||
docker container stats --no-stream ${containername} 2>/dev/null 1>&2
|
||||
if [ ! "$?" == "0" ]; then
|
||||
mkdir -p "$(pwd)/$CACHEDIR/$bridgename"
|
||||
docker run --rm --env-file $file -v $(pwd)/${RESPONSESDIR}:/mono/monitor/responses \
|
||||
${alist:+"-v"} ${alist:+"$al_param"} ${blist:+"-v"} ${blist:+"$bl_param"} \
|
||||
-v $(pwd)/${CACHEDIR}/${bridgename}:/mono/monitor/cache/${bridgename} \
|
||||
--name ${containername} poanetwork/tokenbridge-monitor:${IMAGETAG} \
|
||||
/bin/bash -c 'yarn check-all'
|
||||
shasum -a 256 -s -c ${checksumfile}
|
||||
@@ -46,15 +58,15 @@ if /usr/local/bin/docker-compose ps | grep -q -i 'monitor'; then
|
||||
else
|
||||
echo "${containername} have not finished yet" >&2
|
||||
fi
|
||||
|
||||
|
||||
rm ${checksumfile}
|
||||
echo "========================================"
|
||||
done
|
||||
|
||||
|
||||
tend=`date +"%s"`
|
||||
tdiff=`expr ${tend} - ${tstart}`
|
||||
echo "Total time to run: ${tdiff}"
|
||||
|
||||
else
|
||||
echo "Monitor is not running, skipping checks."
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
require('dotenv').config()
|
||||
const Web3 = require('web3')
|
||||
const logger = require('./logger')('stuckTransfers.js')
|
||||
const { FOREIGN_V1_ABI } = require('../commons/abis')
|
||||
const { web3Foreign, getForeignBlockNumber } = require('./utils/web3')
|
||||
const { getPastEvents } = require('./utils/web3Cache')
|
||||
|
||||
const { COMMON_FOREIGN_RPC_URL, COMMON_FOREIGN_BRIDGE_ADDRESS } = process.env
|
||||
const { COMMON_FOREIGN_BRIDGE_ADDRESS } = process.env
|
||||
const MONITOR_FOREIGN_START_BLOCK = Number(process.env.MONITOR_FOREIGN_START_BLOCK) || 0
|
||||
|
||||
const foreignProvider = new Web3.providers.HttpProvider(COMMON_FOREIGN_RPC_URL)
|
||||
const web3Foreign = new Web3(foreignProvider)
|
||||
|
||||
const ABITransferWithoutData = [
|
||||
{
|
||||
anonymous: false,
|
||||
@@ -64,38 +62,39 @@ const ABIWithData = [
|
||||
}
|
||||
]
|
||||
|
||||
function compareTransfers(transfersNormal) {
|
||||
return withData => {
|
||||
return (
|
||||
transfersNormal.filter(normal => {
|
||||
return normal.transactionHash === withData.transactionHash
|
||||
}).length === 0
|
||||
)
|
||||
}
|
||||
function transferWithoutCallback(transfersNormal) {
|
||||
const txHashes = new Set()
|
||||
transfersNormal.forEach(transfer => txHashes.add(transfer.transactionHash))
|
||||
return withData => !txHashes.has(withData.transactionHash)
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_V1_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
logger.debug('calling foreignBridge.methods.erc677token')
|
||||
const erc20Address = await foreignBridge.methods.erc677token().call()
|
||||
const tokenContract = new web3Foreign.eth.Contract(ABITransferWithoutData, erc20Address)
|
||||
const tokenContractWithData = new web3Foreign.eth.Contract(ABIWithData, erc20Address)
|
||||
logger.debug('getting last block number')
|
||||
const foreignBlockNumber = await getForeignBlockNumber()
|
||||
const foreignConfirmations = await foreignBridge.methods.requiredBlockConfirmations().call()
|
||||
const foreignDelayedBlockNumber = foreignBlockNumber - foreignConfirmations
|
||||
logger.debug('calling tokenContract.getPastEvents Transfer')
|
||||
const transfersNormal = await tokenContract.getPastEvents('Transfer', {
|
||||
filter: {
|
||||
to: COMMON_FOREIGN_BRIDGE_ADDRESS
|
||||
const options = {
|
||||
event: 'Transfer',
|
||||
options: {
|
||||
filter: {
|
||||
to: COMMON_FOREIGN_BRIDGE_ADDRESS
|
||||
}
|
||||
},
|
||||
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
toBlock: foreignBlockNumber,
|
||||
chain: 'foreign',
|
||||
safeToBlock: foreignDelayedBlockNumber
|
||||
}
|
||||
const transfersNormal = await getPastEvents(tokenContract, options)
|
||||
logger.debug('calling tokenContractWithData.getPastEvents Transfer')
|
||||
const transfersWithData = await tokenContractWithData.getPastEvents('Transfer', {
|
||||
filter: {
|
||||
to: COMMON_FOREIGN_BRIDGE_ADDRESS
|
||||
},
|
||||
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
const stuckTransfers = transfersNormal.filter(compareTransfers(transfersWithData))
|
||||
const transfersWithData = await getPastEvents(tokenContractWithData, options)
|
||||
const stuckTransfers = transfersNormal.filter(transferWithoutCallback(transfersWithData))
|
||||
logger.debug('Done')
|
||||
return {
|
||||
stuckTransfers,
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
const { toBN } = require('web3').utils
|
||||
|
||||
const getBlockNumberCall = web3 => web3.eth.getBlockNumber()
|
||||
|
||||
async function getBlockNumber(web3Home, web3Foreign) {
|
||||
return (await Promise.all([web3Home, web3Foreign].map(getBlockNumberCall))).map(toBN)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getBlockNumber
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
require('dotenv').config()
|
||||
const Web3 = require('web3')
|
||||
const { toBN } = require('web3').utils
|
||||
const logger = require('../logger')('eventsUtils')
|
||||
const {
|
||||
BRIDGE_MODES,
|
||||
@@ -11,7 +9,6 @@ const {
|
||||
ERC20_ABI,
|
||||
ERC677_BRIDGE_TOKEN_ABI,
|
||||
getTokenType,
|
||||
getPastEvents,
|
||||
ZERO_ADDRESS,
|
||||
OLD_AMB_USER_REQUEST_FOR_SIGNATURE_ABI,
|
||||
OLD_AMB_USER_REQUEST_FOR_AFFIRMATION_ABI
|
||||
@@ -19,24 +16,12 @@ const {
|
||||
const { normalizeEventInformation } = require('./message')
|
||||
const { filterTransferBeforeES } = require('./tokenUtils')
|
||||
const { writeFile, readCacheFile } = require('./file')
|
||||
const { web3Home, web3Foreign, getHomeBlockNumber, getForeignBlockNumber } = require('./web3')
|
||||
const { getPastEvents } = require('./web3Cache')
|
||||
|
||||
const {
|
||||
COMMON_HOME_RPC_URL,
|
||||
COMMON_FOREIGN_RPC_URL,
|
||||
COMMON_HOME_BRIDGE_ADDRESS,
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS,
|
||||
MONITOR_CACHE_EVENTS
|
||||
} = process.env
|
||||
const MONITOR_HOME_START_BLOCK = toBN(Number(process.env.MONITOR_HOME_START_BLOCK) || 0)
|
||||
const MONITOR_FOREIGN_START_BLOCK = toBN(Number(process.env.MONITOR_FOREIGN_START_BLOCK) || 0)
|
||||
|
||||
const homeProvider = new Web3.providers.HttpProvider(COMMON_HOME_RPC_URL)
|
||||
const web3Home = new Web3(homeProvider)
|
||||
|
||||
const foreignProvider = new Web3.providers.HttpProvider(COMMON_FOREIGN_RPC_URL)
|
||||
const web3Foreign = new Web3(foreignProvider)
|
||||
|
||||
const { getBlockNumber } = require('./contract')
|
||||
const { COMMON_HOME_BRIDGE_ADDRESS, COMMON_FOREIGN_BRIDGE_ADDRESS, MONITOR_CACHE_EVENTS } = process.env
|
||||
const MONITOR_HOME_START_BLOCK = Number(process.env.MONITOR_HOME_START_BLOCK) || 0
|
||||
const MONITOR_FOREIGN_START_BLOCK = Number(process.env.MONITOR_FOREIGN_START_BLOCK) || 0
|
||||
|
||||
const cacheFilePath = '/tmp/cachedEvents.json'
|
||||
async function main(mode) {
|
||||
@@ -73,7 +58,13 @@ async function main(mode) {
|
||||
}
|
||||
|
||||
logger.debug('getting last block numbers')
|
||||
const [homeBlockNumber, foreignBlockNumber] = await getBlockNumber(web3Home, web3Foreign)
|
||||
const homeBlockNumber = await getHomeBlockNumber()
|
||||
const foreignBlockNumber = await getForeignBlockNumber()
|
||||
const homeConfirmations = await homeBridge.methods.requiredBlockConfirmations().call()
|
||||
const foreignConfirmations = await foreignBridge.methods.requiredBlockConfirmations().call()
|
||||
const homeDelayedBlockNumber = homeBlockNumber - homeConfirmations
|
||||
const foreignDelayedBlockNumber = foreignBlockNumber - foreignConfirmations
|
||||
|
||||
let homeToForeignRequests = []
|
||||
let foreignToHomeRequests = []
|
||||
let homeMigrationBlock = MONITOR_HOME_START_BLOCK
|
||||
@@ -90,22 +81,24 @@ async function main(mode) {
|
||||
homeToForeignRequests = (await getPastEvents(oldHomeBridge, {
|
||||
event: 'UserRequestForSignature',
|
||||
fromBlock: MONITOR_HOME_START_BLOCK,
|
||||
toBlock: homeBlockNumber
|
||||
toBlock: homeDelayedBlockNumber,
|
||||
chain: 'home'
|
||||
})).map(normalizeEvent)
|
||||
logger.debug(`found ${homeToForeignRequests.length} events`)
|
||||
if (homeToForeignRequests.length > 0) {
|
||||
homeMigrationBlock = toBN(Math.max(...homeToForeignRequests.map(x => x.blockNumber)))
|
||||
homeMigrationBlock = Math.max(...homeToForeignRequests.map(x => x.blockNumber))
|
||||
}
|
||||
|
||||
logger.debug("calling oldForeignBridge.getPastEvents('UserRequestForAffirmation(bytes)')")
|
||||
foreignToHomeRequests = (await getPastEvents(oldForeignBridge, {
|
||||
event: 'UserRequestForAffirmation',
|
||||
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
||||
toBlock: foreignBlockNumber
|
||||
toBlock: foreignDelayedBlockNumber,
|
||||
chain: 'foreign'
|
||||
})).map(normalizeEvent)
|
||||
logger.debug(`found ${foreignToHomeRequests.length} events`)
|
||||
if (foreignToHomeRequests.length > 0) {
|
||||
foreignMigrationBlock = toBN(Math.max(...foreignToHomeRequests.map(x => x.blockNumber)))
|
||||
foreignMigrationBlock = Math.max(...foreignToHomeRequests.map(x => x.blockNumber))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +106,8 @@ async function main(mode) {
|
||||
const homeToForeignRequestsNew = (await getPastEvents(homeBridge, {
|
||||
event: v1Bridge ? 'Deposit' : 'UserRequestForSignature',
|
||||
fromBlock: homeMigrationBlock,
|
||||
toBlock: homeBlockNumber
|
||||
toBlock: homeDelayedBlockNumber,
|
||||
chain: 'home'
|
||||
})).map(normalizeEvent)
|
||||
homeToForeignRequests = [...homeToForeignRequests, ...homeToForeignRequestsNew]
|
||||
|
||||
@@ -121,21 +115,26 @@ async function main(mode) {
|
||||
const homeToForeignConfirmations = (await getPastEvents(foreignBridge, {
|
||||
event: v1Bridge ? 'Deposit' : 'RelayedMessage',
|
||||
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
||||
toBlock: foreignBlockNumber
|
||||
toBlock: foreignBlockNumber,
|
||||
chain: 'foreign',
|
||||
safeToBlock: foreignDelayedBlockNumber
|
||||
})).map(normalizeEvent)
|
||||
|
||||
logger.debug("calling homeBridge.getPastEvents('AffirmationCompleted')")
|
||||
const foreignToHomeConfirmations = (await getPastEvents(homeBridge, {
|
||||
event: v1Bridge ? 'Withdraw' : 'AffirmationCompleted',
|
||||
fromBlock: MONITOR_HOME_START_BLOCK,
|
||||
toBlock: homeBlockNumber
|
||||
toBlock: homeBlockNumber,
|
||||
chain: 'home',
|
||||
safeToBlock: homeDelayedBlockNumber
|
||||
})).map(normalizeEvent)
|
||||
|
||||
logger.debug("calling foreignBridge.getPastEvents('UserRequestForAffirmation')")
|
||||
const foreignToHomeRequestsNew = (await getPastEvents(foreignBridge, {
|
||||
event: v1Bridge ? 'Withdraw' : 'UserRequestForAffirmation',
|
||||
fromBlock: foreignMigrationBlock,
|
||||
toBlock: foreignBlockNumber
|
||||
toBlock: foreignDelayedBlockNumber,
|
||||
chain: 'foreign'
|
||||
})).map(normalizeEvent)
|
||||
foreignToHomeRequests = [...foreignToHomeRequests, ...foreignToHomeRequestsNew]
|
||||
|
||||
@@ -144,10 +143,11 @@ async function main(mode) {
|
||||
let transferEvents = (await getPastEvents(erc20Contract, {
|
||||
event: 'Transfer',
|
||||
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
||||
toBlock: foreignBlockNumber,
|
||||
toBlock: foreignDelayedBlockNumber,
|
||||
options: {
|
||||
filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS }
|
||||
}
|
||||
},
|
||||
chain: 'foreign'
|
||||
})).map(normalizeEvent)
|
||||
|
||||
let directTransfers = transferEvents
|
||||
@@ -158,7 +158,9 @@ async function main(mode) {
|
||||
const tokensSwappedEvents = await getPastEvents(foreignBridge, {
|
||||
event: 'TokensSwapped',
|
||||
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
||||
toBlock: foreignBlockNumber
|
||||
toBlock: foreignBlockNumber,
|
||||
chain: 'foreign',
|
||||
safeToBlock: foreignDelayedBlockNumber
|
||||
})
|
||||
|
||||
// Get token swap events emitted by foreign bridge
|
||||
@@ -194,10 +196,11 @@ async function main(mode) {
|
||||
const halfDuplexTransferEvents = (await getPastEvents(halfDuplexTokenContract, {
|
||||
event: 'Transfer',
|
||||
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
||||
toBlock: foreignBlockNumber,
|
||||
toBlock: foreignDelayedBlockNumber,
|
||||
options: {
|
||||
filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS }
|
||||
}
|
||||
},
|
||||
chain: 'foreign'
|
||||
})).map(normalizeEvent)
|
||||
|
||||
// Remove events after the ES
|
||||
@@ -232,7 +235,9 @@ async function main(mode) {
|
||||
foreignToHomeConfirmations,
|
||||
foreignToHomeRequests,
|
||||
isExternalErc20,
|
||||
bridgeMode
|
||||
bridgeMode,
|
||||
homeDelayedBlockNumber,
|
||||
foreignDelayedBlockNumber
|
||||
}
|
||||
|
||||
if (MONITOR_CACHE_EVENTS === 'true') {
|
||||
|
||||
@@ -38,9 +38,25 @@ function readCacheFile(filePath) {
|
||||
}
|
||||
}
|
||||
|
||||
function writeCacheFile(filePath, object) {
|
||||
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
||||
fs.writeFileSync(filePath, JSON.stringify(object))
|
||||
}
|
||||
|
||||
function readAccessListFile(filePath) {
|
||||
const data = fs.readFileSync(filePath)
|
||||
return data
|
||||
.toString()
|
||||
.split('\n')
|
||||
.map(addr => addr.trim().toLowerCase())
|
||||
.filter(addr => addr.length === 42)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
readFile,
|
||||
writeFile,
|
||||
createDir,
|
||||
readCacheFile
|
||||
readCacheFile,
|
||||
writeCacheFile,
|
||||
readAccessListFile
|
||||
}
|
||||
|
||||
93
monitor/utils/getValidatorsList.js
Normal file
93
monitor/utils/getValidatorsList.js
Normal file
@@ -0,0 +1,93 @@
|
||||
const { REWARDABLE_VALIDATORS_ABI, processValidatorsEvents } = require('../../commons')
|
||||
const { getPastEvents } = require('./web3Cache')
|
||||
|
||||
const VALIDATORS_INDEXED_EVENTS_ABI = [
|
||||
{
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{
|
||||
indexed: true,
|
||||
name: 'validator',
|
||||
type: 'address'
|
||||
}
|
||||
],
|
||||
name: 'ValidatorRemoved',
|
||||
type: 'event'
|
||||
},
|
||||
{
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{
|
||||
indexed: true,
|
||||
name: 'validator',
|
||||
type: 'address'
|
||||
}
|
||||
],
|
||||
name: 'ValidatorAdded',
|
||||
type: 'event'
|
||||
},
|
||||
{
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{
|
||||
indexed: true,
|
||||
name: 'validator',
|
||||
type: 'address'
|
||||
},
|
||||
{
|
||||
indexed: true,
|
||||
name: 'reward',
|
||||
type: 'address'
|
||||
}
|
||||
],
|
||||
name: 'ValidatorAdded',
|
||||
type: 'event'
|
||||
}
|
||||
]
|
||||
|
||||
const tryCall = async (method, fallbackValue) => {
|
||||
try {
|
||||
return await method.call()
|
||||
} catch (e) {
|
||||
return fallbackValue
|
||||
}
|
||||
}
|
||||
|
||||
const getValidatorList = async (address, eth, options) => {
|
||||
const { logger } = options
|
||||
logger.debug('getting validatorList')
|
||||
|
||||
const validatorsContract = new eth.Contract(REWARDABLE_VALIDATORS_ABI, address) // in monitor, BRIDGE_VALIDATORS_ABI was used
|
||||
const validators = await tryCall(validatorsContract.methods.validatorList(), [])
|
||||
|
||||
if (validators.length) {
|
||||
return validators
|
||||
}
|
||||
|
||||
logger.debug('getting validatorsEvents')
|
||||
|
||||
options.fromBlock = Number(await tryCall(validatorsContract.methods.deployedAtBlock(), 0))
|
||||
|
||||
const contract = new eth.Contract(VALIDATORS_INDEXED_EVENTS_ABI, address)
|
||||
|
||||
const validatorsEvents = [
|
||||
...(await getPastEvents(contract, {
|
||||
event: 'ValidatorAdded(address)',
|
||||
...options
|
||||
})),
|
||||
...(await getPastEvents(contract, {
|
||||
event: 'ValidatorAdded(address,address)',
|
||||
...options
|
||||
})),
|
||||
...(await getPastEvents(contract, {
|
||||
event: 'ValidatorRemoved(address)',
|
||||
...options
|
||||
}))
|
||||
].sort((a, b) => a.blockNumber - b.blockNumber || a.transactionIndex - b.transactionIndex)
|
||||
|
||||
return processValidatorsEvents(validatorsEvents)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getValidatorList
|
||||
}
|
||||
@@ -1,44 +1,30 @@
|
||||
const web3Utils = require('web3').utils
|
||||
const { parseAMBMessage } = require('../../commons')
|
||||
const { readAccessListFile } = require('./file')
|
||||
|
||||
const { MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST, MONITOR_HOME_TO_FOREIGN_BLOCK_LIST } = process.env
|
||||
|
||||
const keyAMB = e => [e.messageId, e.sender, e.executor].join(',').toLowerCase()
|
||||
|
||||
const normalizeAMBMessage = e => {
|
||||
let msgData = e.returnValues.encodedData
|
||||
if (!e.returnValues.messageId) {
|
||||
// append tx hash to an old message, where message id was not used
|
||||
// for old messages, e.messageId is a corresponding transactionHash
|
||||
msgData = e.transactionHash + msgData.slice(2)
|
||||
}
|
||||
return parseAMBMessage(msgData)
|
||||
}
|
||||
|
||||
function deliveredMsgNotProcessed(processedList) {
|
||||
return deliveredMsg => {
|
||||
let msgData = deliveredMsg.returnValues.encodedData
|
||||
if (!deliveredMsg.returnValues.messageId) {
|
||||
// append tx hash to an old message, where message id was not used
|
||||
msgData = deliveredMsg.transactionHash + msgData.slice(2)
|
||||
}
|
||||
const msg = parseAMBMessage(msgData)
|
||||
return (
|
||||
processedList.filter(processedMsg => {
|
||||
return messageEqualsEvent(msg, processedMsg.returnValues)
|
||||
}).length === 0
|
||||
)
|
||||
}
|
||||
const keys = new Set()
|
||||
processedList.forEach(processedMsg => keys.add(keyAMB(processedMsg.returnValues)))
|
||||
return deliveredMsg => !keys.has(keyAMB(normalizeAMBMessage(deliveredMsg)))
|
||||
}
|
||||
|
||||
function processedMsgNotDelivered(deliveredList) {
|
||||
return processedMsg => {
|
||||
return (
|
||||
deliveredList.filter(deliveredMsg => {
|
||||
let msgData = deliveredMsg.returnValues.encodedData
|
||||
if (!deliveredMsg.returnValues.messageId) {
|
||||
// append tx hash to an old message, where message id was not used
|
||||
msgData = deliveredMsg.transactionHash + msgData.slice(2)
|
||||
}
|
||||
const msg = parseAMBMessage(msgData)
|
||||
return messageEqualsEvent(msg, processedMsg.returnValues)
|
||||
}).length === 0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function messageEqualsEvent(parsedMsg, event) {
|
||||
return (
|
||||
web3Utils.toChecksumAddress(parsedMsg.sender) === event.sender &&
|
||||
web3Utils.toChecksumAddress(parsedMsg.executor) === event.executor &&
|
||||
parsedMsg.messageId === event.messageId // for an old messages, event.messageId is actually a transactionHash
|
||||
)
|
||||
const keys = new Set()
|
||||
deliveredList.forEach(deliveredMsg => keys.add(keyAMB(normalizeAMBMessage(deliveredMsg))))
|
||||
return processedMsg => !keys.has(keyAMB(processedMsg.returnValues))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,13 +46,49 @@ const normalizeEventInformation = event => ({
|
||||
value: event.returnValues.value
|
||||
})
|
||||
|
||||
const eventWithoutReference = otherSideEvents => e =>
|
||||
otherSideEvents.filter(a => a.referenceTx === e.referenceTx && a.recipient === e.recipient && a.value === e.value)
|
||||
.length === 0
|
||||
const key = e => [e.referenceTx, e.recipient, e.value].join(',').toLowerCase()
|
||||
|
||||
const eventWithoutReference = otherSideEvents => {
|
||||
const keys = new Set()
|
||||
otherSideEvents.forEach(e => keys.add(key(e)))
|
||||
return e => !keys.has(key(e))
|
||||
}
|
||||
|
||||
const unclaimedHomeToForeignRequests = () => {
|
||||
if (MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST) {
|
||||
const allowanceList = readAccessListFile(MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST)
|
||||
return e => !allowanceList.includes(e.recipient.toLowerCase()) && !(e.sender && allowanceList.includes(e.sender))
|
||||
} else if (MONITOR_HOME_TO_FOREIGN_BLOCK_LIST) {
|
||||
const blockList = readAccessListFile(MONITOR_HOME_TO_FOREIGN_BLOCK_LIST)
|
||||
return e => blockList.includes(e.recipient.toLowerCase()) || (e.sender && blockList.includes(e.sender))
|
||||
} else {
|
||||
return () => false
|
||||
}
|
||||
}
|
||||
|
||||
const manuallyProcessedAMBHomeToForeignRequests = () => {
|
||||
if (MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST) {
|
||||
const allowanceList = readAccessListFile(MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST)
|
||||
return e => {
|
||||
const { sender, executor, decodedDataType } = normalizeAMBMessage(e)
|
||||
return (!allowanceList.includes(sender) && !allowanceList.includes(executor)) || decodedDataType.manualLane
|
||||
}
|
||||
} else if (MONITOR_HOME_TO_FOREIGN_BLOCK_LIST) {
|
||||
const blockList = readAccessListFile(MONITOR_HOME_TO_FOREIGN_BLOCK_LIST)
|
||||
return e => {
|
||||
const { sender, executor, decodedDataType } = normalizeAMBMessage(e)
|
||||
return blockList.includes(sender) || blockList.includes(executor) || decodedDataType.manualLane
|
||||
}
|
||||
} else {
|
||||
return e => normalizeAMBMessage(e).decodedDataType.manualLane
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
deliveredMsgNotProcessed,
|
||||
processedMsgNotDelivered,
|
||||
normalizeEventInformation,
|
||||
eventWithoutReference
|
||||
eventWithoutReference,
|
||||
unclaimedHomeToForeignRequests,
|
||||
manuallyProcessedAMBHomeToForeignRequests
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
const Web3 = require('web3')
|
||||
const { BRIDGE_MODES, getBridgeMode, HOME_ERC_TO_ERC_ABI } = require('../../commons')
|
||||
|
||||
const { COMMON_HOME_BRIDGE_ADDRESS, COMMON_HOME_RPC_URL } = process.env
|
||||
const homeProvider = new Web3.providers.HttpProvider(COMMON_HOME_RPC_URL)
|
||||
const web3Home = new Web3(homeProvider)
|
||||
|
||||
async function isV1Bridge() {
|
||||
const homeBridge = new web3Home.eth.Contract(HOME_ERC_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
||||
const bridgeMode = await getBridgeMode(homeBridge)
|
||||
return bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC_V1
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isV1Bridge
|
||||
}
|
||||
27
monitor/utils/web3.js
Normal file
27
monitor/utils/web3.js
Normal file
@@ -0,0 +1,27 @@
|
||||
require('dotenv').config()
|
||||
const Web3 = require('web3')
|
||||
|
||||
const { COMMON_HOME_RPC_URL, COMMON_FOREIGN_RPC_URL } = process.env
|
||||
|
||||
const homeProvider = new Web3.providers.HttpProvider(COMMON_HOME_RPC_URL)
|
||||
const web3Home = new Web3(homeProvider)
|
||||
|
||||
const foreignProvider = new Web3.providers.HttpProvider(COMMON_FOREIGN_RPC_URL)
|
||||
const web3Foreign = new Web3(foreignProvider)
|
||||
|
||||
function blockNumberWrapper(web3) {
|
||||
let blockNumber = null
|
||||
return async () => {
|
||||
if (!blockNumber) {
|
||||
blockNumber = await web3.eth.getBlockNumber()
|
||||
}
|
||||
return blockNumber
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
web3Home,
|
||||
web3Foreign,
|
||||
getHomeBlockNumber: blockNumberWrapper(web3Home),
|
||||
getForeignBlockNumber: blockNumberWrapper(web3Foreign)
|
||||
}
|
||||
133
monitor/utils/web3Cache.js
Normal file
133
monitor/utils/web3Cache.js
Normal file
@@ -0,0 +1,133 @@
|
||||
const logger = require('../logger')('web3Cache')
|
||||
const { readCacheFile, writeCacheFile } = require('./file')
|
||||
const { web3Home } = require('./web3')
|
||||
const { getPastEvents: commonGetPastEvents } = require('../../commons')
|
||||
|
||||
const { MONITOR_BRIDGE_NAME, MONITOR_CACHE_EVENTS } = process.env
|
||||
|
||||
let isDirty = false
|
||||
|
||||
const homeTxSendersCacheFile = `./cache/${MONITOR_BRIDGE_NAME}/home/txSenders.json`
|
||||
const cachedHomeTxSenders = readCacheFile(homeTxSendersCacheFile) || {}
|
||||
|
||||
async function getHomeTxSender(txHash) {
|
||||
if (!cachedHomeTxSenders[txHash]) {
|
||||
logger.debug(`Fetching sender for tx ${txHash}`)
|
||||
cachedHomeTxSenders[txHash] = (await web3Home.eth.getTransaction(txHash)).from.toLowerCase()
|
||||
isDirty = true
|
||||
}
|
||||
return cachedHomeTxSenders[txHash]
|
||||
}
|
||||
|
||||
async function getPastEvents(contract, options) {
|
||||
if (MONITOR_CACHE_EVENTS !== 'true') {
|
||||
return commonGetPastEvents(contract, options)
|
||||
}
|
||||
|
||||
const contractAddr = contract.options.address
|
||||
|
||||
let eventSignature
|
||||
if (options.event.includes('(')) {
|
||||
eventSignature = options.event
|
||||
options.event = web3Home.utils.sha3(eventSignature)
|
||||
const eventABI = contract.options.jsonInterface.find(e => e.type === 'event' && e.signature === options.event)
|
||||
if (!eventABI) {
|
||||
throw new Error(`Event ${eventSignature} not found`)
|
||||
}
|
||||
} else {
|
||||
const eventABI = contract.options.jsonInterface.find(
|
||||
e => e.type === 'event' && (e.name === options.event || e.signature === options.event)
|
||||
)
|
||||
if (!eventABI) {
|
||||
throw new Error(`Event ${options.event} not found`)
|
||||
}
|
||||
eventSignature = `${eventABI.name}(${eventABI.inputs.map(i => i.type).join(',')})`
|
||||
}
|
||||
|
||||
const cacheFile = `./cache/${MONITOR_BRIDGE_NAME}/${options.chain}/${contractAddr}/${eventSignature}.json`
|
||||
|
||||
const { fromBlock, toBlock } = options
|
||||
const { fromBlock: cachedFromBlock, toBlock: cachedToBlock, events: cachedEvents } = readCacheFile(cacheFile) || {
|
||||
fromBlock: 0,
|
||||
toBlock: 0,
|
||||
events: []
|
||||
}
|
||||
|
||||
let result
|
||||
if (cachedFromBlock > toBlock || fromBlock > cachedToBlock) {
|
||||
// requested: A...B
|
||||
// cached: C...D
|
||||
// OR
|
||||
// requested: A...B
|
||||
// cached: C...D
|
||||
logger.debug(`Fetching events for blocks ${fromBlock}...${toBlock}`)
|
||||
result = await commonGetPastEvents(contract, options)
|
||||
} else if (fromBlock < cachedFromBlock && toBlock <= cachedToBlock) {
|
||||
// requested: A...B
|
||||
// cached: C...D
|
||||
logger.debug(`Cache hit for blocks ${cachedFromBlock}...${toBlock}`)
|
||||
logger.debug(`Fetching events for blocks ${fromBlock}...${cachedFromBlock - 1}`)
|
||||
result = [
|
||||
...(await commonGetPastEvents(contract, { ...options, toBlock: cachedFromBlock - 1 })),
|
||||
...cachedEvents.filter(e => e.blockNumber <= toBlock)
|
||||
]
|
||||
} else if (fromBlock < cachedFromBlock && cachedToBlock < toBlock) {
|
||||
// requested: A.....B
|
||||
// cached: C.D
|
||||
logger.debug(`Cache hit for blocks ${cachedFromBlock}...${cachedToBlock}`)
|
||||
logger.debug(`Fetching events for blocks ${fromBlock}...${cachedFromBlock - 1}`)
|
||||
logger.debug(`Fetching events for blocks ${cachedToBlock + 1}...${toBlock}`)
|
||||
result = [
|
||||
...(await commonGetPastEvents(contract, { ...options, toBlock: cachedFromBlock - 1 })),
|
||||
...cachedEvents,
|
||||
...(await commonGetPastEvents(contract, { ...options, fromBlock: cachedToBlock + 1 }))
|
||||
]
|
||||
} else if (cachedFromBlock <= fromBlock && toBlock <= cachedToBlock) {
|
||||
// requested: A.B
|
||||
// cached: C.....D
|
||||
logger.debug(`Cache hit for blocks ${fromBlock}...${toBlock}`)
|
||||
result = cachedEvents.filter(e => fromBlock <= e.blockNumber && e.blockNumber <= toBlock)
|
||||
} else if (fromBlock >= cachedFromBlock && toBlock > cachedToBlock) {
|
||||
// requested: A...B
|
||||
// cached: C...D
|
||||
logger.debug(`Cache hit for blocks ${fromBlock}...${cachedToBlock}`)
|
||||
logger.debug(`Fetching events for blocks ${cachedToBlock + 1}...${toBlock}`)
|
||||
result = [
|
||||
...cachedEvents.filter(e => e.blockNumber >= fromBlock),
|
||||
...(await commonGetPastEvents(contract, { ...options, fromBlock: cachedToBlock + 1 }))
|
||||
]
|
||||
} else {
|
||||
throw new Error(
|
||||
`Something is broken with cache resolution for getPastEvents,
|
||||
requested blocks ${fromBlock}...${toBlock},
|
||||
cached blocks ${cachedFromBlock}...${cachedToBlock}`
|
||||
)
|
||||
}
|
||||
|
||||
// it is not safe to cache events with too low block confirmations
|
||||
// so, only events from finalized blocks are included into the cache
|
||||
const safeToBlock = options.safeToBlock || toBlock
|
||||
const cacheToSave = result.filter(e => e.blockNumber <= safeToBlock)
|
||||
logger.debug(
|
||||
`Saving events cache for ${MONITOR_BRIDGE_NAME}/${options.chain}/${contractAddr}/${eventSignature} on disk`
|
||||
)
|
||||
writeCacheFile(cacheFile, {
|
||||
fromBlock,
|
||||
toBlock: safeToBlock,
|
||||
events: cacheToSave
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
function saveCache() {
|
||||
if (isDirty) {
|
||||
logger.debug('Saving cache on disk')
|
||||
writeCacheFile(homeTxSendersCacheFile, cachedHomeTxSenders)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getHomeTxSender,
|
||||
getPastEvents,
|
||||
saveCache
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
require('dotenv').config()
|
||||
const Web3 = require('web3')
|
||||
const Web3Utils = require('web3').utils
|
||||
const fetch = require('node-fetch')
|
||||
const logger = require('./logger')('validators')
|
||||
const { getBridgeABIs, BRIDGE_VALIDATORS_ABI, getValidatorList, gasPriceFromSupplier } = require('../commons')
|
||||
const { getBlockNumber } = require('./utils/contract')
|
||||
const { getBridgeABIs, BRIDGE_VALIDATORS_ABI, gasPriceFromSupplier } = require('../commons')
|
||||
const { web3Home, web3Foreign, getHomeBlockNumber, getForeignBlockNumber } = require('./utils/web3')
|
||||
const { getValidatorList } = require('./utils/getValidatorsList')
|
||||
|
||||
const {
|
||||
COMMON_HOME_RPC_URL,
|
||||
COMMON_FOREIGN_RPC_URL,
|
||||
COMMON_HOME_BRIDGE_ADDRESS,
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS,
|
||||
COMMON_HOME_GAS_PRICE_SUPPLIER_URL,
|
||||
@@ -19,19 +18,9 @@ const {
|
||||
COMMON_FOREIGN_GAS_PRICE_FALLBACK,
|
||||
COMMON_FOREIGN_GAS_PRICE_FACTOR
|
||||
} = process.env
|
||||
const MONITOR_HOME_START_BLOCK = Number(process.env.MONITOR_HOME_START_BLOCK) || 0
|
||||
const MONITOR_FOREIGN_START_BLOCK = Number(process.env.MONITOR_FOREIGN_START_BLOCK) || 0
|
||||
const MONITOR_VALIDATOR_HOME_TX_LIMIT = Number(process.env.MONITOR_VALIDATOR_HOME_TX_LIMIT) || 0
|
||||
const MONITOR_VALIDATOR_FOREIGN_TX_LIMIT = Number(process.env.MONITOR_VALIDATOR_FOREIGN_TX_LIMIT) || 0
|
||||
|
||||
const Web3Utils = Web3.utils
|
||||
|
||||
const homeProvider = new Web3.providers.HttpProvider(COMMON_HOME_RPC_URL)
|
||||
const web3Home = new Web3(homeProvider)
|
||||
|
||||
const foreignProvider = new Web3.providers.HttpProvider(COMMON_FOREIGN_RPC_URL)
|
||||
const web3Foreign = new Web3(foreignProvider)
|
||||
|
||||
const homeGasPriceSupplierOpts = {
|
||||
speedType: COMMON_HOME_GAS_PRICE_SPEED_TYPE,
|
||||
factor: COMMON_HOME_GAS_PRICE_FACTOR,
|
||||
@@ -58,7 +47,12 @@ async function main(bridgeMode) {
|
||||
const homeBridgeValidators = new web3Home.eth.Contract(BRIDGE_VALIDATORS_ABI, homeValidatorsAddress)
|
||||
|
||||
logger.debug('getting last block numbers')
|
||||
const [homeBlockNumber, foreignBlockNumber] = await getBlockNumber(web3Home, web3Foreign)
|
||||
const homeBlockNumber = await getHomeBlockNumber()
|
||||
const foreignBlockNumber = await getForeignBlockNumber()
|
||||
const homeConfirmations = await homeBridge.methods.requiredBlockConfirmations().call()
|
||||
const foreignConfirmations = await foreignBridge.methods.requiredBlockConfirmations().call()
|
||||
const homeDelayedBlockNumber = homeBlockNumber - homeConfirmations
|
||||
const foreignDelayedBlockNumber = foreignBlockNumber - foreignConfirmations
|
||||
|
||||
logger.debug('calling foreignBridge.methods.validatorContract().call()')
|
||||
const foreignValidatorsAddress = await foreignBridge.methods.validatorContract().call()
|
||||
@@ -66,16 +60,18 @@ async function main(bridgeMode) {
|
||||
|
||||
logger.debug('calling foreignBridgeValidators getValidatorList()')
|
||||
const foreignValidators = (await getValidatorList(foreignValidatorsAddress, web3Foreign.eth, {
|
||||
from: MONITOR_FOREIGN_START_BLOCK,
|
||||
to: foreignBlockNumber,
|
||||
logger
|
||||
toBlock: foreignBlockNumber,
|
||||
logger,
|
||||
chain: 'foreign',
|
||||
safeToBlock: foreignDelayedBlockNumber
|
||||
})).map(web3Foreign.utils.toChecksumAddress)
|
||||
|
||||
logger.debug('calling homeBridgeValidators getValidatorList()')
|
||||
const homeValidators = (await getValidatorList(homeValidatorsAddress, web3Home.eth, {
|
||||
from: MONITOR_HOME_START_BLOCK,
|
||||
to: homeBlockNumber,
|
||||
logger
|
||||
toBlock: homeBlockNumber,
|
||||
logger,
|
||||
chain: 'home',
|
||||
safeToBlock: homeDelayedBlockNumber
|
||||
})).map(web3Home.utils.toChecksumAddress)
|
||||
|
||||
const foreignVBalances = {}
|
||||
@@ -100,8 +96,13 @@ async function main(bridgeMode) {
|
||||
|
||||
if (MONITOR_VALIDATOR_FOREIGN_TX_LIMIT) {
|
||||
logger.debug('calling foreign getGasPrices')
|
||||
const fetchFn =
|
||||
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL === 'gas-price-oracle'
|
||||
? null
|
||||
: () => fetch(COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL)
|
||||
|
||||
foreignGasPrice =
|
||||
(await gasPriceFromSupplier(() => fetch(COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL), foreignGasPriceSupplierOpts)) ||
|
||||
(await gasPriceFromSupplier(fetchFn, foreignGasPriceSupplierOpts)) ||
|
||||
Web3Utils.toBN(COMMON_FOREIGN_GAS_PRICE_FALLBACK)
|
||||
foreignGasPriceGwei = Web3Utils.fromWei(foreignGasPrice.toString(), 'gwei')
|
||||
foreignTxCost = foreignGasPrice.mul(Web3Utils.toBN(MONITOR_VALIDATOR_FOREIGN_TX_LIMIT))
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"websocket": "^1.0.28"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.9"
|
||||
"node": ">= 10.18"
|
||||
},
|
||||
"devDependencies": {}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,24 @@
|
||||
cd $(dirname $0)
|
||||
|
||||
../e2e-commons/up.sh deploy blocks oracle oracle-validator-2 oracle-validator-3
|
||||
mode="$1"
|
||||
case "$mode" in
|
||||
amb)
|
||||
script=./test/amb.js
|
||||
;;
|
||||
native-to-erc)
|
||||
script=./test/nativeToErc.js
|
||||
;;
|
||||
erc-to-erc)
|
||||
script=./test/ercToErc.js
|
||||
;;
|
||||
erc-to-native)
|
||||
script=./test/ercToNative.js
|
||||
;;
|
||||
esac
|
||||
|
||||
docker-compose -f ../e2e-commons/docker-compose.yml run e2e yarn workspace oracle-e2e run start
|
||||
MODE="$mode" ../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 $script
|
||||
rc=$?
|
||||
|
||||
../e2e-commons/down.sh
|
||||
|
||||
@@ -3,7 +3,7 @@ const assert = require('assert')
|
||||
const { user, homeRPC, foreignRPC, amb, validator } = require('../../e2e-commons/constants.json')
|
||||
const { uniformRetry } = require('../../e2e-commons/utils')
|
||||
const { BOX_ABI, HOME_AMB_ABI, FOREIGN_AMB_ABI } = require('../../commons')
|
||||
const { setRequiredSignatures } = require('./utils')
|
||||
const { delay, setRequiredSignatures } = require('./utils')
|
||||
|
||||
const { toBN } = Web3.utils
|
||||
|
||||
@@ -19,14 +19,17 @@ foreignWeb3.eth.accounts.wallet.add(user.privateKey)
|
||||
foreignWeb3.eth.accounts.wallet.add(validator.privateKey)
|
||||
|
||||
const homeBox = new homeWeb3.eth.Contract(BOX_ABI, amb.homeBox)
|
||||
const blockHomeBox = new homeWeb3.eth.Contract(BOX_ABI, amb.blockedHomeBox)
|
||||
const foreignBox = new foreignWeb3.eth.Contract(BOX_ABI, amb.foreignBox)
|
||||
const homeBridge = new homeWeb3.eth.Contract(HOME_AMB_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
||||
const foreignBridge = new foreignWeb3.eth.Contract(FOREIGN_AMB_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
|
||||
describe('arbitrary message bridging', () => {
|
||||
let requiredSignatures = 1
|
||||
before(async () => {
|
||||
// Only 1 validator is used in ultimate tests
|
||||
if (process.env.ULTIMATE !== 'true') {
|
||||
requiredSignatures = 2
|
||||
// Set 2 required signatures for home bridge
|
||||
await setRequiredSignatures({
|
||||
bridgeContract: homeBridge,
|
||||
@@ -76,6 +79,85 @@ describe('arbitrary message bridging', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// allowance/block lists files are not mounted to the host during the ultimate test
|
||||
if (process.env.ULTIMATE !== 'true') {
|
||||
it('should confirm but not relay message from blocked contract', async () => {
|
||||
const newValue = 4
|
||||
|
||||
const initialValue = await foreignBox.methods.value().call()
|
||||
assert(!toBN(initialValue).eq(toBN(newValue)), 'initial value should be different from new value')
|
||||
|
||||
const signatures = await homeBridge.getPastEvents('SignedForUserRequest', {
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
|
||||
await blockHomeBox.methods
|
||||
.setValueOnOtherNetwork(newValue, amb.home, amb.foreignBox)
|
||||
.send({
|
||||
from: user.address,
|
||||
gas: '400000'
|
||||
})
|
||||
.catch(e => {
|
||||
console.error(e)
|
||||
})
|
||||
|
||||
await delay(5000)
|
||||
|
||||
const newSignatures = await homeBridge.getPastEvents('SignedForUserRequest', {
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
|
||||
assert(
|
||||
newSignatures.length === signatures.length + requiredSignatures,
|
||||
`Incorrect amount of signatures submitted, got ${newSignatures.length}, expected ${signatures.length +
|
||||
requiredSignatures}`
|
||||
)
|
||||
|
||||
const value = await foreignBox.methods.value().call()
|
||||
assert(!toBN(value).eq(toBN(newValue)), 'Message should not be relayed by oracle automatically')
|
||||
})
|
||||
}
|
||||
|
||||
it('should confirm but not relay message from manual lane', async () => {
|
||||
const newValue = 5
|
||||
|
||||
const initialValue = await foreignBox.methods.value().call()
|
||||
assert(!toBN(initialValue).eq(toBN(newValue)), 'initial value should be different from new value')
|
||||
|
||||
const signatures = await homeBridge.getPastEvents('SignedForUserRequest', {
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
|
||||
await homeBox.methods
|
||||
.setValueOnOtherNetworkUsingManualLane(newValue, amb.home, amb.foreignBox)
|
||||
.send({
|
||||
from: user.address,
|
||||
gas: '400000'
|
||||
})
|
||||
.catch(e => {
|
||||
console.error(e)
|
||||
})
|
||||
|
||||
await delay(5000)
|
||||
|
||||
const newSignatures = await homeBridge.getPastEvents('SignedForUserRequest', {
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
|
||||
assert(
|
||||
newSignatures.length === signatures.length + requiredSignatures,
|
||||
`Incorrect amount of signatures submitted, got ${newSignatures.length}, expected ${signatures.length +
|
||||
requiredSignatures}`
|
||||
)
|
||||
|
||||
const value = await foreignBox.methods.value().call()
|
||||
assert(!toBN(value).eq(toBN(newValue)), 'Message should not be relayed by oracle automatically')
|
||||
})
|
||||
})
|
||||
})
|
||||
describe('Foreign to Home', () => {
|
||||
|
||||
@@ -4,13 +4,14 @@ const promiseRetry = require('promise-retry')
|
||||
const {
|
||||
user,
|
||||
secondUser,
|
||||
blockedUser,
|
||||
validator,
|
||||
ercToNativeBridge,
|
||||
homeRPC,
|
||||
foreignRPC
|
||||
} = require('../../e2e-commons/constants.json')
|
||||
const { ERC677_BRIDGE_TOKEN_ABI, FOREIGN_ERC_TO_NATIVE_ABI, HOME_ERC_TO_NATIVE_ABI } = require('../../commons')
|
||||
const { uniformRetry } = 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))
|
||||
@@ -22,6 +23,7 @@ const COMMON_FOREIGN_BRIDGE_ADDRESS = ercToNativeBridge.foreign
|
||||
const { toBN } = foreignWeb3.utils
|
||||
|
||||
homeWeb3.eth.accounts.wallet.add(user.privateKey)
|
||||
homeWeb3.eth.accounts.wallet.add(blockedUser.privateKey)
|
||||
homeWeb3.eth.accounts.wallet.add(validator.privateKey)
|
||||
foreignWeb3.eth.accounts.wallet.add(user.privateKey)
|
||||
foreignWeb3.eth.accounts.wallet.add(validator.privateKey)
|
||||
@@ -31,12 +33,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)
|
||||
|
||||
describe('erc to native', () => {
|
||||
let halfDuplexTokenAddress
|
||||
let halfDuplexToken
|
||||
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
|
||||
await setRequiredSignatures({
|
||||
bridgeContract: homeBridge,
|
||||
@@ -59,85 +56,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 () => {
|
||||
const balance = await erc20Token.methods.balanceOf(user.address).call()
|
||||
const originalBalanceOnHome = await homeWeb3.eth.getBalance(user.address)
|
||||
@@ -226,6 +144,47 @@ describe('erc to native', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
it('should not process transaction from blocked users', async () => {
|
||||
const originalBalance1 = await erc20Token.methods.balanceOf(user.address).call()
|
||||
const originalBalance2 = await erc20Token.methods.balanceOf(blockedUser.address).call()
|
||||
|
||||
// check that account has tokens in home chain
|
||||
const balance1 = await homeWeb3.eth.getBalance(user.address)
|
||||
const balance2 = await homeWeb3.eth.getBalance(blockedUser.address)
|
||||
assert(!toBN(balance1).isZero(), 'Account should have tokens')
|
||||
assert(!toBN(balance2).isZero(), 'Account should have tokens')
|
||||
|
||||
// send transaction to home bridge
|
||||
await homeWeb3.eth.sendTransaction({
|
||||
from: user.address,
|
||||
to: COMMON_HOME_BRIDGE_ADDRESS,
|
||||
gasPrice: '1',
|
||||
gas: '1000000',
|
||||
value: homeWeb3.utils.toWei('0.01')
|
||||
})
|
||||
|
||||
// send transaction to home bridge
|
||||
await homeWeb3.eth.sendTransaction({
|
||||
from: blockedUser.address,
|
||||
to: COMMON_HOME_BRIDGE_ADDRESS,
|
||||
gasPrice: '1',
|
||||
gas: '1000000',
|
||||
value: homeWeb3.utils.toWei('0.01')
|
||||
})
|
||||
|
||||
// check that balance increases
|
||||
await uniformRetry(async retry => {
|
||||
const balance = await erc20Token.methods.balanceOf(user.address).call()
|
||||
if (toBN(balance).lte(toBN(originalBalance1))) {
|
||||
retry()
|
||||
}
|
||||
})
|
||||
|
||||
await sleep(3000)
|
||||
|
||||
const balance = await erc20Token.methods.balanceOf(blockedUser.address).call()
|
||||
assert(toBN(balance).eq(toBN(originalBalance2)), 'Bridge should not process collected signatures from blocked user')
|
||||
})
|
||||
it('should not invest dai when chai token is disabled', async () => {
|
||||
const bridgeDaiTokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
const { BRIDGE_VALIDATORS_ABI } = require('../../commons')
|
||||
|
||||
async function delay(ms) {
|
||||
return new Promise(res => setTimeout(res, ms))
|
||||
}
|
||||
|
||||
const setRequiredSignatures = async ({ bridgeContract, web3, requiredSignatures, options }) => {
|
||||
const validatorAddress = await bridgeContract.methods.validatorContract().call()
|
||||
const validatorContract = new web3.eth.Contract(BRIDGE_VALIDATORS_ABI, validatorAddress)
|
||||
@@ -8,5 +12,6 @@ const setRequiredSignatures = async ({ bridgeContract, web3, requiredSignatures,
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
delay,
|
||||
setRequiredSignatures
|
||||
}
|
||||
|
||||
@@ -29,6 +29,11 @@ ORACLE_FOREIGN_START_BLOCK=
|
||||
|
||||
ORACLE_LOG_LEVEL=debug
|
||||
ORACLE_MAX_PROCESSING_TIME=20000
|
||||
ORACLE_RPC_REQUEST_TIMEOUT=5000
|
||||
|
||||
ORACLE_HOME_TO_FOREIGN_ALLOWANCE_LIST=access-lists/allowance_list.txt
|
||||
ORACLE_HOME_TO_FOREIGN_BLOCK_LIST=access-lists/block_list.txt
|
||||
ORACLE_HOME_TO_FOREIGN_CHECK_SENDER=false
|
||||
|
||||
#Uncomment these lines only if you are going to send transaction by testing scripts
|
||||
#USER_ADDRESS=0x59c4474184579b9c31b5e51445b6eef91cebf370
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:8 as contracts
|
||||
FROM node:10 as contracts
|
||||
|
||||
WORKDIR /mono
|
||||
|
||||
@@ -11,14 +11,11 @@ COPY ./contracts/truffle-config.js ./
|
||||
COPY ./contracts/contracts ./contracts
|
||||
RUN npm run compile
|
||||
|
||||
FROM node:8
|
||||
FROM node:10
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y build-essential
|
||||
RUN apt-get install -y libc6-dev
|
||||
RUN apt-get install -y libc6-dev-i386
|
||||
RUN apt-get install -y wget
|
||||
RUN apt-get clean
|
||||
RUN apt-get update && \
|
||||
apt-get install -y build-essential libc6-dev libc6-dev-i386 wget && \
|
||||
apt-get clean
|
||||
|
||||
WORKDIR /mono
|
||||
COPY package.json .
|
||||
|
||||
@@ -24,7 +24,7 @@ module.exports = {
|
||||
...baseConfig.bridgeConfig,
|
||||
...baseConfig.foreignConfig,
|
||||
event: 'UserRequestForAffirmation',
|
||||
queue: 'home',
|
||||
queue: 'home-prioritized',
|
||||
name: `watcher-${id}`,
|
||||
id
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ const bridgeConfig = {
|
||||
}
|
||||
|
||||
const homeConfig = {
|
||||
chain: 'home',
|
||||
eventContractAddress: process.env.COMMON_HOME_BRIDGE_ADDRESS,
|
||||
eventAbi: homeAbi,
|
||||
bridgeContractAddress: process.env.COMMON_HOME_BRIDGE_ADDRESS,
|
||||
@@ -83,6 +84,7 @@ const homeConfig = {
|
||||
}
|
||||
|
||||
const foreignConfig = {
|
||||
chain: 'foreign',
|
||||
eventContractAddress: process.env.COMMON_FOREIGN_BRIDGE_ADDRESS,
|
||||
eventAbi: foreignAbi,
|
||||
bridgeContractAddress: process.env.COMMON_FOREIGN_BRIDGE_ADDRESS,
|
||||
|
||||
@@ -6,7 +6,7 @@ module.exports = {
|
||||
...baseConfig.bridgeConfig,
|
||||
...baseConfig.homeConfig,
|
||||
event: 'CollectedSignatures',
|
||||
queue: 'foreign',
|
||||
queue: 'foreign-prioritized',
|
||||
name: `watcher-${id}`,
|
||||
id
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ module.exports = {
|
||||
...baseConfig.bridgeConfig,
|
||||
...baseConfig.foreignConfig,
|
||||
workerQueue: 'convert-to-chai',
|
||||
senderQueue: 'foreign',
|
||||
senderQueue: 'foreign-prioritized',
|
||||
name: `worker-${id}`,
|
||||
id
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
const baseConfig = require('./base.config')
|
||||
|
||||
const { web3Foreign } = require('../src/services/web3')
|
||||
const { web3Foreign, web3ForeignRedundant } = require('../src/services/web3')
|
||||
|
||||
module.exports = {
|
||||
...baseConfig.bridgeConfig,
|
||||
queue: 'foreign',
|
||||
queue: 'foreign-prioritized',
|
||||
oldQueue: 'foreign',
|
||||
id: 'foreign',
|
||||
name: 'sender-foreign',
|
||||
web3: web3Foreign
|
||||
web3: web3Foreign,
|
||||
web3Redundant: web3ForeignRedundant
|
||||
}
|
||||
|
||||
@@ -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,11 +1,13 @@
|
||||
const baseConfig = require('./base.config')
|
||||
|
||||
const { web3Home } = require('../src/services/web3')
|
||||
const { web3Home, web3HomeRedundant } = require('../src/services/web3')
|
||||
|
||||
module.exports = {
|
||||
...baseConfig.bridgeConfig,
|
||||
queue: 'home',
|
||||
queue: 'home-prioritized',
|
||||
oldQueue: 'home',
|
||||
id: 'home',
|
||||
name: 'sender-home',
|
||||
web3: web3Home
|
||||
web3: web3Home,
|
||||
web3Redundant: web3HomeRedundant
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ module.exports = {
|
||||
...baseConfig.bridgeConfig,
|
||||
...baseConfig.homeConfig,
|
||||
event: 'UserRequestForSignature',
|
||||
queue: 'home',
|
||||
queue: 'home-prioritized',
|
||||
name: `watcher-${id}`,
|
||||
id
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -41,7 +41,7 @@ module.exports = {
|
||||
eventContractAddress: initialChecks.bridgeableTokenAddress,
|
||||
eventAbi: ERC20_ABI,
|
||||
eventFilter: { to: process.env.COMMON_FOREIGN_BRIDGE_ADDRESS },
|
||||
queue: 'home',
|
||||
queue: 'home-prioritized',
|
||||
...workerQueueConfig,
|
||||
name: `watcher-${id}`,
|
||||
id
|
||||
|
||||
@@ -3,4 +3,6 @@ version: '2.4'
|
||||
services:
|
||||
oracle:
|
||||
image: poanetwork/tokenbridge-oracle
|
||||
build: .
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: ./oracle/Dockerfile
|
||||
|
||||
@@ -7,8 +7,6 @@ services:
|
||||
service: rabbit
|
||||
networks:
|
||||
- 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:
|
||||
@@ -16,7 +14,6 @@ services:
|
||||
service: redis
|
||||
networks:
|
||||
- net_db_bridge_transfer
|
||||
- net_db_bridge_half_duplex_transfer
|
||||
bridge_request:
|
||||
extends:
|
||||
file: docker-compose.yml
|
||||
@@ -28,6 +25,9 @@ services:
|
||||
extends:
|
||||
file: docker-compose.yml
|
||||
service: bridge_collected
|
||||
volumes:
|
||||
- '~/bridge_data/access-lists/block_list.txt:/mono/oracle/access-lists/block_list.txt'
|
||||
- '~/bridge_data/access-lists/allowance_list.txt:/mono/oracle/access-lists/allowance_list.txt'
|
||||
networks:
|
||||
- net_db_bridge_request
|
||||
- net_rabbit_bridge_request
|
||||
@@ -51,31 +51,6 @@ services:
|
||||
networks:
|
||||
- net_db_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:
|
||||
cpus: 0.1
|
||||
mem_limit: 500m
|
||||
@@ -112,8 +87,6 @@ networks:
|
||||
driver: bridge
|
||||
net_db_bridge_transfer:
|
||||
driver: bridge
|
||||
net_db_bridge_half_duplex_transfer:
|
||||
driver: bridge
|
||||
net_db_bridge_senderhome:
|
||||
driver: bridge
|
||||
net_db_bridge_senderforeign:
|
||||
@@ -126,10 +99,6 @@ networks:
|
||||
driver: bridge
|
||||
net_rabbit_bridge_transfer:
|
||||
driver: bridge
|
||||
net_rabbit_bridge_half_duplex_transfer:
|
||||
driver: bridge
|
||||
net_rabbit_bridge_swap_tokens_worker:
|
||||
driver: bridge
|
||||
net_rabbit_bridge_senderhome:
|
||||
driver: bridge
|
||||
net_rabbit_bridge_senderforeign:
|
||||
|
||||
@@ -9,13 +9,11 @@
|
||||
"watcher:collected-signatures": "./scripts/start-worker.sh watcher collected-signatures-watcher",
|
||||
"watcher:affirmation-request": "./scripts/start-worker.sh watcher affirmation-request-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",
|
||||
"sender:home": "./scripts/start-worker.sh sender home-sender",
|
||||
"sender:foreign": "./scripts/start-worker.sh sender foreign-sender",
|
||||
"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:watch": "NODE_ENV=test mocha --watch --reporter=min",
|
||||
"coverage": "NODE_ENV=test nyc --reporter=text --reporter=html mocha",
|
||||
@@ -28,15 +26,13 @@
|
||||
"amqplib": "^0.5.2",
|
||||
"bignumber.js": "^7.2.1",
|
||||
"dotenv": "^5.0.1",
|
||||
"http-list-provider": "0.0.5",
|
||||
"ioredis": "^3.2.2",
|
||||
"node-fetch": "^2.1.2",
|
||||
"pino": "^4.17.3",
|
||||
"pino-pretty": "^2.0.1",
|
||||
"promise-limit": "^2.7.0",
|
||||
"promise-retry": "^1.1.1",
|
||||
"web3": "1.0.0-beta.34",
|
||||
"web3-utils": "1.0.0-beta.34"
|
||||
"web3": "^1.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bn-chai": "^1.0.1",
|
||||
@@ -50,6 +46,6 @@
|
||||
"sinon": "^6.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.9"
|
||||
"node": ">= 10.18"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
require('../../env')
|
||||
const Web3 = require('web3')
|
||||
const Web3Utils = require('web3-utils')
|
||||
const rpcUrlsManager = require('../../src/services/getRpcUrlsManager')
|
||||
const { sendTx, sendRawTx } = require('../../src/tx/sendTx')
|
||||
const { toWei } = require('web3').utils
|
||||
const { web3Foreign } = require('../../src/services/web3')
|
||||
const { sendTx } = require('../../src/tx/sendTx')
|
||||
const { ERC20_ABI } = require('../../../commons')
|
||||
|
||||
const {
|
||||
@@ -17,37 +16,23 @@ const NUMBER_OF_DEPOSITS_TO_SEND = process.argv[2] || process.env.NUMBER_OF_DEPO
|
||||
|
||||
const { FOREIGN_ERC_TO_ERC_ABI } = require('../../../commons')
|
||||
|
||||
const foreignRpcUrl = rpcUrlsManager.foreignUrls[0]
|
||||
const foreignProvider = new Web3.providers.HttpProvider(foreignRpcUrl)
|
||||
const web3Foreign = new Web3(foreignProvider)
|
||||
|
||||
async function main() {
|
||||
const bridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
const bridgeableTokenAddress = await bridge.methods.erc20token().call()
|
||||
const poa20 = new web3Foreign.eth.Contract(ERC20_ABI, bridgeableTokenAddress)
|
||||
|
||||
try {
|
||||
const foreignChainId = await sendRawTx({
|
||||
chain: 'foreign',
|
||||
params: [],
|
||||
method: 'net_version'
|
||||
})
|
||||
let nonce = await sendRawTx({
|
||||
chain: 'foreign',
|
||||
method: 'eth_getTransactionCount',
|
||||
params: [USER_ADDRESS, 'latest']
|
||||
})
|
||||
nonce = Web3Utils.hexToNumber(nonce)
|
||||
const foreignChainId = await web3Foreign.eth.getChainId()
|
||||
let nonce = await web3Foreign.eth.getTransactionCount(USER_ADDRESS)
|
||||
let actualSent = 0
|
||||
for (let i = 0; i < Number(NUMBER_OF_DEPOSITS_TO_SEND); i++) {
|
||||
const gasLimit = await poa20.methods
|
||||
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX))
|
||||
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, toWei(FOREIGN_MIN_AMOUNT_PER_TX))
|
||||
.estimateGas({ from: USER_ADDRESS })
|
||||
const data = await poa20.methods
|
||||
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX))
|
||||
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, toWei(FOREIGN_MIN_AMOUNT_PER_TX))
|
||||
.encodeABI({ from: USER_ADDRESS })
|
||||
const txHash = await sendTx({
|
||||
chain: 'foreign',
|
||||
privateKey: USER_ADDRESS_PRIVATE_KEY,
|
||||
data,
|
||||
nonce,
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
require('../../env')
|
||||
const Web3 = require('web3')
|
||||
const Web3Utils = require('web3-utils')
|
||||
const rpcUrlsManager = require('../../src/services/getRpcUrlsManager')
|
||||
const { sendTx, sendRawTx } = require('../../src/tx/sendTx')
|
||||
const { toWei } = require('web3').utils
|
||||
const { web3Home } = require('../../src/services/web3')
|
||||
const { sendTx } = require('../../src/tx/sendTx')
|
||||
const { isValidAmount } = require('../utils/utils')
|
||||
const { HOME_ERC_TO_ERC_ABI } = require('../../../commons')
|
||||
|
||||
@@ -46,10 +45,6 @@ const BRIDGEABLE_TOKEN_ABI = [
|
||||
}
|
||||
]
|
||||
|
||||
const homeRpcUrl = rpcUrlsManager.homeUrls[0]
|
||||
const homeProvider = new Web3.providers.HttpProvider(homeRpcUrl)
|
||||
const web3Home = new Web3(homeProvider)
|
||||
|
||||
async function main() {
|
||||
const bridge = new web3Home.eth.Contract(HOME_ERC_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
||||
const BRIDGEABLE_TOKEN_ADDRESS = await bridge.methods.erc677token().call()
|
||||
@@ -58,27 +53,17 @@ async function main() {
|
||||
try {
|
||||
await isValidAmount(HOME_MIN_AMOUNT_PER_TX, bridge)
|
||||
|
||||
const homeChainId = await sendRawTx({
|
||||
chain: 'home',
|
||||
params: [],
|
||||
method: 'net_version'
|
||||
})
|
||||
let nonce = await sendRawTx({
|
||||
chain: 'home',
|
||||
method: 'eth_getTransactionCount',
|
||||
params: [USER_ADDRESS, 'latest']
|
||||
})
|
||||
nonce = Web3Utils.hexToNumber(nonce)
|
||||
const homeChainId = await web3Home.eth.getChainId()
|
||||
let nonce = await web3Home.eth.getTransactionCount(USER_ADDRESS)
|
||||
let actualSent = 0
|
||||
for (let i = 0; i < Number(NUMBER_OF_WITHDRAWALS_TO_SEND); i++) {
|
||||
const gasLimit = await erc677.methods
|
||||
.transferAndCall(COMMON_HOME_BRIDGE_ADDRESS, Web3Utils.toWei(HOME_MIN_AMOUNT_PER_TX), '0x')
|
||||
.transferAndCall(COMMON_HOME_BRIDGE_ADDRESS, toWei(HOME_MIN_AMOUNT_PER_TX), '0x')
|
||||
.estimateGas({ from: USER_ADDRESS })
|
||||
const data = await erc677.methods
|
||||
.transferAndCall(COMMON_HOME_BRIDGE_ADDRESS, Web3Utils.toWei(HOME_MIN_AMOUNT_PER_TX), '0x')
|
||||
.transferAndCall(COMMON_HOME_BRIDGE_ADDRESS, toWei(HOME_MIN_AMOUNT_PER_TX), '0x')
|
||||
.encodeABI({ from: USER_ADDRESS })
|
||||
const txHash = await sendTx({
|
||||
chain: 'home',
|
||||
privateKey: USER_ADDRESS_PRIVATE_KEY,
|
||||
data,
|
||||
nonce,
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
require('../../env')
|
||||
const Web3 = require('web3')
|
||||
const Web3Utils = require('web3-utils')
|
||||
const rpcUrlsManager = require('../../src/services/getRpcUrlsManager')
|
||||
const { sendTx, sendRawTx } = require('../../src/tx/sendTx')
|
||||
const { toWei } = require('web3').utils
|
||||
const { web3Foreign } = require('../../src/services/web3')
|
||||
const { sendTx } = require('../../src/tx/sendTx')
|
||||
|
||||
const {
|
||||
USER_ADDRESS,
|
||||
@@ -16,37 +15,23 @@ const NUMBER_OF_DEPOSITS_TO_SEND = process.argv[2] || process.env.NUMBER_OF_DEPO
|
||||
|
||||
const { ERC20_ABI, FOREIGN_ERC_TO_NATIVE_ABI } = require('../../../commons')
|
||||
|
||||
const foreignRpcUrl = rpcUrlsManager.foreignUrls[0]
|
||||
const foreignProvider = new Web3.providers.HttpProvider(foreignRpcUrl)
|
||||
const web3Foreign = new Web3(foreignProvider)
|
||||
|
||||
async function main() {
|
||||
const bridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
const bridgeableTokenAddress = await bridge.methods.erc20token().call()
|
||||
const poa20 = new web3Foreign.eth.Contract(ERC20_ABI, bridgeableTokenAddress)
|
||||
|
||||
try {
|
||||
const foreignChainId = await sendRawTx({
|
||||
chain: 'foreign',
|
||||
params: [],
|
||||
method: 'net_version'
|
||||
})
|
||||
let nonce = await sendRawTx({
|
||||
chain: 'foreign',
|
||||
method: 'eth_getTransactionCount',
|
||||
params: [USER_ADDRESS, 'latest']
|
||||
})
|
||||
nonce = Web3Utils.hexToNumber(nonce)
|
||||
const foreignChainId = await web3Foreign.eth.getChainId()
|
||||
let nonce = await web3Foreign.eth.getTransactionCount(USER_ADDRESS)
|
||||
let actualSent = 0
|
||||
for (let i = 0; i < Number(NUMBER_OF_DEPOSITS_TO_SEND); i++) {
|
||||
const gasLimit = await poa20.methods
|
||||
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX))
|
||||
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, toWei(FOREIGN_MIN_AMOUNT_PER_TX))
|
||||
.estimateGas({ from: USER_ADDRESS })
|
||||
const data = await poa20.methods
|
||||
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX))
|
||||
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, toWei(FOREIGN_MIN_AMOUNT_PER_TX))
|
||||
.encodeABI({ from: USER_ADDRESS })
|
||||
const txHash = await sendTx({
|
||||
chain: 'foreign',
|
||||
privateKey: USER_ADDRESS_PRIVATE_KEY,
|
||||
data,
|
||||
nonce,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
require('../../env')
|
||||
const Web3Utils = require('web3-utils')
|
||||
const { web3Home } = require('../../src/services/web3')
|
||||
const { sendTx, sendRawTx } = require('../../src/tx/sendTx')
|
||||
const { sendTx } = require('../../src/tx/sendTx')
|
||||
const { isValidAmount } = require('../utils/utils')
|
||||
const { HOME_ERC_TO_NATIVE_ABI } = require('../../../commons')
|
||||
|
||||
@@ -21,21 +20,11 @@ async function main() {
|
||||
try {
|
||||
await isValidAmount(HOME_MIN_AMOUNT_PER_TX, bridge)
|
||||
|
||||
const homeChainId = await sendRawTx({
|
||||
chain: 'home',
|
||||
params: [],
|
||||
method: 'net_version'
|
||||
})
|
||||
let nonce = await sendRawTx({
|
||||
chain: 'home',
|
||||
method: 'eth_getTransactionCount',
|
||||
params: [USER_ADDRESS, 'latest']
|
||||
})
|
||||
nonce = Web3Utils.hexToNumber(nonce)
|
||||
const homeChainId = await web3Home.eth.getChainId()
|
||||
let nonce = await web3Home.eth.getTransactionCount(USER_ADDRESS)
|
||||
let actualSent = 0
|
||||
for (let i = 0; i < Number(NUMBER_OF_DEPOSITS_TO_SEND); i++) {
|
||||
const txHash = await sendTx({
|
||||
chain: 'home',
|
||||
privateKey: USER_ADDRESS_PRIVATE_KEY,
|
||||
data: '0x',
|
||||
nonce,
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
require('../env')
|
||||
const Web3 = require('web3')
|
||||
|
||||
const { BRIDGE_VALIDATORS_ABI } = require('../../commons')
|
||||
const rpcUrlsManager = require('../src/services/getRpcUrlsManager')
|
||||
const { web3Home, web3Foreign } = require('../src/services/web3')
|
||||
const { bridgeConfig } = require('../config/base.config')
|
||||
|
||||
const homeABI = bridgeConfig.homeBridgeAbi
|
||||
const foreignABI = bridgeConfig.foreignBridgeAbi
|
||||
|
||||
async function getStartBlock(rpcUrl, bridgeAddress, bridgeAbi) {
|
||||
async function getStartBlock(web3, bridgeAddress, bridgeAbi) {
|
||||
try {
|
||||
const web3Provider = new Web3.providers.HttpProvider(rpcUrl)
|
||||
const web3Instance = new Web3(web3Provider)
|
||||
const bridgeContract = new web3Instance.eth.Contract(bridgeAbi, bridgeAddress)
|
||||
const bridgeContract = new web3.eth.Contract(bridgeAbi, bridgeAddress)
|
||||
|
||||
const deployedAtBlock = await bridgeContract.methods.deployedAtBlock().call()
|
||||
|
||||
const validatorContractAddress = await bridgeContract.methods.validatorContract().call()
|
||||
const validatorContract = new web3Instance.eth.Contract(BRIDGE_VALIDATORS_ABI, validatorContractAddress)
|
||||
const validatorContract = new web3.eth.Contract(BRIDGE_VALIDATORS_ABI, validatorContractAddress)
|
||||
|
||||
const validatorDeployedAtBlock = await validatorContract.methods.deployedAtBlock().call()
|
||||
|
||||
@@ -35,10 +32,8 @@ async function getStartBlock(rpcUrl, bridgeAddress, bridgeAbi) {
|
||||
async function main() {
|
||||
const { COMMON_HOME_BRIDGE_ADDRESS, COMMON_FOREIGN_BRIDGE_ADDRESS } = process.env
|
||||
|
||||
const homeRpcUrl = rpcUrlsManager.homeUrls[0]
|
||||
const foreignRpcUrl = rpcUrlsManager.foreignUrls[0]
|
||||
const homeStartBlock = await getStartBlock(homeRpcUrl, COMMON_HOME_BRIDGE_ADDRESS, homeABI)
|
||||
const foreignStartBlock = await getStartBlock(foreignRpcUrl, COMMON_FOREIGN_BRIDGE_ADDRESS, foreignABI)
|
||||
const homeStartBlock = await getStartBlock(web3Home, COMMON_HOME_BRIDGE_ADDRESS, homeABI)
|
||||
const foreignStartBlock = await getStartBlock(web3Foreign, COMMON_FOREIGN_BRIDGE_ADDRESS, foreignABI)
|
||||
const result = {
|
||||
homeStartBlock,
|
||||
foreignStartBlock
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
require('../env')
|
||||
const Web3 = require('web3')
|
||||
const { getTokensState } = require('../src/utils/tokenState')
|
||||
const {
|
||||
ERC677_BRIDGE_TOKEN_ABI,
|
||||
@@ -7,6 +6,7 @@ const {
|
||||
FOREIGN_ERC_TO_NATIVE_ABI,
|
||||
getTokenType
|
||||
} = require('../../commons')
|
||||
const { web3Foreign } = require('../src/services/web3')
|
||||
|
||||
const emptyLogger = {
|
||||
debug: () => {},
|
||||
@@ -14,26 +14,25 @@ const emptyLogger = {
|
||||
}
|
||||
|
||||
async function initialChecks() {
|
||||
const { ORACLE_BRIDGE_MODE, COMMON_FOREIGN_RPC_URL, COMMON_FOREIGN_BRIDGE_ADDRESS } = process.env
|
||||
const { ORACLE_BRIDGE_MODE, COMMON_FOREIGN_BRIDGE_ADDRESS } = process.env
|
||||
let result = {}
|
||||
const foreignWeb3 = new Web3(new Web3.providers.HttpProvider(COMMON_FOREIGN_RPC_URL))
|
||||
|
||||
if (ORACLE_BRIDGE_MODE === 'ERC_TO_ERC') {
|
||||
const bridge = new foreignWeb3.eth.Contract(FOREIGN_ERC_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
const bridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
result.bridgeableTokenAddress = await bridge.methods.erc20token().call()
|
||||
} else if (ORACLE_BRIDGE_MODE === 'ERC_TO_NATIVE') {
|
||||
const bridge = new foreignWeb3.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
const bridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
result = await getTokensState(bridge, emptyLogger)
|
||||
}
|
||||
|
||||
if (ORACLE_BRIDGE_MODE === 'ERC_TO_ERC') {
|
||||
const bridgeTokenContract = new foreignWeb3.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, result.bridgeableTokenAddress)
|
||||
const bridgeTokenContract = new web3Foreign.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, result.bridgeableTokenAddress)
|
||||
result.foreignERC = await getTokenType(bridgeTokenContract, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
}
|
||||
console.log(JSON.stringify(result))
|
||||
return result
|
||||
}
|
||||
|
||||
initialChecks()
|
||||
const result = initialChecks()
|
||||
|
||||
module.exports = initialChecks
|
||||
module.exports = result
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
require('../../env')
|
||||
const Web3Utils = require('web3-utils')
|
||||
const { toWei } = require('web3').utils
|
||||
const { web3Foreign } = require('../../src/services/web3')
|
||||
const { sendTx, sendRawTx } = require('../../src/tx/sendTx')
|
||||
const { sendTx } = require('../../src/tx/sendTx')
|
||||
const { isValidAmount } = require('../utils/utils')
|
||||
const { FOREIGN_NATIVE_TO_ERC_ABI } = require('../../../commons')
|
||||
|
||||
@@ -53,27 +53,17 @@ async function main() {
|
||||
try {
|
||||
await isValidAmount(FOREIGN_MIN_AMOUNT_PER_TX, bridge)
|
||||
|
||||
const foreignChainId = await sendRawTx({
|
||||
chain: 'foreign',
|
||||
params: [],
|
||||
method: 'net_version'
|
||||
})
|
||||
let nonce = await sendRawTx({
|
||||
chain: 'foreign',
|
||||
method: 'eth_getTransactionCount',
|
||||
params: [USER_ADDRESS, 'latest']
|
||||
})
|
||||
nonce = Web3Utils.hexToNumber(nonce)
|
||||
const foreignChainId = await web3Foreign.eth.getChainId()
|
||||
let nonce = await web3Foreign.eth.getTransactionCount(USER_ADDRESS)
|
||||
let actualSent = 0
|
||||
for (let i = 0; i < Number(NUMBER_OF_WITHDRAWALS_TO_SEND); i++) {
|
||||
const gasLimit = await poa20.methods
|
||||
.transferAndCall(COMMON_FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX), '0x')
|
||||
.transferAndCall(COMMON_FOREIGN_BRIDGE_ADDRESS, toWei(FOREIGN_MIN_AMOUNT_PER_TX), '0x')
|
||||
.estimateGas({ from: USER_ADDRESS })
|
||||
const data = await poa20.methods
|
||||
.transferAndCall(COMMON_FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX), '0x')
|
||||
.transferAndCall(COMMON_FOREIGN_BRIDGE_ADDRESS, toWei(FOREIGN_MIN_AMOUNT_PER_TX), '0x')
|
||||
.encodeABI({ from: USER_ADDRESS })
|
||||
const txHash = await sendTx({
|
||||
chain: 'foreign',
|
||||
privateKey: USER_ADDRESS_PRIVATE_KEY,
|
||||
data,
|
||||
nonce,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
require('../../env')
|
||||
const Web3Utils = require('web3-utils')
|
||||
const { web3Home } = require('../../src/services/web3')
|
||||
const { sendTx, sendRawTx } = require('../../src/tx/sendTx')
|
||||
const { sendTx } = require('../../src/tx/sendTx')
|
||||
const { isValidAmount } = require('../utils/utils')
|
||||
const { HOME_NATIVE_TO_ERC_ABI } = require('../../../commons')
|
||||
|
||||
@@ -21,21 +20,11 @@ async function main() {
|
||||
try {
|
||||
await isValidAmount(HOME_MIN_AMOUNT_PER_TX, bridge)
|
||||
|
||||
const homeChainId = await sendRawTx({
|
||||
chain: 'home',
|
||||
params: [],
|
||||
method: 'net_version'
|
||||
})
|
||||
let nonce = await sendRawTx({
|
||||
chain: 'home',
|
||||
method: 'eth_getTransactionCount',
|
||||
params: [USER_ADDRESS, 'latest']
|
||||
})
|
||||
nonce = Web3Utils.hexToNumber(nonce)
|
||||
const homeChainId = await web3Home.eth.getChainId()
|
||||
let nonce = await web3Home.eth.getTransactionCount(USER_ADDRESS)
|
||||
let actualSent = 0
|
||||
for (let i = 0; i < Number(NUMBER_OF_DEPOSITS_TO_SEND); i++) {
|
||||
const txHash = await sendTx({
|
||||
chain: 'home',
|
||||
privateKey: USER_ADDRESS_PRIVATE_KEY,
|
||||
data: '0x',
|
||||
nonce,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const Web3Utils = require('web3-utils')
|
||||
const { fromWei } = require('web3').utils
|
||||
|
||||
async function getMinPerTxLimit(bridge) {
|
||||
const minPerTx = await bridge.methods.minPerTx().call()
|
||||
return Web3Utils.fromWei(minPerTx)
|
||||
return fromWei(minPerTx)
|
||||
}
|
||||
|
||||
async function isValidAmount(amount, bridge) {
|
||||
|
||||
@@ -3,7 +3,6 @@ const path = require('path')
|
||||
const { isAttached, connectWatcherToQueue, connection } = require('./services/amqpClient')
|
||||
const logger = require('./services/logger')
|
||||
const GasPrice = require('./services/gasPrice')
|
||||
const rpcUrlsManager = require('./services/getRpcUrlsManager')
|
||||
const { getNonce, getChainId, getEventsFromTx } = require('./tx/web3')
|
||||
const { sendTx } = require('./tx/sendTx')
|
||||
const { checkHTTPS, watchdog, syncForEach, addExtraGas } = require('./utils/utils')
|
||||
@@ -37,8 +36,7 @@ async function initialize() {
|
||||
try {
|
||||
const checkHttps = checkHTTPS(ORACLE_ALLOW_HTTP_FOR_RPC, logger)
|
||||
|
||||
rpcUrlsManager.homeUrls.forEach(checkHttps('home'))
|
||||
rpcUrlsManager.foreignUrls.forEach(checkHttps('foreign'))
|
||||
web3Instance.currentProvider.urls.forEach(checkHttps(config.chain))
|
||||
|
||||
attached = await isAttached()
|
||||
if (attached) {
|
||||
@@ -138,8 +136,8 @@ async function main({ sendJob, txHash }) {
|
||||
}
|
||||
|
||||
async function sendJobTx(jobs) {
|
||||
const gasPrice = await GasPrice.start(config.queue, true)
|
||||
const chainId = await getChainId(config.queue)
|
||||
const gasPrice = await GasPrice.start(config.chain, true)
|
||||
const chainId = await getChainId(web3Instance)
|
||||
let nonce = await getNonce(web3Instance, ORACLE_VALIDATOR_ADDRESS)
|
||||
|
||||
await syncForEach(jobs, async job => {
|
||||
@@ -153,7 +151,6 @@ async function sendJobTx(jobs) {
|
||||
try {
|
||||
logger.info(`Sending transaction with nonce ${nonce}`)
|
||||
const txHash = await sendTx({
|
||||
chain: config.queue,
|
||||
data: job.data,
|
||||
nonce,
|
||||
gasPrice: gasPrice.toString(10),
|
||||
@@ -177,7 +174,7 @@ async function sendJobTx(jobs) {
|
||||
e.message
|
||||
)
|
||||
|
||||
if (e.message.includes('Insufficient funds')) {
|
||||
if (e.message.toLowerCase().includes('insufficient funds')) {
|
||||
const currentBalance = await web3Instance.eth.getBalance(ORACLE_VALIDATOR_ADDRESS)
|
||||
const minimumBalance = gasLimit.multipliedBy(gasPrice)
|
||||
logger.error(
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user