Compare commits

..

1 Commits

Author SHA1 Message Date
Kirill Fedoseev
c02ecad8fd Fix isBridgeContract handler 2020-10-02 21:21:02 +03:00
94 changed files with 1734 additions and 2370 deletions

View File

@@ -8,16 +8,11 @@
**/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

View File

@@ -19,11 +19,9 @@ jobs:
- 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') }}"
- run: git submodule status > submodule.status
- id: get_cache_key
run: echo "::set-output name=cache_key::cache-repo-${{ hashFiles('yarn.lock', 'package.json', 'submodule.status') }}"
- uses: actions/cache@v2
id: cache-repo
with:
@@ -31,8 +29,7 @@ jobs:
**/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 }}
- if: ${{ !steps.cache-repo.outputs.cache-hit }}
run: |
yarn install --frozen-lockfile
yarn run install:deploy
@@ -59,8 +56,7 @@ jobs:
**/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 }}
- run: ${{ steps.cache-repo.outputs.cache-hit }} && yarn run ${{ matrix.task }}
ui-coverage:
runs-on: ubuntu-latest
needs:
@@ -80,8 +76,7 @@ jobs:
**/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
- run: ${{ steps.cache-repo.outputs.cache-hit }} && yarn workspace ui run coverage
- uses: coverallsapp/github-action@master
with:
github-token: ${{ github.token }}
@@ -92,16 +87,14 @@ jobs:
- uses: actions/checkout@v2
with:
submodules: true
- name: Evaluate e2e docker images tags
run: |
- 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: |
echo "::set-env name=E2E_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}"
echo "::set-env name=ORACLE_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}"
echo "::set-env name=MONITOR_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}"
echo "::set-env name=UI_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'ui') }}"
echo "::set-env name=ALM_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}"
- 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
}
@@ -126,10 +119,8 @@ jobs:
- 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: |
- run: echo "::set-env name=MOLECULE_RUNNER_TAG::${{ hashFiles('./deployment-e2e/Dockerfile') }}"
- 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
}
@@ -159,14 +150,13 @@ jobs:
- uses: actions/checkout@v2
with:
submodules: true
- name: Evaluate e2e docker images tags
run: |
- 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 "::set-env name=E2E_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}"
echo "::set-env name=ORACLE_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}"
echo "::set-env name=MONITOR_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}"
echo "::set-env name=UI_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'ui') }}"
echo "::set-env name=ALM_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}"
- if: ${{ matrix.use-cache }}
uses: actions/cache@v2
id: cache-repo
@@ -175,10 +165,8 @@ jobs:
**/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 }}
- run: docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }}
- run: ${{ !matrix.use-cache || steps.cache-repo.outputs.cache-hit }} && yarn run ${{ matrix.task }}
deployment:
runs-on: ubuntu-latest
needs:
@@ -191,10 +179,8 @@ jobs:
- 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: echo "::set-env name=MOLECULE_RUNNER_TAG::${{ hashFiles('./deployment-e2e/Dockerfile') }}"
- run: docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }}
- run: deployment-e2e/molecule.sh ${{ matrix.task }}
ultimate:
runs-on: ubuntu-latest
@@ -219,15 +205,14 @@ jobs:
- uses: actions/checkout@v2
with:
submodules: true
- name: Evaluate e2e docker images tags
run: |
- 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
echo "::set-env name=E2E_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}"
echo "::set-env name=ORACLE_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}"
echo "::set-env name=MONITOR_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}"
echo "::set-env name=UI_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'ui') }}"
echo "::set-env name=ALM_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}"
echo "::set-env name=MOLECULE_RUNNER_TAG::${{ hashFiles('./deployment-e2e/Dockerfile') }}"
- uses: actions/cache@v2
id: cache-repo
with:
@@ -235,19 +220,12 @@ jobs:
**/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: docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }}
- run: ${{ steps.cache-repo.outputs.cache-hit }} && e2e-commons/up.sh deploy blocks
- run: docker-compose -f ./e2e-commons/docker-compose.yml pull oracle
- run: deployment-e2e/molecule.sh ultimate-${{ matrix.task }}
- run: sudo chown -R $USER:docker /var/run/docker.sock
- 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 }}
- 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
View File

@@ -10,8 +10,11 @@ dist
# misc
.DS_Store
*.env*
!.env.example
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
.idea
.nyc_output
logs/
@@ -46,6 +49,5 @@ __pycache__
#monitor
monitor/responses/*
monitor/cache/*
!monitor/cache/.gitkeep
monitor/configs/*.env
!monitor/.gitkeep

View File

@@ -41,7 +41,6 @@ ORACLE_HOME_TO_FOREIGN_ALLOWANCE_LIST | Filename with a list of addresses, separ
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
@@ -78,7 +77,4 @@ 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 | `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`
MONITOR_CACHE_EVENTS | If set to true, monitor will cache obtained events for other workers runs

View File

@@ -51,6 +51,9 @@ export const isBridgeContract = async (contract: Contract, allowedModes?: string
}
return allowedModes.includes(mode)
} catch (e) {
if (e.message.includes("Returned values aren't valid")) {
return false
}
throw e
}
}

View File

@@ -2600,11 +2600,6 @@
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"
@@ -3220,11 +3215,6 @@ 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"
@@ -3350,11 +3340,6 @@ 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"
@@ -3450,13 +3435,6 @@ 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"
@@ -3821,11 +3799,6 @@ 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"
@@ -4215,18 +4188,6 @@ 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"
@@ -4252,11 +4213,6 @@ 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"
@@ -4490,11 +4446,6 @@ 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"
@@ -5290,13 +5241,6 @@ 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"
@@ -5469,16 +5413,6 @@ 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"
@@ -7159,11 +7093,6 @@ 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"
@@ -7298,18 +7227,6 @@ 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"
@@ -7443,11 +7360,6 @@ 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"
@@ -7606,11 +7518,6 @@ 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"
@@ -9685,11 +9592,6 @@ 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"
@@ -10041,11 +9943,6 @@ 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"
@@ -10110,13 +10007,6 @@ 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"
@@ -10131,23 +10021,6 @@ 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"
@@ -11094,11 +10967,6 @@ 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"
@@ -13403,14 +13271,6 @@ 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"
@@ -13852,13 +13712,6 @@ 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"
@@ -14223,17 +14076,6 @@ 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"
@@ -14280,11 +14122,6 @@ 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"
@@ -14330,11 +14167,6 @@ 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"
@@ -15649,8 +15481,3 @@ 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==

View File

@@ -5,8 +5,7 @@
],
"rules": {
"no-unused-expressions": "off",
"import/no-extraneous-dependencies": "off",
"no-bitwise": "off"
"import/no-extraneous-dependencies": "off"
},
"env": {
"mocha": true

View File

@@ -6,30 +6,17 @@ 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,
dataType,
decodedDataType: decodeAMBDataType(dataType)
messageId
}
}

View File

@@ -164,18 +164,18 @@ const getPastEvents = async (
} catch (e) {
if (e.message.includes('query returned more than') && toBlock !== 'latest') {
const middle = toBN(fromBlock)
.add(toBN(toBlock))
.add(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

View File

@@ -65,20 +65,6 @@ const homeV1Abi = [
payable: false,
stateMutability: 'view',
type: 'function'
},
{
constant: true,
inputs: [],
name: 'requiredBlockConfirmations',
outputs: [
{
name: '',
type: 'uint256'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
}
]
@@ -168,20 +154,6 @@ const foreignViAbi = [
payable: false,
stateMutability: 'view',
type: 'function'
},
{
constant: true,
inputs: [],
name: 'requiredBlockConfirmations',
outputs: [
{
name: '',
type: 'uint256'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
}
]

View File

@@ -1,2 +1 @@
0xc9e38bfdB9c635F0796ad83CC8705dc379F41c04
0x612E8bd50A7b1F009F43f2b8679E9B8eD91eb5CE

View File

@@ -23,4 +23,3 @@ 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

View File

@@ -63,7 +63,6 @@
"foreign": "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0",
"homeBox": "0x6C4EaAb8756d53Bf599FFe2347FAFF1123D6C8A1",
"foreignBox": "0x6C4EaAb8756d53Bf599FFe2347FAFF1123D6C8A1",
"blockedHomeBox": "0x612E8bd50A7b1F009F43f2b8679E9B8eD91eb5CE",
"monitor": "http://monitor-amb:3013/bridge"
},
"ambStakeErcToErc": {

View File

@@ -61,9 +61,6 @@ services:
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:

View File

@@ -53,8 +53,3 @@ 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

View File

@@ -17,29 +17,21 @@ docker-compose up -d parity1 parity2 e2e
startValidator () {
docker-compose $1 run -d --name $4 redis
docker-compose $1 run -d --name $5 rabbit
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
}
@@ -56,7 +48,25 @@ startAMBValidator () {
while [ "$1" != "" ]; do
if [ "$1" == "oracle" ]; then
startValidator "" "" "" "redis" "rabbit"
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 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
fi
if [ "$1" == "oracle-validator-2" ]; then
@@ -100,23 +110,7 @@ while [ "$1" != "" ]; do
fi
if [ "$1" == "monitor" ]; then
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

View File

@@ -1,15 +1,7 @@
while true; do
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
sleep 5
docker-compose -f ../e2e-commons/docker-compose.yml exec -d monitor yarn check-all
docker-compose -f ../e2e-commons/docker-compose.yml exec -d monitor-erc20 yarn check-all
docker-compose -f ../e2e-commons/docker-compose.yml exec -d monitor-erc20-native yarn check-all
docker-compose -f ../e2e-commons/docker-compose.yml exec -d monitor-amb yarn check-all
done

View File

@@ -1,28 +1,12 @@
cd $(dirname $0)
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
../e2e-commons/up.sh deploy blocks monitor
MODE="$mode" ../e2e-commons/up.sh deploy blocks monitor
MODE="$mode" ./wait-for-monitor.sh
./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 $script
docker-compose -f ../e2e-commons/docker-compose.yml run e2e yarn workspace monitor-e2e run start
rc=$?
../e2e-commons/down.sh

View File

@@ -25,7 +25,6 @@ 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))
@@ -115,16 +114,7 @@ describe('AMB', () => {
await waitUntil(async () => {
;({ data } = await axios.get(`${baseUrl}`))
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
return data.fromHomeToForeignDiff !== 0
})
})
it('should change validatorsMatch', async () => {

View File

@@ -54,16 +54,16 @@ describe('ERC TO NATIVE with changing state of contracts', () => {
})
it('should consider chai token balance', async function() {
this.timeout(120000)
this.timeout(60000)
await initializeChaiToken(foreignRPC.URL, ercToNativeBridge.foreign)
await sendTokens(foreignRPC.URL, user, ercToNativeBridge.foreignToken, ercToNativeBridge.foreign)
await waitUntil(async () => {
;({ data } = await axios.get(`${baseUrl}`))
const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
if (!data.foreign) {
return false
}
const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
return (
data.balanceDiff === 0.02 &&
erc20Balance === '0.02' &&
@@ -77,10 +77,10 @@ describe('ERC TO NATIVE with changing state of contracts', () => {
await waitUntil(async () => {
;({ data } = await axios.get(`${baseUrl}`))
const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
if (!data.foreign) {
return false
}
const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
return (
data.balanceDiff === 0.02 &&
erc20Balance === '0.01' &&
@@ -94,10 +94,10 @@ describe('ERC TO NATIVE with changing state of contracts', () => {
await waitUntil(async () => {
;({ data } = await axios.get(`${baseUrl}`))
const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
if (!data.foreign) {
return false
}
const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
return (
data.balanceDiff === 0.02 &&
erc20Balance === '0.005' &&

View File

@@ -44,16 +44,12 @@ const sendTokens = async (rpcUrl, account, tokenAddress, recipientAddress) => {
})
}
const sendAMBMessage = async (rpcUrl, account, boxAddress, bridgeAddress, boxOtherSideAddress, manualLane = false) => {
const sendAMBMessage = async (rpcUrl, account, boxAddress, bridgeAddress, boxOtherSideAddress) => {
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[manualLane ? 'setValueOnOtherNetworkUsingManualLane' : 'setValueOnOtherNetwork'](
3,
bridgeAddress,
boxOtherSideAddress
).send({
await homeBox.methods.setValueOnOtherNetwork(3, bridgeAddress, boxOtherSideAddress).send({
from: account.address,
gas: '400000'
})

View File

@@ -6,18 +6,10 @@ check_files_exist() {
rc=0
for f in "${FILES[@]}"; do
command="test -f responses/bridge/$f"
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
}

View File

@@ -22,6 +22,3 @@ 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=

View File

@@ -1,9 +1,18 @@
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 { web3Home, web3Foreign, getHomeBlockNumber, getForeignBlockNumber } = require('./utils/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)
async function main() {
const {
@@ -24,8 +33,7 @@ async function main() {
xAffirmations = foreignToHomeConfirmations.filter(eventWithoutReference(foreignToHomeRequests))
}
logger.debug('building misbehavior blocks')
const homeBlockNumber = await getHomeBlockNumber()
const foreignBlockNumber = await getForeignBlockNumber()
const [homeBlockNumber, foreignBlockNumber] = await getBlockNumber(web3Home, web3Foreign)
const baseRange = [false, false, false, false, false]
const xSignaturesMisbehavior = buildRangesObject(
@@ -65,21 +73,21 @@ async function main() {
/**
* Finds the location for the blockNumber in a specific range starting from currentBlockNumber
* @param {Number} currentBlockNumber
* @param {BN} currentBlockNumber
* @returns {function({blockNumber?: *}): boolean[]}
*/
const findMisbehaviorRange = currentBlockNumber => ({ blockNumber }) => {
const minus60 = currentBlockNumber - 60
const minus180 = currentBlockNumber - 180
const minus720 = currentBlockNumber - 720
const minus17280 = currentBlockNumber - 17280
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))
return [
minus60 <= blockNumber,
minus180 <= blockNumber && minus60 > blockNumber,
minus720 <= blockNumber && minus180 > blockNumber,
minus17280 <= blockNumber && minus720 > blockNumber,
minus17280 > blockNumber
minus60.lte(blockNumber),
minus180.lte(blockNumber) && minus60.gt(blockNumber),
minus720.lte(blockNumber) && minus180.gt(blockNumber),
minus17280.lte(blockNumber) && minus720.gt(blockNumber),
minus17280.gt(blockNumber)
]
}

View File

View File

@@ -1,21 +1,21 @@
require('dotenv').config()
const BN = require('bignumber.js')
const Web3 = require('web3')
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, MONITOR_BRIDGE_NAME } = process.env
const { COMMON_HOME_BRIDGE_ADDRESS, COMMON_HOME_RPC_URL, 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,22 +24,16 @@ 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, eventsInfo)
const balances = await getBalances(bridgeMode)
logger.debug('calling getShortEventStats()')
const events = await getShortEventStats(bridgeMode, eventsInfo)
const events = await getShortEventStats(bridgeMode)
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)

View File

@@ -3,7 +3,6 @@ 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
@@ -27,7 +26,6 @@ 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)

View File

@@ -1,12 +1,15 @@
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 } = process.env
const { MONITOR_BRIDGE_NAME, COMMON_HOME_BRIDGE_ADDRESS, COMMON_HOME_RPC_URL } = 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)

View File

@@ -10,6 +10,5 @@ services:
- NODE_ENV=production
volumes:
- ./responses:/mono/monitor/responses
- ./cache:/mono/monitor/cache
restart: unless-stopped
entrypoint: "yarn start"

View File

@@ -1,20 +1,8 @@
require('dotenv').config()
const eventsInfo = require('./utils/events')
const {
processedMsgNotDelivered,
deliveredMsgNotProcessed,
eventWithoutReference,
unclaimedHomeToForeignRequests
} = require('./utils/message')
const { getHomeTxSender } = require('./utils/web3Cache')
const { processedMsgNotDelivered, deliveredMsgNotProcessed, eventWithoutReference } = require('./utils/message')
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,
@@ -45,30 +33,17 @@ async function main() {
lastChecked: Math.floor(Date.now() / 1000)
}
} else {
let onlyInHomeDeposits = homeToForeignRequests.filter(eventWithoutReference(homeToForeignConfirmations))
const 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)
}
}

View File

@@ -1,11 +1,23 @@
require('dotenv').config()
const BN = require('bignumber.js')
const Web3Utils = require('web3').utils
const Web3 = require('web3')
const logger = require('./logger')('getBalances')
const { BRIDGE_MODES } = require('../commons')
const { web3Home, web3Foreign, getHomeBlockNumber } = require('./utils/web3')
const { COMMON_HOME_BRIDGE_ADDRESS, COMMON_FOREIGN_BRIDGE_ADDRESS } = process.env
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 {
ERC20_ABI,
@@ -18,50 +30,21 @@ const {
FOREIGN_NATIVE_TO_ERC_ABI
} = require('../commons')
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)
)
async function main(bridgeMode) {
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({}, foreignDelayedBlockNumber)
const foreignErc20Balance = await erc20Contract.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
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({}, homeDelayedBlockNumber)
const foreignBalanceBN = new BN(foreignErc20Balance).plus(lateForeignConfirmationsTotalValue)
const foreignTotalSupplyBN = new BN(totalSupply).plus(lateHomeConfirmationsTotalValue)
const totalSupply = await tokenContract.methods.totalSupply().call()
const foreignBalanceBN = new BN(foreignErc20Balance)
const foreignTotalSupplyBN = new BN(totalSupply)
const diff = foreignBalanceBN.minus(foreignTotalSupplyBN).toString(10)
logger.debug('Done')
return {
@@ -78,12 +61,12 @@ async function main(bridgeMode, eventsInfo) {
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, homeDelayedBlockNumber)
const homeBalance = await web3Home.eth.getBalance(COMMON_HOME_BRIDGE_ADDRESS)
const tokenContract = new web3Foreign.eth.Contract(ERC20_ABI, erc20Address)
logger.debug('calling tokenContract.methods.totalSupply()')
const totalSupply = await tokenContract.methods.totalSupply().call({}, foreignDelayedBlockNumber)
const homeBalanceBN = new BN(homeBalance).plus(lateHomeConfirmationsTotalValue)
const foreignTotalSupplyBN = new BN(totalSupply).plus(lateForeignConfirmationsTotalValue)
const totalSupply = await tokenContract.methods.totalSupply().call()
const homeBalanceBN = new BN(homeBalance)
const foreignTotalSupplyBN = new BN(totalSupply)
const diff = homeBalanceBN.minus(foreignTotalSupplyBN).toString(10)
logger.debug('Done')
return {
@@ -120,25 +103,21 @@ async function main(bridgeMode, eventsInfo) {
}
logger.debug('calling erc20Contract.methods.balanceOf')
const foreignErc20Balance = await erc20Contract.methods
.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS)
.call({}, foreignDelayedBlockNumber)
const foreignErc20Balance = await erc20Contract.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
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({}, homeBlockNumber)
const mintedCoins = await blockRewardContract.methods.mintedTotallyByBridge(COMMON_HOME_BRIDGE_ADDRESS).call()
logger.debug('calling homeBridge.methods.totalBurntCoins')
const burntCoins = await homeBridge.methods.totalBurntCoins().call({}, homeDelayedBlockNumber)
const burntCoins = await homeBridge.methods.totalBurntCoins().call()
const mintedCoinsBN = new BN(mintedCoins)
const burntCoinsBN = new BN(burntCoins)
const totalSupplyBN = mintedCoinsBN.minus(burntCoinsBN)
const foreignErc20BalanceBN = new BN(foreignErc20Balance).plus(lateForeignConfirmationsTotalValue)
const foreignErc20BalanceBN = new BN(foreignErc20Balance)
const investedAmountInDaiBN = new BN(investedAmountInDai)
const bridgeDsrBalanceBN = new BN(bridgeDsrBalance)

View File

@@ -1,36 +1,18 @@
require('dotenv').config()
const BN = require('bignumber.js')
const Web3Utils = require('web3').utils
const {
eventWithoutReference,
deliveredMsgNotProcessed,
unclaimedHomeToForeignRequests,
manuallyProcessedAMBHomeToForeignRequests
} = require('./utils/message')
const eventsInfo = require('./utils/events')
const { BRIDGE_MODES } = require('../commons')
const { getHomeTxSender } = require('./utils/web3Cache')
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) {
async function main(bridgeMode) {
const {
homeToForeignConfirmations,
homeToForeignRequests,
foreignToHomeConfirmations,
foreignToHomeRequests
} = eventsInfo
} = await eventsInfo(bridgeMode)
if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) {
const onlyInHomeRequests = homeToForeignRequests.filter(deliveredMsgNotProcessed(homeToForeignConfirmations))
const manuallyProcessedRequests = onlyInHomeRequests.filter(manuallyProcessedAMBHomeToForeignRequests())
return {
fromHomeToForeignDiff:
homeToForeignRequests.length - homeToForeignConfirmations.length - manuallyProcessedRequests.length,
fromHomeToForeignPBUDiff: manuallyProcessedRequests.length,
fromHomeToForeignDiff: homeToForeignRequests.length - homeToForeignConfirmations.length,
fromForeignToHomeDiff: foreignToHomeConfirmations.length - foreignToHomeRequests.length,
home: {
toForeign: homeToForeignRequests.length,
@@ -42,26 +24,9 @@ async function main(bridgeMode, eventsInfo) {
}
}
} else {
const stats = {
depositsDiff: homeToForeignRequests.length - homeToForeignConfirmations.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,
depositsDiff: homeToForeignRequests.length - homeToForeignConfirmations.length,
withdrawalDiff: foreignToHomeConfirmations.length - foreignToHomeRequests.length,
home: {
deposits: homeToForeignRequests.length,
withdrawals: foreignToHomeConfirmations.length

View File

@@ -1,13 +1,10 @@
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)

View File

@@ -14,12 +14,11 @@
"author": "",
"license": "ISC",
"dependencies": {
"bignumber.js": "^9.0.1",
"cors": "^2.8.5",
"bignumber.js": "^6.0.0",
"dotenv": "^5.0.1",
"express": "^4.16.3",
"node-fetch": "^2.1.2",
"web3": "^1.3.0"
"web3": "1.0.0-beta.34"
},
"engines": {
"node": ">= 10.18"

View File

@@ -2,10 +2,6 @@
CONFIGDIR="configs"
RESPONSESDIR="responses"
ACLDIR="access-lists"
ALLOWANCEFILE="allowance_list.txt"
BLOCKFILE="block_list.txt"
CACHEDIR="cache"
IMAGETAG="latest"
cd $(dirname $0)/..
@@ -30,18 +26,10 @@ 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}

View File

@@ -1,12 +1,14 @@
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_BRIDGE_ADDRESS } = process.env
const { COMMON_FOREIGN_RPC_URL, 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,
@@ -62,39 +64,38 @@ const ABIWithData = [
}
]
function transferWithoutCallback(transfersNormal) {
const txHashes = new Set()
transfersNormal.forEach(transfer => txHashes.add(transfer.transactionHash))
return withData => !txHashes.has(withData.transactionHash)
function compareTransfers(transfersNormal) {
return withData => {
return (
transfersNormal.filter(normal => {
return normal.transactionHash === withData.transactionHash
}).length === 0
)
}
}
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 options = {
event: 'Transfer',
options: {
const transfersNormal = await tokenContract.getPastEvents('Transfer', {
filter: {
to: COMMON_FOREIGN_BRIDGE_ADDRESS
}
},
fromBlock: MONITOR_FOREIGN_START_BLOCK,
toBlock: foreignBlockNumber,
chain: 'foreign',
safeToBlock: foreignDelayedBlockNumber
}
const transfersNormal = await getPastEvents(tokenContract, options)
toBlock: 'latest'
})
logger.debug('calling tokenContractWithData.getPastEvents Transfer')
const transfersWithData = await getPastEvents(tokenContractWithData, options)
const stuckTransfers = transfersNormal.filter(transferWithoutCallback(transfersWithData))
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))
logger.debug('Done')
return {
stuckTransfers,

11
monitor/utils/contract.js Normal file
View File

@@ -0,0 +1,11 @@
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
}

View File

@@ -1,4 +1,6 @@
require('dotenv').config()
const Web3 = require('web3')
const { toBN } = require('web3').utils
const logger = require('../logger')('eventsUtils')
const {
BRIDGE_MODES,
@@ -9,6 +11,7 @@ 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
@@ -16,12 +19,24 @@ 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_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 {
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 cacheFilePath = '/tmp/cachedEvents.json'
async function main(mode) {
@@ -58,13 +73,7 @@ async function main(mode) {
}
logger.debug('getting last block numbers')
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
const [homeBlockNumber, foreignBlockNumber] = await getBlockNumber(web3Home, web3Foreign)
let homeToForeignRequests = []
let foreignToHomeRequests = []
let homeMigrationBlock = MONITOR_HOME_START_BLOCK
@@ -81,24 +90,22 @@ async function main(mode) {
homeToForeignRequests = (await getPastEvents(oldHomeBridge, {
event: 'UserRequestForSignature',
fromBlock: MONITOR_HOME_START_BLOCK,
toBlock: homeDelayedBlockNumber,
chain: 'home'
toBlock: homeBlockNumber
})).map(normalizeEvent)
logger.debug(`found ${homeToForeignRequests.length} events`)
if (homeToForeignRequests.length > 0) {
homeMigrationBlock = Math.max(...homeToForeignRequests.map(x => x.blockNumber))
homeMigrationBlock = toBN(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: foreignDelayedBlockNumber,
chain: 'foreign'
toBlock: foreignBlockNumber
})).map(normalizeEvent)
logger.debug(`found ${foreignToHomeRequests.length} events`)
if (foreignToHomeRequests.length > 0) {
foreignMigrationBlock = Math.max(...foreignToHomeRequests.map(x => x.blockNumber))
foreignMigrationBlock = toBN(Math.max(...foreignToHomeRequests.map(x => x.blockNumber)))
}
}
@@ -106,8 +113,7 @@ async function main(mode) {
const homeToForeignRequestsNew = (await getPastEvents(homeBridge, {
event: v1Bridge ? 'Deposit' : 'UserRequestForSignature',
fromBlock: homeMigrationBlock,
toBlock: homeDelayedBlockNumber,
chain: 'home'
toBlock: homeBlockNumber
})).map(normalizeEvent)
homeToForeignRequests = [...homeToForeignRequests, ...homeToForeignRequestsNew]
@@ -115,26 +121,21 @@ async function main(mode) {
const homeToForeignConfirmations = (await getPastEvents(foreignBridge, {
event: v1Bridge ? 'Deposit' : 'RelayedMessage',
fromBlock: MONITOR_FOREIGN_START_BLOCK,
toBlock: foreignBlockNumber,
chain: 'foreign',
safeToBlock: foreignDelayedBlockNumber
toBlock: foreignBlockNumber
})).map(normalizeEvent)
logger.debug("calling homeBridge.getPastEvents('AffirmationCompleted')")
const foreignToHomeConfirmations = (await getPastEvents(homeBridge, {
event: v1Bridge ? 'Withdraw' : 'AffirmationCompleted',
fromBlock: MONITOR_HOME_START_BLOCK,
toBlock: homeBlockNumber,
chain: 'home',
safeToBlock: homeDelayedBlockNumber
toBlock: homeBlockNumber
})).map(normalizeEvent)
logger.debug("calling foreignBridge.getPastEvents('UserRequestForAffirmation')")
const foreignToHomeRequestsNew = (await getPastEvents(foreignBridge, {
event: v1Bridge ? 'Withdraw' : 'UserRequestForAffirmation',
fromBlock: foreignMigrationBlock,
toBlock: foreignDelayedBlockNumber,
chain: 'foreign'
toBlock: foreignBlockNumber
})).map(normalizeEvent)
foreignToHomeRequests = [...foreignToHomeRequests, ...foreignToHomeRequestsNew]
@@ -143,11 +144,10 @@ async function main(mode) {
let transferEvents = (await getPastEvents(erc20Contract, {
event: 'Transfer',
fromBlock: MONITOR_FOREIGN_START_BLOCK,
toBlock: foreignDelayedBlockNumber,
toBlock: foreignBlockNumber,
options: {
filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS }
},
chain: 'foreign'
}
})).map(normalizeEvent)
let directTransfers = transferEvents
@@ -158,9 +158,7 @@ async function main(mode) {
const tokensSwappedEvents = await getPastEvents(foreignBridge, {
event: 'TokensSwapped',
fromBlock: MONITOR_FOREIGN_START_BLOCK,
toBlock: foreignBlockNumber,
chain: 'foreign',
safeToBlock: foreignDelayedBlockNumber
toBlock: foreignBlockNumber
})
// Get token swap events emitted by foreign bridge
@@ -196,11 +194,10 @@ async function main(mode) {
const halfDuplexTransferEvents = (await getPastEvents(halfDuplexTokenContract, {
event: 'Transfer',
fromBlock: MONITOR_FOREIGN_START_BLOCK,
toBlock: foreignDelayedBlockNumber,
toBlock: foreignBlockNumber,
options: {
filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS }
},
chain: 'foreign'
}
})).map(normalizeEvent)
// Remove events after the ES
@@ -235,9 +232,7 @@ async function main(mode) {
foreignToHomeConfirmations,
foreignToHomeRequests,
isExternalErc20,
bridgeMode,
homeDelayedBlockNumber,
foreignDelayedBlockNumber
bridgeMode
}
if (MONITOR_CACHE_EVENTS === 'true') {

View File

@@ -38,25 +38,9 @@ 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,
writeCacheFile,
readAccessListFile
readCacheFile
}

View File

@@ -1,93 +0,0 @@
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
}

View File

@@ -1,30 +1,44 @@
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) {
const keys = new Set()
processedList.forEach(processedMsg => keys.add(keyAMB(processedMsg.returnValues)))
return deliveredMsg => !keys.has(keyAMB(normalizeAMBMessage(deliveredMsg)))
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
)
}
}
function processedMsgNotDelivered(deliveredList) {
const keys = new Set()
deliveredList.forEach(deliveredMsg => keys.add(keyAMB(normalizeAMBMessage(deliveredMsg))))
return processedMsg => !keys.has(keyAMB(processedMsg.returnValues))
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
)
}
/**
@@ -46,49 +60,13 @@ const normalizeEventInformation = event => ({
value: event.returnValues.value
})
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
}
}
const eventWithoutReference = otherSideEvents => e =>
otherSideEvents.filter(a => a.referenceTx === e.referenceTx && a.recipient === e.recipient && a.value === e.value)
.length === 0
module.exports = {
deliveredMsgNotProcessed,
processedMsgNotDelivered,
normalizeEventInformation,
eventWithoutReference,
unclaimedHomeToForeignRequests,
manuallyProcessedAMBHomeToForeignRequests
eventWithoutReference
}

View File

@@ -0,0 +1,16 @@
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
}

View File

@@ -1,27 +0,0 @@
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)
}

View File

@@ -1,133 +0,0 @@
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
}

View File

@@ -1,12 +1,13 @@
require('dotenv').config()
const Web3Utils = require('web3').utils
const Web3 = require('web3')
const fetch = require('node-fetch')
const logger = require('./logger')('validators')
const { getBridgeABIs, BRIDGE_VALIDATORS_ABI, gasPriceFromSupplier } = require('../commons')
const { web3Home, web3Foreign, getHomeBlockNumber, getForeignBlockNumber } = require('./utils/web3')
const { getValidatorList } = require('./utils/getValidatorsList')
const { getBridgeABIs, BRIDGE_VALIDATORS_ABI, getValidatorList, gasPriceFromSupplier } = require('../commons')
const { getBlockNumber } = require('./utils/contract')
const {
COMMON_HOME_RPC_URL,
COMMON_FOREIGN_RPC_URL,
COMMON_HOME_BRIDGE_ADDRESS,
COMMON_FOREIGN_BRIDGE_ADDRESS,
COMMON_HOME_GAS_PRICE_SUPPLIER_URL,
@@ -18,9 +19,19 @@ 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,
@@ -47,12 +58,7 @@ async function main(bridgeMode) {
const homeBridgeValidators = new web3Home.eth.Contract(BRIDGE_VALIDATORS_ABI, homeValidatorsAddress)
logger.debug('getting last block numbers')
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
const [homeBlockNumber, foreignBlockNumber] = await getBlockNumber(web3Home, web3Foreign)
logger.debug('calling foreignBridge.methods.validatorContract().call()')
const foreignValidatorsAddress = await foreignBridge.methods.validatorContract().call()
@@ -60,18 +66,16 @@ async function main(bridgeMode) {
logger.debug('calling foreignBridgeValidators getValidatorList()')
const foreignValidators = (await getValidatorList(foreignValidatorsAddress, web3Foreign.eth, {
toBlock: foreignBlockNumber,
logger,
chain: 'foreign',
safeToBlock: foreignDelayedBlockNumber
from: MONITOR_FOREIGN_START_BLOCK,
to: foreignBlockNumber,
logger
})).map(web3Foreign.utils.toChecksumAddress)
logger.debug('calling homeBridgeValidators getValidatorList()')
const homeValidators = (await getValidatorList(homeValidatorsAddress, web3Home.eth, {
toBlock: homeBlockNumber,
logger,
chain: 'home',
safeToBlock: homeDelayedBlockNumber
from: MONITOR_HOME_START_BLOCK,
to: homeBlockNumber,
logger
})).map(web3Home.utils.toChecksumAddress)
const foreignVBalances = {}

View File

@@ -1,24 +1,8 @@
cd $(dirname $0)
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
../e2e-commons/up.sh deploy blocks oracle oracle-validator-2 oracle-validator-3
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
docker-compose -f ../e2e-commons/docker-compose.yml run e2e yarn workspace oracle-e2e run start
rc=$?
../e2e-commons/down.sh

View File

@@ -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 { delay, setRequiredSignatures } = require('./utils')
const { setRequiredSignatures } = require('./utils')
const { toBN } = Web3.utils
@@ -19,17 +19,14 @@ 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,
@@ -79,85 +76,6 @@ 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', () => {

View File

@@ -1,9 +1,5 @@
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)
@@ -12,6 +8,5 @@ const setRequiredSignatures = async ({ bridgeContract, web3, requiredSignatures,
}
module.exports = {
delay,
setRequiredSignatures
}

View File

@@ -29,7 +29,6 @@ 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

View File

@@ -1,6 +1,6 @@
const baseConfig = require('./base.config')
const { web3Foreign, web3ForeignRedundant } = require('../src/services/web3')
const { web3Foreign } = require('../src/services/web3')
module.exports = {
...baseConfig.bridgeConfig,
@@ -8,6 +8,5 @@ module.exports = {
oldQueue: 'foreign',
id: 'foreign',
name: 'sender-foreign',
web3: web3Foreign,
web3Redundant: web3ForeignRedundant
web3: web3Foreign
}

View File

@@ -1,6 +1,6 @@
const baseConfig = require('./base.config')
const { web3Home, web3HomeRedundant } = require('../src/services/web3')
const { web3Home } = require('../src/services/web3')
module.exports = {
...baseConfig.bridgeConfig,
@@ -8,6 +8,5 @@ module.exports = {
oldQueue: 'home',
id: 'home',
name: 'sender-home',
web3: web3Home,
web3Redundant: web3HomeRedundant
web3: web3Home
}

View File

@@ -26,13 +26,15 @@
"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.3.0"
"web3": "1.0.0-beta.34",
"web3-utils": "1.0.0-beta.34"
},
"devDependencies": {
"bn-chai": "^1.0.1",

View File

@@ -1,7 +1,8 @@
require('../../env')
const { toWei } = require('web3').utils
const { web3Foreign } = require('../../src/services/web3')
const { sendTx } = require('../../src/tx/sendTx')
const Web3 = require('web3')
const Web3Utils = require('web3-utils')
const rpcUrlsManager = require('../../src/services/getRpcUrlsManager')
const { sendTx, sendRawTx } = require('../../src/tx/sendTx')
const { ERC20_ABI } = require('../../../commons')
const {
@@ -16,23 +17,37 @@ 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 web3Foreign.eth.getChainId()
let nonce = await web3Foreign.eth.getTransactionCount(USER_ADDRESS)
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)
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, toWei(FOREIGN_MIN_AMOUNT_PER_TX))
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX))
.estimateGas({ from: USER_ADDRESS })
const data = await poa20.methods
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, toWei(FOREIGN_MIN_AMOUNT_PER_TX))
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX))
.encodeABI({ from: USER_ADDRESS })
const txHash = await sendTx({
chain: 'foreign',
privateKey: USER_ADDRESS_PRIVATE_KEY,
data,
nonce,

View File

@@ -1,7 +1,8 @@
require('../../env')
const { toWei } = require('web3').utils
const { web3Home } = require('../../src/services/web3')
const { sendTx } = require('../../src/tx/sendTx')
const Web3 = require('web3')
const Web3Utils = require('web3-utils')
const rpcUrlsManager = require('../../src/services/getRpcUrlsManager')
const { sendTx, sendRawTx } = require('../../src/tx/sendTx')
const { isValidAmount } = require('../utils/utils')
const { HOME_ERC_TO_ERC_ABI } = require('../../../commons')
@@ -45,6 +46,10 @@ 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()
@@ -53,17 +58,27 @@ async function main() {
try {
await isValidAmount(HOME_MIN_AMOUNT_PER_TX, bridge)
const homeChainId = await web3Home.eth.getChainId()
let nonce = await web3Home.eth.getTransactionCount(USER_ADDRESS)
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)
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, toWei(HOME_MIN_AMOUNT_PER_TX), '0x')
.transferAndCall(COMMON_HOME_BRIDGE_ADDRESS, Web3Utils.toWei(HOME_MIN_AMOUNT_PER_TX), '0x')
.estimateGas({ from: USER_ADDRESS })
const data = await erc677.methods
.transferAndCall(COMMON_HOME_BRIDGE_ADDRESS, toWei(HOME_MIN_AMOUNT_PER_TX), '0x')
.transferAndCall(COMMON_HOME_BRIDGE_ADDRESS, Web3Utils.toWei(HOME_MIN_AMOUNT_PER_TX), '0x')
.encodeABI({ from: USER_ADDRESS })
const txHash = await sendTx({
chain: 'home',
privateKey: USER_ADDRESS_PRIVATE_KEY,
data,
nonce,

View File

@@ -1,7 +1,8 @@
require('../../env')
const { toWei } = require('web3').utils
const { web3Foreign } = require('../../src/services/web3')
const { sendTx } = require('../../src/tx/sendTx')
const Web3 = require('web3')
const Web3Utils = require('web3-utils')
const rpcUrlsManager = require('../../src/services/getRpcUrlsManager')
const { sendTx, sendRawTx } = require('../../src/tx/sendTx')
const {
USER_ADDRESS,
@@ -15,23 +16,37 @@ 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 web3Foreign.eth.getChainId()
let nonce = await web3Foreign.eth.getTransactionCount(USER_ADDRESS)
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)
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, toWei(FOREIGN_MIN_AMOUNT_PER_TX))
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX))
.estimateGas({ from: USER_ADDRESS })
const data = await poa20.methods
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, toWei(FOREIGN_MIN_AMOUNT_PER_TX))
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX))
.encodeABI({ from: USER_ADDRESS })
const txHash = await sendTx({
chain: 'foreign',
privateKey: USER_ADDRESS_PRIVATE_KEY,
data,
nonce,

View File

@@ -1,6 +1,7 @@
require('../../env')
const Web3Utils = require('web3-utils')
const { web3Home } = require('../../src/services/web3')
const { sendTx } = require('../../src/tx/sendTx')
const { sendTx, sendRawTx } = require('../../src/tx/sendTx')
const { isValidAmount } = require('../utils/utils')
const { HOME_ERC_TO_NATIVE_ABI } = require('../../../commons')
@@ -20,11 +21,21 @@ async function main() {
try {
await isValidAmount(HOME_MIN_AMOUNT_PER_TX, bridge)
const homeChainId = await web3Home.eth.getChainId()
let nonce = await web3Home.eth.getTransactionCount(USER_ADDRESS)
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)
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,

View File

@@ -1,20 +1,23 @@
require('../env')
const Web3 = require('web3')
const { BRIDGE_VALIDATORS_ABI } = require('../../commons')
const { web3Home, web3Foreign } = require('../src/services/web3')
const rpcUrlsManager = require('../src/services/getRpcUrlsManager')
const { bridgeConfig } = require('../config/base.config')
const homeABI = bridgeConfig.homeBridgeAbi
const foreignABI = bridgeConfig.foreignBridgeAbi
async function getStartBlock(web3, bridgeAddress, bridgeAbi) {
async function getStartBlock(rpcUrl, bridgeAddress, bridgeAbi) {
try {
const bridgeContract = new web3.eth.Contract(bridgeAbi, bridgeAddress)
const web3Provider = new Web3.providers.HttpProvider(rpcUrl)
const web3Instance = new Web3(web3Provider)
const bridgeContract = new web3Instance.eth.Contract(bridgeAbi, bridgeAddress)
const deployedAtBlock = await bridgeContract.methods.deployedAtBlock().call()
const validatorContractAddress = await bridgeContract.methods.validatorContract().call()
const validatorContract = new web3.eth.Contract(BRIDGE_VALIDATORS_ABI, validatorContractAddress)
const validatorContract = new web3Instance.eth.Contract(BRIDGE_VALIDATORS_ABI, validatorContractAddress)
const validatorDeployedAtBlock = await validatorContract.methods.deployedAtBlock().call()
@@ -32,8 +35,10 @@ async function getStartBlock(web3, bridgeAddress, bridgeAbi) {
async function main() {
const { COMMON_HOME_BRIDGE_ADDRESS, COMMON_FOREIGN_BRIDGE_ADDRESS } = process.env
const homeStartBlock = await getStartBlock(web3Home, COMMON_HOME_BRIDGE_ADDRESS, homeABI)
const foreignStartBlock = await getStartBlock(web3Foreign, COMMON_FOREIGN_BRIDGE_ADDRESS, foreignABI)
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 result = {
homeStartBlock,
foreignStartBlock

View File

@@ -1,4 +1,5 @@
require('../env')
const Web3 = require('web3')
const { getTokensState } = require('../src/utils/tokenState')
const {
ERC677_BRIDGE_TOKEN_ABI,
@@ -6,7 +7,6 @@ const {
FOREIGN_ERC_TO_NATIVE_ABI,
getTokenType
} = require('../../commons')
const { web3Foreign } = require('../src/services/web3')
const emptyLogger = {
debug: () => {},
@@ -14,25 +14,26 @@ const emptyLogger = {
}
async function initialChecks() {
const { ORACLE_BRIDGE_MODE, COMMON_FOREIGN_BRIDGE_ADDRESS } = process.env
const { ORACLE_BRIDGE_MODE, COMMON_FOREIGN_RPC_URL, 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 web3Foreign.eth.Contract(FOREIGN_ERC_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
const bridge = new foreignWeb3.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 web3Foreign.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
const bridge = new foreignWeb3.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 web3Foreign.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, result.bridgeableTokenAddress)
const bridgeTokenContract = new foreignWeb3.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, result.bridgeableTokenAddress)
result.foreignERC = await getTokenType(bridgeTokenContract, COMMON_FOREIGN_BRIDGE_ADDRESS)
}
console.log(JSON.stringify(result))
return result
}
const result = initialChecks()
initialChecks()
module.exports = result
module.exports = initialChecks

View File

@@ -1,7 +1,7 @@
require('../../env')
const { toWei } = require('web3').utils
const Web3Utils = require('web3-utils')
const { web3Foreign } = require('../../src/services/web3')
const { sendTx } = require('../../src/tx/sendTx')
const { sendTx, sendRawTx } = require('../../src/tx/sendTx')
const { isValidAmount } = require('../utils/utils')
const { FOREIGN_NATIVE_TO_ERC_ABI } = require('../../../commons')
@@ -53,17 +53,27 @@ async function main() {
try {
await isValidAmount(FOREIGN_MIN_AMOUNT_PER_TX, bridge)
const foreignChainId = await web3Foreign.eth.getChainId()
let nonce = await web3Foreign.eth.getTransactionCount(USER_ADDRESS)
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)
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, toWei(FOREIGN_MIN_AMOUNT_PER_TX), '0x')
.transferAndCall(COMMON_FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX), '0x')
.estimateGas({ from: USER_ADDRESS })
const data = await poa20.methods
.transferAndCall(COMMON_FOREIGN_BRIDGE_ADDRESS, toWei(FOREIGN_MIN_AMOUNT_PER_TX), '0x')
.transferAndCall(COMMON_FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX), '0x')
.encodeABI({ from: USER_ADDRESS })
const txHash = await sendTx({
chain: 'foreign',
privateKey: USER_ADDRESS_PRIVATE_KEY,
data,
nonce,

View File

@@ -1,6 +1,7 @@
require('../../env')
const Web3Utils = require('web3-utils')
const { web3Home } = require('../../src/services/web3')
const { sendTx } = require('../../src/tx/sendTx')
const { sendTx, sendRawTx } = require('../../src/tx/sendTx')
const { isValidAmount } = require('../utils/utils')
const { HOME_NATIVE_TO_ERC_ABI } = require('../../../commons')
@@ -20,11 +21,21 @@ async function main() {
try {
await isValidAmount(HOME_MIN_AMOUNT_PER_TX, bridge)
const homeChainId = await web3Home.eth.getChainId()
let nonce = await web3Home.eth.getTransactionCount(USER_ADDRESS)
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)
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,

View File

@@ -1,8 +1,8 @@
const { fromWei } = require('web3').utils
const Web3Utils = require('web3-utils')
async function getMinPerTxLimit(bridge) {
const minPerTx = await bridge.methods.minPerTx().call()
return fromWei(minPerTx)
return Web3Utils.fromWei(minPerTx)
}
async function isValidAmount(amount, bridge) {

View File

@@ -3,6 +3,7 @@ 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')
@@ -36,7 +37,8 @@ async function initialize() {
try {
const checkHttps = checkHTTPS(ORACLE_ALLOW_HTTP_FOR_RPC, logger)
web3Instance.currentProvider.urls.forEach(checkHttps(config.chain))
rpcUrlsManager.homeUrls.forEach(checkHttps('home'))
rpcUrlsManager.foreignUrls.forEach(checkHttps('foreign'))
attached = await isAttached()
if (attached) {
@@ -137,7 +139,7 @@ async function main({ sendJob, txHash }) {
async function sendJobTx(jobs) {
const gasPrice = await GasPrice.start(config.chain, true)
const chainId = await getChainId(web3Instance)
const chainId = await getChainId(config.chain)
let nonce = await getNonce(web3Instance, ORACLE_VALIDATOR_ADDRESS)
await syncForEach(jobs, async job => {
@@ -151,6 +153,7 @@ async function sendJobTx(jobs) {
try {
logger.info(`Sending transaction with nonce ${nonce}`)
const txHash = await sendTx({
chain: config.chain,
data: job.data,
nonce,
gasPrice: gasPrice.toString(10),

View File

@@ -1,4 +1,4 @@
const { HttpListProviderError } = require('../../services/HttpListProvider')
const { HttpListProviderError } = require('http-list-provider')
const { AlreadyProcessedError, AlreadySignedError, InvalidValidatorError } = require('../../utils/errors')
const logger = require('../../services/logger').child({
module: 'processAffirmationRequests:estimateGas'

View File

@@ -1,6 +1,6 @@
require('dotenv').config()
const { HttpListProviderError } = require('http-list-provider')
const promiseLimit = require('promise-limit')
const { HttpListProviderError } = require('../../services/HttpListProvider')
const rootLogger = require('../../services/logger')
const { web3Home } = require('../../services/web3')
const bridgeValidatorsABI = require('../../../../contracts/build/contracts/BridgeValidators').abi

View File

@@ -1,5 +1,5 @@
const Web3 = require('web3')
const { HttpListProviderError } = require('../../services/HttpListProvider')
const { HttpListProviderError } = require('http-list-provider')
const { AlreadyProcessedError, IncompatibleContractError, InvalidValidatorError } = require('../../utils/errors')
const logger = require('../../services/logger').child({
module: 'processCollectedSignatures:estimateGas'

View File

@@ -1,11 +1,10 @@
require('dotenv').config()
const promiseLimit = require('promise-limit')
const { HttpListProviderError } = require('../../services/HttpListProvider')
const { HttpListProviderError } = require('http-list-provider')
const bridgeValidatorsABI = require('../../../../contracts/build/contracts/BridgeValidators').abi
const rootLogger = require('../../services/logger')
const { web3Home, web3Foreign } = require('../../services/web3')
const { signatureToVRS, packSignatures } = require('../../utils/message')
const { readAccessListFile } = require('../../utils/utils')
const { parseAMBMessage } = require('../../../../commons')
const estimateGas = require('./estimateGas')
const { AlreadyProcessedError, IncompatibleContractError, InvalidValidatorError } = require('../../utils/errors')
@@ -13,11 +12,7 @@ const { MAX_CONCURRENT_EVENTS, EXTRA_GAS_ABSOLUTE } = require('../../utils/const
const limit = promiseLimit(MAX_CONCURRENT_EVENTS)
const {
ORACLE_HOME_TO_FOREIGN_ALLOWANCE_LIST,
ORACLE_HOME_TO_FOREIGN_BLOCK_LIST,
ORACLE_ALWAYS_RELAY_SIGNATURES
} = process.env
const { ORACLE_ALWAYS_RELAY_SIGNATURES } = process.env
let validatorContract = null
@@ -55,41 +50,6 @@ function processCollectedSignaturesBuilder(config) {
logger.info(`Processing CollectedSignatures ${colSignature.transactionHash}`)
const message = await homeBridge.methods.message(messageHash).call()
const parsedMessage = parseAMBMessage(message)
if (ORACLE_HOME_TO_FOREIGN_ALLOWANCE_LIST || ORACLE_HOME_TO_FOREIGN_BLOCK_LIST) {
const sender = parsedMessage.sender.toLowerCase()
const executor = parsedMessage.executor.toLowerCase()
if (ORACLE_HOME_TO_FOREIGN_ALLOWANCE_LIST) {
const allowanceList = await readAccessListFile(ORACLE_HOME_TO_FOREIGN_ALLOWANCE_LIST, logger)
if (!allowanceList.includes(executor) && !allowanceList.includes(sender)) {
logger.info(
{ sender, executor },
'Validator skips a message. Neither sender nor executor addresses are in the allowance list.'
)
return
}
} else if (ORACLE_HOME_TO_FOREIGN_BLOCK_LIST) {
const blockList = await readAccessListFile(ORACLE_HOME_TO_FOREIGN_BLOCK_LIST, logger)
if (blockList.includes(executor)) {
logger.info({ executor }, 'Validator skips a message. Executor address is in the block list.')
return
}
if (blockList.includes(sender)) {
logger.info({ sender }, 'Validator skips a message. Sender address is in the block list.')
return
}
}
}
if (parsedMessage.decodedDataType.manualLane) {
logger.info(
{ dataType: parsedMessage.dataType },
'Validator skips a message. Message was forwarded to the manual lane by the extension'
)
return
}
logger.debug({ NumberOfCollectedSignatures }, 'Number of signatures to get')

View File

@@ -1,6 +1,6 @@
require('dotenv').config()
const promiseLimit = require('promise-limit')
const { HttpListProviderError } = require('../../services/HttpListProvider')
const { HttpListProviderError } = require('http-list-provider')
const bridgeValidatorsABI = require('../../../../contracts/build/contracts/BridgeValidators').abi
const rootLogger = require('../../services/logger')
const { web3Home } = require('../../services/web3')

View File

@@ -1,4 +1,4 @@
const { HttpListProviderError } = require('../../services/HttpListProvider')
const { HttpListProviderError } = require('http-list-provider')
const { AlreadyProcessedError, AlreadySignedError, InvalidValidatorError } = require('../../utils/errors')
const logger = require('../../services/logger').child({
module: 'processAffirmationRequests:estimateGas'

View File

@@ -1,6 +1,6 @@
require('../../../env')
const promiseLimit = require('promise-limit')
const { HttpListProviderError } = require('../../services/HttpListProvider')
const { HttpListProviderError } = require('http-list-provider')
const rootLogger = require('../../services/logger')
const { web3Home } = require('../../services/web3')

View File

@@ -1,5 +1,5 @@
const Web3 = require('web3')
const { HttpListProviderError } = require('../../services/HttpListProvider')
const { HttpListProviderError } = require('http-list-provider')
const { AlreadyProcessedError, IncompatibleContractError, InvalidValidatorError } = require('../../utils/errors')
const { parseMessage } = require('../../utils/message')
const logger = require('../../services/logger').child({

View File

@@ -1,6 +1,6 @@
require('../../../env')
const promiseLimit = require('promise-limit')
const { HttpListProviderError } = require('../../services/HttpListProvider')
const { HttpListProviderError } = require('http-list-provider')
const { BRIDGE_VALIDATORS_ABI } = require('../../../../commons')
const rootLogger = require('../../services/logger')
const { web3Home, web3Foreign } = require('../../services/web3')

View File

@@ -1,4 +1,4 @@
const { HttpListProviderError } = require('../../services/HttpListProvider')
const { HttpListProviderError } = require('http-list-provider')
const { AlreadyProcessedError, AlreadySignedError, InvalidValidatorError } = require('../../utils/errors')
const logger = require('../../services/logger').child({
module: 'processSignatureRequests:estimateGas'

View File

@@ -1,6 +1,6 @@
require('../../../env')
const promiseLimit = require('promise-limit')
const { HttpListProviderError } = require('../../services/HttpListProvider')
const { HttpListProviderError } = require('http-list-provider')
const { BRIDGE_VALIDATORS_ABI } = require('../../../../commons')
const rootLogger = require('../../services/logger')
const { web3Home } = require('../../services/web3')

View File

@@ -1,6 +1,6 @@
require('../../../env')
const promiseLimit = require('promise-limit')
const { HttpListProviderError } = require('../../services/HttpListProvider')
const { HttpListProviderError } = require('http-list-provider')
const { BRIDGE_VALIDATORS_ABI, ZERO_ADDRESS } = require('../../../../commons')
const rootLogger = require('../../services/logger')
const { web3Home, web3Foreign } = require('../../services/web3')

View File

@@ -4,6 +4,7 @@ const { connectSenderToQueue } = require('./services/amqpClient')
const { redis } = require('./services/redisClient')
const GasPrice = require('./services/gasPrice')
const logger = require('./services/logger')
const rpcUrlsManager = require('./services/getRpcUrlsManager')
const { sendTx } = require('./tx/sendTx')
const { getNonce, getChainId } = require('./tx/web3')
const {
@@ -17,7 +18,7 @@ const {
} = require('./utils/utils')
const { EXIT_CODES, EXTRA_GAS_PERCENTAGE, MAX_GAS_LIMIT } = require('./utils/constants')
const { ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY, ORACLE_TX_REDUNDANCY } = process.env
const { ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY } = process.env
const ORACLE_VALIDATOR_ADDRESS = privateKeyToAddress(ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY)
@@ -29,7 +30,6 @@ if (process.argv.length < 3) {
const config = require(path.join('../config/', process.argv[2]))
const web3Instance = config.web3
const web3Redundant = ORACLE_TX_REDUNDANCY === 'true' ? config.web3Redundant : config.web3
const nonceKey = `${config.id}:nonce`
let chainId = 0
@@ -37,11 +37,12 @@ async function initialize() {
try {
const checkHttps = checkHTTPS(process.env.ORACLE_ALLOW_HTTP_FOR_RPC, logger)
web3Instance.currentProvider.urls.forEach(checkHttps(config.chain))
rpcUrlsManager.homeUrls.forEach(checkHttps('home'))
rpcUrlsManager.foreignUrls.forEach(checkHttps('foreign'))
GasPrice.start(config.id)
chainId = await getChainId(web3Instance)
chainId = await getChainId(config.id)
connectSenderToQueue({
queueName: config.queue,
oldQueueName: config.oldQueue,
@@ -79,17 +80,13 @@ async function readNonce(forceUpdate) {
logger.debug({ nonce }, 'Nonce found in the DB')
return Number(nonce)
} else {
logger.warn("Nonce wasn't found in the DB")
logger.debug("Nonce wasn't found in the DB")
return getNonce(web3Instance, ORACLE_VALIDATOR_ADDRESS)
}
}
function updateNonce(nonce) {
if (typeof nonce !== 'number') {
logger.warn('Given nonce value is not a valid number. Nothing will be updated in the DB.')
} else {
redis.set(nonceKey, nonce)
}
return redis.set(nonceKey, nonce)
}
async function main({ msg, ackMsg, nackMsg, channel, scheduleForRetry, scheduleTransactionResend }) {
@@ -101,13 +98,13 @@ async function main({ msg, ackMsg, nackMsg, channel, scheduleForRetry, scheduleT
const txArray = JSON.parse(msg.content)
logger.debug(`Msg received with ${txArray.length} Tx to send`)
const gasPrice = GasPrice.getPrice().toString(10)
const gasPrice = GasPrice.getPrice()
let nonce
let insufficientFunds = false
let minimumBalance = null
const failedTx = []
const resendJobs = []
const sentTx = []
const isResend = txArray.length > 0 && !!txArray[0].txHash
@@ -139,31 +136,30 @@ async function main({ msg, ackMsg, nackMsg, channel, scheduleForRetry, scheduleT
nonce = await readNonce(true)
}
logger.info(`Transaction ${job.txHash} was not mined, updating gasPrice: ${job.gasPrice} -> ${gasPrice}`)
logger.info(
`Transaction ${job.txHash} was not mined, updating gasPrice: ${job.gasPrice} -> ${gasPrice.toString(10)}`
)
}
logger.info(`Sending transaction with nonce ${nonce}`)
const txHash = await sendTx({
job.gasPrice = gasPrice.toString(10)
job.txHash = await sendTx({
chain: config.id,
data: job.data,
nonce,
gasPrice,
gasPrice: job.gasPrice,
amount: '0',
gasLimit,
privateKey: ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY,
to: job.to,
chainId,
web3: web3Redundant
web3: web3Instance
})
const resendJob = {
...job,
txHash,
gasPrice
}
resendJobs.push(resendJob)
sentTx.push(job)
nonce++
logger.info(
{ eventTransactionHash: job.transactionReference, generatedTransactionHash: txHash },
`Tx generated ${txHash} for event Tx ${job.transactionReference}`
{ eventTransactionHash: job.transactionReference, generatedTransactionHash: job.txHash },
`Tx generated ${job.txHash} for event Tx ${job.transactionReference}`
)
} catch (e) {
logger.error(
@@ -172,12 +168,8 @@ async function main({ msg, ackMsg, nackMsg, channel, scheduleForRetry, scheduleT
e.message
)
if (!e.message.toLowerCase().includes('transaction with the same hash was already imported')) {
if (isResend) {
resendJobs.push(job)
} else {
failedTx.push(job)
}
}
if (e.message.toLowerCase().includes('insufficient funds')) {
insufficientFunds = true
@@ -192,18 +184,16 @@ async function main({ msg, ackMsg, nackMsg, channel, scheduleForRetry, scheduleT
}
})
if (typeof nonce === 'number') {
logger.debug('Updating nonce')
await updateNonce(nonce)
}
if (failedTx.length) {
logger.info(`Sending ${failedTx.length} Failed Tx to Queue`)
await scheduleForRetry(failedTx, msg.properties.headers['x-retries'])
}
if (resendJobs.length) {
logger.info(`Sending ${resendJobs.length} Tx Delayed Resend Requests to Queue`)
await scheduleTransactionResend(resendJobs)
if (sentTx.length) {
logger.info(`Sending ${sentTx.length} Tx Delayed Resend Requests to Queue`)
await scheduleTransactionResend(sentTx)
}
ackMsg(msg)
logger.debug(`Finished processing msg`)

View File

@@ -1,89 +0,0 @@
const fetch = require('node-fetch')
const promiseRetry = require('promise-retry')
const defaultOptions = {
requestTimeout: 0,
retry: {
retries: 0
}
}
class HttpListProviderError extends Error {
constructor(message, errors) {
super(message)
this.errors = errors
}
}
function HttpListProvider(urls, options = {}) {
if (!(this instanceof HttpListProvider)) {
return new HttpListProvider(urls)
}
if (!urls || !urls.length) {
throw new TypeError(`Invalid URLs: '${urls}'`)
}
this.urls = urls
this.options = { ...defaultOptions, ...options }
this.currentIndex = 0
}
HttpListProvider.prototype.send = async function send(payload, callback) {
// save the currentIndex to avoid race condition
const { currentIndex } = this
try {
const [result, index] = await promiseRetry(retry => {
return trySend(payload, this.urls, currentIndex, this.options).catch(retry)
}, this.options.retry)
this.currentIndex = index
callback(null, result)
} catch (e) {
callback(e)
}
}
function send(url, payload, options) {
return fetch(url, {
headers: {
'Content-type': 'application/json'
},
method: 'POST',
body: JSON.stringify(payload),
timeout: options.requestTimeout
})
.then(response => {
if (response.ok) {
return response
} else {
throw new Error(response.statusText)
}
})
.then(response => response.json())
}
async function trySend(payload, urls, initialIndex, options) {
const errors = []
let index = initialIndex
for (let count = 0; count < urls.length; count++) {
const url = urls[index]
try {
const result = await send(url, payload, options)
return [result, index]
} catch (e) {
errors.push(e)
}
index = (index + 1) % urls.length
}
throw new HttpListProviderError('Request failed for all urls', errors)
}
module.exports = {
HttpListProvider,
HttpListProviderError,
defaultOptions,
send
}

View File

@@ -1,40 +0,0 @@
const promiseRetry = require('promise-retry')
const { promiseAny } = require('../utils/utils')
const { defaultOptions, HttpListProviderError, send } = require('./HttpListProvider')
function RedundantHttpListProvider(urls, options = {}) {
if (!(this instanceof RedundantHttpListProvider)) {
return new RedundantHttpListProvider(urls)
}
if (!urls || !urls.length) {
throw new TypeError(`Invalid URLs: '${urls}'`)
}
this.urls = urls
this.options = { ...defaultOptions, ...options }
this.currentIndex = 0
}
RedundantHttpListProvider.prototype.send = async function send(payload, callback) {
try {
const result = await promiseRetry(retry => {
return trySend(payload, this.urls, this.options).catch(retry)
}, this.options.retry)
callback(null, result)
} catch (e) {
callback(e)
}
}
async function trySend(payload, urls, options) {
try {
return await promiseAny(urls.map(url => send(url, payload, options)))
} catch (errors) {
throw new HttpListProviderError('Request failed for all urls', errors)
}
}
module.exports = {
RedundantHttpListProvider
}

View File

@@ -0,0 +1,50 @@
const promiseRetry = require('promise-retry')
const tryEach = require('../utils/tryEach')
const { RETRY_CONFIG } = require('../utils/constants')
const { promiseAny } = require('../utils/utils')
function RpcUrlsManager(homeUrls, foreignUrls) {
if (!homeUrls) {
throw new Error(`Invalid homeUrls: '${homeUrls}'`)
}
if (!foreignUrls) {
throw new Error(`Invalid foreignUrls: '${foreignUrls}'`)
}
this.homeUrls = homeUrls.split(' ')
this.foreignUrls = foreignUrls.split(' ')
}
RpcUrlsManager.prototype.tryEach = async function(chain, f, redundant = false) {
if (chain !== 'home' && chain !== 'foreign') {
throw new Error(`Invalid argument chain: '${chain}'`)
}
// save urls to avoid race condition
const urls = chain === 'home' ? [...this.homeUrls] : [...this.foreignUrls]
if (redundant) {
// result from first responded node will be returned immediately
// remaining nodes will continue to retry queries in separate promises
// promiseAny will throw only if all urls reached max retry number
return promiseAny(urls.map(url => promiseRetry(retry => f(url).catch(retry), RETRY_CONFIG)))
}
const [result, index] = await promiseRetry(retry => tryEach(urls, f).catch(retry), RETRY_CONFIG)
if (index > 0) {
// rotate urls
const failed = urls.splice(0, index)
urls.push(...failed)
}
if (chain === 'home') {
this.homeUrls = urls
} else {
this.foreignUrls = urls
}
return result
}
module.exports = RpcUrlsManager

View File

@@ -0,0 +1,3 @@
const RpcUrlsManager = require('./RpcUrlsManager')
module.exports = new RpcUrlsManager(process.env.COMMON_HOME_RPC_URL, process.env.COMMON_FOREIGN_RPC_URL)

View File

@@ -1,55 +1,19 @@
const HttpListProvider = require('http-list-provider')
const Web3 = require('web3')
const { HttpListProvider } = require('./HttpListProvider')
const { RedundantHttpListProvider } = require('./RedundantHttpListProvider')
const rpcUrlsManager = require('./getRpcUrlsManager')
const { RETRY_CONFIG } = require('../utils/constants')
const {
COMMON_HOME_RPC_URL,
COMMON_FOREIGN_RPC_URL,
ORACLE_RPC_REQUEST_TIMEOUT,
ORACLE_HOME_RPC_POLLING_INTERVAL,
ORACLE_FOREIGN_RPC_POLLING_INTERVAL
} = process.env
if (!COMMON_HOME_RPC_URL) {
throw new Error(`Invalid homeUrls: '${COMMON_HOME_RPC_URL}'`)
}
if (!COMMON_FOREIGN_RPC_URL) {
throw new Error(`Invalid foreignUrls: '${COMMON_FOREIGN_RPC_URL}'`)
}
const homeUrls = COMMON_HOME_RPC_URL.split(' ').filter(url => url.length > 0)
const foreignUrls = COMMON_FOREIGN_RPC_URL.split(' ').filter(url => url.length > 0)
const homeDefaultTimeout = parseInt(ORACLE_HOME_RPC_POLLING_INTERVAL, 10) * 2
const foreignDefaultTimeout = parseInt(ORACLE_FOREIGN_RPC_POLLING_INTERVAL, 10) * 2
const configuredTimeout = parseInt(ORACLE_RPC_REQUEST_TIMEOUT, 10)
const homeOptions = {
requestTimeout: configuredTimeout || homeDefaultTimeout,
const homeProvider = new HttpListProvider(rpcUrlsManager.homeUrls, {
retry: RETRY_CONFIG
}
const foreignOptions = {
requestTimeout: configuredTimeout || foreignDefaultTimeout,
retry: RETRY_CONFIG
}
const homeProvider = new HttpListProvider(homeUrls, homeOptions)
})
const web3Home = new Web3(homeProvider)
const foreignProvider = new HttpListProvider(foreignUrls, foreignOptions)
const foreignProvider = new HttpListProvider(rpcUrlsManager.foreignUrls, {
retry: RETRY_CONFIG
})
const web3Foreign = new Web3(foreignProvider)
const redundantHomeProvider = new RedundantHttpListProvider(homeUrls, homeOptions)
const web3HomeRedundant = new Web3(redundantHomeProvider)
const redundantForeignProvider = new RedundantHttpListProvider(foreignUrls, foreignOptions)
const web3ForeignRedundant = new Web3(redundantForeignProvider)
module.exports = {
web3Home,
web3Foreign,
web3HomeRedundant,
web3ForeignRedundant
web3Foreign
}

View File

@@ -1,27 +1,67 @@
const { toWei } = require('web3').utils
const Web3Utils = require('web3-utils')
const fetch = require('node-fetch')
const rpcUrlsManager = require('../services/getRpcUrlsManager')
async function sendTx({ privateKey, data, nonce, gasPrice, amount, gasLimit, to, chainId, web3 }) {
const { ORACLE_TX_REDUNDANCY } = process.env
// eslint-disable-next-line consistent-return
async function sendTx({ chain, privateKey, data, nonce, gasPrice, amount, gasLimit, to, chainId, web3 }) {
const serializedTx = await web3.eth.accounts.signTransaction(
{
nonce: Number(nonce),
chainId,
to,
data,
value: toWei(amount),
value: Web3Utils.toWei(amount),
gasPrice,
gas: gasLimit
},
`0x${privateKey}`
)
return new Promise((res, rej) =>
web3.eth
.sendSignedTransaction(serializedTx.rawTransaction)
.once('transactionHash', res)
.once('error', rej)
return sendRawTx({
chain,
method: 'eth_sendRawTransaction',
params: [serializedTx.rawTransaction]
})
}
// eslint-disable-next-line consistent-return
async function sendRawTx({ chain, params, method }) {
const result = await rpcUrlsManager.tryEach(
chain,
async url => {
// curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sendRawTransaction","params":[{see above}],"id":1}'
const response = await fetch(url, {
headers: {
'Content-type': 'application/json'
},
method: 'POST',
body: JSON.stringify({
jsonrpc: '2.0',
method,
params,
id: Math.floor(Math.random() * 100) + 1
})
})
if (!response.ok) {
throw new Error(response.statusText)
}
return response
},
ORACLE_TX_REDUNDANCY === 'true' && method === 'eth_sendRawTransaction'
)
const json = await result.json()
if (json.error) {
throw json.error
}
return json.result
}
module.exports = {
sendTx
sendTx,
sendRawTx
}

View File

@@ -1,6 +1,8 @@
const { hexToNumber } = require('web3-utils')
const logger = require('../services/logger').child({
module: 'web3'
})
const { sendRawTx } = require('./sendTx')
async function getNonce(web3, address) {
try {
@@ -24,10 +26,15 @@ async function getBlockNumber(web3) {
}
}
async function getChainId(web3) {
async function getChainId(chain) {
try {
logger.debug('Getting chain id')
const chainId = await web3.eth.getChainId()
const chainIdHex = await sendRawTx({
chain,
method: 'eth_chainId',
params: []
})
const chainId = hexToNumber(chainIdHex)
logger.debug({ chainId }, 'Chain id obtained')
return chainId
} catch (e) {

View File

@@ -1,13 +1,13 @@
const assert = require('assert')
const { toHex, numberToHex, padLeft } = require('web3').utils
const Web3Utils = require('web3-utils')
const { strip0x } = require('../../../commons')
function createMessage({ recipient, value, transactionHash, bridgeAddress, expectedMessageLength }) {
recipient = strip0x(recipient)
assert.strictEqual(recipient.length, 20 * 2)
value = numberToHex(value)
value = padLeft(value, 32 * 2)
value = Web3Utils.numberToHex(value)
value = Web3Utils.padLeft(value, 32 * 2)
value = strip0x(value)
assert.strictEqual(value.length, 64)
@@ -60,7 +60,7 @@ function signatureToVRS(rawSignature) {
}
function packSignatures(array) {
const length = strip0x(toHex(array.length))
const length = strip0x(Web3Utils.toHex(array.length))
const msgLength = length.length === 1 ? `0${length}` : length
let v = ''
let r = ''

View File

@@ -118,10 +118,7 @@ async function readAccessListFile(fileName, logger) {
.split('\n')
.map(addr => addr.trim().toLowerCase())
.filter(addr => addr.length === 42)
logger.info(
{ fileName },
`Access list was read successfully, ${readAccessLists[fileName].length} addresses found`
)
logger.info({ fileName }, `Access list was read successfully, ${data.length} addresses found`)
logger.debug({ addresses: readAccessLists[fileName] }, `Read addresses from the file`)
} catch (e) {
readAccessLists[fileName] = []

View File

@@ -5,6 +5,7 @@ const { connectWatcherToQueue, connection } = require('./services/amqpClient')
const { getBlockNumber } = require('./tx/web3')
const { redis } = require('./services/redisClient')
const logger = require('./services/logger')
const rpcUrlsManager = require('./services/getRpcUrlsManager')
const { getRequiredBlockConfirmations, getEvents } = require('./tx/web3')
const { checkHTTPS, watchdog } = require('./utils/utils')
const { EXIT_CODES } = require('./utils/constants')
@@ -41,7 +42,8 @@ async function initialize() {
try {
const checkHttps = checkHTTPS(process.env.ORACLE_ALLOW_HTTP_FOR_RPC, logger)
web3Instance.currentProvider.urls.forEach(checkHttps(config.chain))
rpcUrlsManager.homeUrls.forEach(checkHttps('home'))
rpcUrlsManager.foreignUrls.forEach(checkHttps('foreign'))
await getLastProcessedBlock()
connectWatcherToQueue({

View File

@@ -1,5 +1,6 @@
const path = require('path')
const logger = require('./services/logger')
const rpcUrlsManager = require('./services/getRpcUrlsManager')
const { checkHTTPS, watchdog } = require('./utils/utils')
const { EXIT_CODES } = require('./utils/constants')
const { connectWorkerToQueue } = require('./services/amqpClient')
@@ -8,13 +9,12 @@ const config = require(path.join('../config/', process.argv[2]))
const convertToChai = require('./workers/convertToChai')(config)
const web3Instance = config.web3
async function initialize() {
try {
const checkHttps = checkHTTPS(process.env.ORACLE_ALLOW_HTTP_FOR_RPC, logger)
web3Instance.currentProvider.urls.forEach(checkHttps(config.chain))
rpcUrlsManager.homeUrls.forEach(checkHttps('home'))
rpcUrlsManager.foreignUrls.forEach(checkHttps('foreign'))
connectWorkerToQueue({
queueName: config.workerQueue,

View File

@@ -1,5 +1,5 @@
require('../../env')
const { HttpListProviderError } = require('../services/HttpListProvider')
const { HttpListProviderError } = require('http-list-provider')
const rootLogger = require('../services/logger')
const { web3Foreign } = require('../services/web3')

View File

@@ -2,7 +2,7 @@ const chai = require('chai')
const chaiAsPromised = require('chai-as-promised')
const sinon = require('sinon')
const Web3 = require('web3')
const { HttpListProviderError } = require('../src/services/HttpListProvider')
const { HttpListProviderError } = require('http-list-provider')
const estimateGas = require('../src/events/processAffirmationRequests/estimateGas')
const errors = require('../src/utils/errors')

View File

@@ -1,7 +1,7 @@
const { expect } = require('chai').use(require('chai-as-promised'))
const sinon = require('sinon')
const Web3 = require('web3')
const { HttpListProviderError } = require('../src/services/HttpListProvider')
const { HttpListProviderError } = require('http-list-provider')
const { createMessage, signatureToVRS } = require('../src/utils/message')
const estimateGas = require('../src/events/processCollectedSignatures/estimateGas')
const errors = require('../src/utils/errors')

View File

@@ -2,7 +2,7 @@ const chai = require('chai')
const chaiAsPromised = require('chai-as-promised')
const sinon = require('sinon')
const Web3 = require('web3')
const { HttpListProviderError } = require('../src/services/HttpListProvider')
const { HttpListProviderError } = require('http-list-provider')
const estimateGas = require('../src/events/processSignatureRequests/estimateGas')
const errors = require('../src/utils/errors')

View File

@@ -39,7 +39,7 @@
"build:ui": "yarn workspace ui run build",
"build:alm": "yarn workspace alm run build",
"build:plugin": "yarn workspace burner-wallet-plugin run build",
"lint": "yarn wsrun --exclude tokenbridge-contracts lint",
"lint": "yarn wsrun --exclude token-bridge-contracts lint",
"test": "yarn wsrun --exclude oracle-e2e --exclude ui-e2e --exclude monitor-e2e --exclude alm-e2e test",
"oracle-e2e": "./oracle-e2e/run-tests.sh",
"ui-e2e": "./ui-e2e/run-tests.sh",
@@ -47,7 +47,7 @@
"monitor-e2e": "./monitor-e2e/run-tests.sh",
"alm-e2e": "./alm-e2e/run-tests.sh",
"clean": "rm -rf ./node_modules ./**/node_modules ./**/**/node_modules ./**/build ./**/**/dist",
"compile:contracts": "yarn workspace tokenbridge-contracts run compile",
"compile:contracts": "yarn workspace token-bridge-contracts run compile",
"install:deploy": "cd contracts/deploy && npm install --unsafe-perm --silent",
"postinstall": "test -n \"$NOYARNPOSTINSTALL\" || ln -sf $(pwd)/node_modules/openzeppelin-solidity/ contracts/node_modules/openzeppelin-solidity"
}

1980
yarn.lock

File diff suppressed because it is too large Load Diff