Merge the develop branch to the master branch, preparation to v2.6.0-rc2
This commit is contained in:
commit
1122daf9a1
@ -8,11 +8,16 @@
|
|||||||
**/docs
|
**/docs
|
||||||
**/*.md
|
**/*.md
|
||||||
|
|
||||||
|
monitor/**/*.env*
|
||||||
|
oracle/**/*.env*
|
||||||
|
!**/.env.example
|
||||||
|
|
||||||
contracts/test
|
contracts/test
|
||||||
contracts/build
|
contracts/build
|
||||||
oracle/test
|
oracle/test
|
||||||
monitor/test
|
monitor/test
|
||||||
monitor/responses
|
monitor/responses
|
||||||
|
monitor/cache/*
|
||||||
commons/test
|
commons/test
|
||||||
oracle/**/*.png
|
oracle/**/*.png
|
||||||
oracle/**/*.jpg
|
oracle/**/*.jpg
|
||||||
|
102
.github/workflows/main.yml
vendored
102
.github/workflows/main.yml
vendored
@ -19,9 +19,11 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- run: git submodule status > submodule.status
|
- name: Set cache key
|
||||||
- id: get_cache_key
|
id: get_cache_key
|
||||||
run: echo "::set-output name=cache_key::cache-repo-${{ hashFiles('yarn.lock', 'package.json', 'submodule.status') }}"
|
run: |
|
||||||
|
git submodule status > submodule.status
|
||||||
|
echo "::set-output name=cache_key::cache-repo-${{ hashFiles('yarn.lock', 'package.json', 'submodule.status') }}"
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v2
|
||||||
id: cache-repo
|
id: cache-repo
|
||||||
with:
|
with:
|
||||||
@ -29,7 +31,8 @@ jobs:
|
|||||||
**/node_modules
|
**/node_modules
|
||||||
contracts/build
|
contracts/build
|
||||||
key: ${{ steps.get_cache_key.outputs.cache_key }}
|
key: ${{ steps.get_cache_key.outputs.cache_key }}
|
||||||
- if: ${{ !steps.cache-repo.outputs.cache-hit }}
|
- name: Install dependencies and compile contracts
|
||||||
|
if: ${{ !steps.cache-repo.outputs.cache-hit }}
|
||||||
run: |
|
run: |
|
||||||
yarn install --frozen-lockfile
|
yarn install --frozen-lockfile
|
||||||
yarn run install:deploy
|
yarn run install:deploy
|
||||||
@ -56,7 +59,8 @@ jobs:
|
|||||||
**/node_modules
|
**/node_modules
|
||||||
contracts/build
|
contracts/build
|
||||||
key: ${{ needs.initialize.outputs.cache_key }}
|
key: ${{ needs.initialize.outputs.cache_key }}
|
||||||
- run: ${{ steps.cache-repo.outputs.cache-hit }} && yarn run ${{ matrix.task }}
|
- name: yarn run ${{ matrix.task }}
|
||||||
|
run: ${{ steps.cache-repo.outputs.cache-hit }} && yarn run ${{ matrix.task }}
|
||||||
ui-coverage:
|
ui-coverage:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
@ -76,7 +80,8 @@ jobs:
|
|||||||
**/node_modules
|
**/node_modules
|
||||||
contracts/build
|
contracts/build
|
||||||
key: ${{ needs.initialize.outputs.cache_key }}
|
key: ${{ needs.initialize.outputs.cache_key }}
|
||||||
- run: ${{ steps.cache-repo.outputs.cache-hit }} && yarn workspace ui run coverage
|
- name: yarn workspace ui run coverage
|
||||||
|
run: ${{ steps.cache-repo.outputs.cache-hit }} && yarn workspace ui run coverage
|
||||||
- uses: coverallsapp/github-action@master
|
- uses: coverallsapp/github-action@master
|
||||||
with:
|
with:
|
||||||
github-token: ${{ github.token }}
|
github-token: ${{ github.token }}
|
||||||
@ -87,14 +92,16 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- run: |
|
- name: Evaluate e2e docker images tags
|
||||||
|
run: |
|
||||||
git submodule status > submodule.status
|
git submodule status > submodule.status
|
||||||
echo "::set-env name=E2E_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}"
|
echo "E2E_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=ORACLE_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}"
|
echo "ORACLE_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=MONITOR_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}"
|
echo "MONITOR_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=UI_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'ui') }}"
|
echo "UI_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'ui') }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=ALM_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}"
|
echo "ALM_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}" >> $GITHUB_ENV
|
||||||
- run: |
|
- name: Rebuild and push updated images
|
||||||
|
run: |
|
||||||
function check_if_image_exists() {
|
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
|
curl -fsSlL -H 'Authorization: bearer ${{ github.token }}' "https://${DOCKER_REGISTRY}/v2/${DOCKER_REPO}/tokenbridge-e2e-$1/manifests/$2" > /dev/null
|
||||||
}
|
}
|
||||||
@ -119,8 +126,10 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- run: echo "::set-env name=MOLECULE_RUNNER_TAG::${{ hashFiles('./deployment-e2e/Dockerfile') }}"
|
- name: Evaluate e2e molecule runner tag
|
||||||
- run: |
|
run: echo "MOLECULE_RUNNER_TAG=${{ hashFiles('./deployment-e2e/Dockerfile') }}" >> $GITHUB_ENV
|
||||||
|
- name: Rebuild and push molecule runner e2e image
|
||||||
|
run: |
|
||||||
function check_if_image_exists() {
|
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
|
curl -fsSlL -H 'Authorization: bearer ${{ github.token }}' "https://${DOCKER_REGISTRY}/v2/${DOCKER_REPO}/tokenbridge-e2e-$1/manifests/$2" > /dev/null
|
||||||
}
|
}
|
||||||
@ -150,14 +159,15 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- run: |
|
- name: Evaluate e2e docker images tags
|
||||||
|
run: |
|
||||||
git submodule status > submodule.status
|
git submodule status > submodule.status
|
||||||
echo "::set-env name=E2E_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}"
|
echo "E2E_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=ORACLE_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}"
|
echo "ORACLE_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=MONITOR_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}"
|
echo "MONITOR_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=UI_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'ui') }}"
|
echo "UI_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'ui') }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=ALM_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}"
|
echo "ALM_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}" >> $GITHUB_ENV
|
||||||
- if: ${{ matrix.use-cache }}
|
- if: ${{ matrix.use-cache }}
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
id: cache-repo
|
id: cache-repo
|
||||||
with:
|
with:
|
||||||
@ -165,8 +175,10 @@ jobs:
|
|||||||
**/node_modules
|
**/node_modules
|
||||||
contracts/build
|
contracts/build
|
||||||
key: ${{ needs.initialize.outputs.cache_key }}
|
key: ${{ needs.initialize.outputs.cache_key }}
|
||||||
- run: docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }}
|
- name: Login to docker registry
|
||||||
- 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 }}
|
||||||
|
- name: yarn run ${{ matrix.task }}
|
||||||
|
run: ${{ !matrix.use-cache || steps.cache-repo.outputs.cache-hit }} && yarn run ${{ matrix.task }}
|
||||||
deployment:
|
deployment:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
@ -179,8 +191,10 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- run: echo "::set-env name=MOLECULE_RUNNER_TAG::${{ hashFiles('./deployment-e2e/Dockerfile') }}"
|
- name: Evaluate e2e molecule runner tag
|
||||||
- run: docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }}
|
run: echo "MOLECULE_RUNNER_TAG=${{ hashFiles('./deployment-e2e/Dockerfile') }}" >> $GITHUB_ENV
|
||||||
|
- name: Login to docker registry
|
||||||
|
run: docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }}
|
||||||
- run: deployment-e2e/molecule.sh ${{ matrix.task }}
|
- run: deployment-e2e/molecule.sh ${{ matrix.task }}
|
||||||
ultimate:
|
ultimate:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -205,14 +219,15 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- run: |
|
- name: Evaluate e2e docker images tags
|
||||||
|
run: |
|
||||||
git submodule status > submodule.status
|
git submodule status > submodule.status
|
||||||
echo "::set-env name=E2E_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}"
|
echo "E2E_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=ORACLE_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}"
|
echo "ORACLE_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=MONITOR_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}"
|
echo "MONITOR_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=UI_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'ui') }}"
|
echo "UI_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'ui') }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=ALM_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}"
|
echo "ALM_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=MOLECULE_RUNNER_TAG::${{ hashFiles('./deployment-e2e/Dockerfile') }}"
|
echo "MOLECULE_RUNNER_TAG=${{ hashFiles('./deployment-e2e/Dockerfile') }}" >> $GITHUB_ENV
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v2
|
||||||
id: cache-repo
|
id: cache-repo
|
||||||
with:
|
with:
|
||||||
@ -220,12 +235,19 @@ jobs:
|
|||||||
**/node_modules
|
**/node_modules
|
||||||
contracts/build
|
contracts/build
|
||||||
key: ${{ needs.initialize.outputs.cache_key }}
|
key: ${{ needs.initialize.outputs.cache_key }}
|
||||||
- run: docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }}
|
- name: Login to docker registry
|
||||||
- run: ${{ steps.cache-repo.outputs.cache-hit }} && e2e-commons/up.sh deploy blocks
|
run: docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }}
|
||||||
- run: docker-compose -f ./e2e-commons/docker-compose.yml pull oracle
|
- name: Deploy contracts
|
||||||
- run: deployment-e2e/molecule.sh ultimate-${{ matrix.task }}
|
run: ${{ steps.cache-repo.outputs.cache-hit }} && e2e-commons/up.sh deploy blocks
|
||||||
- run: sudo chown -R $USER:docker /var/run/docker.sock
|
- name: Pull e2e oracle image
|
||||||
- if: ${{ matrix.ui-e2e-grep }}
|
run: docker-compose -f ./e2e-commons/docker-compose.yml pull oracle
|
||||||
|
- name: Deploy oracle and ui
|
||||||
|
run: deployment-e2e/molecule.sh ultimate-${{ matrix.task }}
|
||||||
|
- name: Reset docker socket permissions
|
||||||
|
run: sudo chown -R $USER:docker /var/run/docker.sock
|
||||||
|
- name: Run ui e2e tests
|
||||||
|
if: ${{ matrix.ui-e2e-grep }}
|
||||||
run: cd ui-e2e && xvfb-run yarn mocha -g "${{ matrix.ui-e2e-grep }}" -b ./test.js
|
run: cd ui-e2e && xvfb-run yarn mocha -g "${{ matrix.ui-e2e-grep }}" -b ./test.js
|
||||||
- if: ${{ !matrix.ui-e2e-grep }}
|
- name: Run oracle e2e tests
|
||||||
|
if: ${{ !matrix.ui-e2e-grep }}
|
||||||
run: docker-compose -f ./e2e-commons/docker-compose.yml run e2e yarn workspace oracle-e2e run ${{ matrix.task }}
|
run: docker-compose -f ./e2e-commons/docker-compose.yml run e2e yarn workspace oracle-e2e run ${{ matrix.task }}
|
||||||
|
10
.gitignore
vendored
10
.gitignore
vendored
@ -10,11 +10,8 @@ dist
|
|||||||
|
|
||||||
# misc
|
# misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.env
|
*.env*
|
||||||
.env.local
|
!.env.example
|
||||||
.env.development.local
|
|
||||||
.env.test.local
|
|
||||||
.env.production.local
|
|
||||||
.idea
|
.idea
|
||||||
.nyc_output
|
.nyc_output
|
||||||
logs/
|
logs/
|
||||||
@ -49,5 +46,6 @@ __pycache__
|
|||||||
|
|
||||||
#monitor
|
#monitor
|
||||||
monitor/responses/*
|
monitor/responses/*
|
||||||
monitor/configs/*.env
|
monitor/cache/*
|
||||||
|
!monitor/cache/.gitkeep
|
||||||
!monitor/.gitkeep
|
!monitor/.gitkeep
|
||||||
|
@ -41,6 +41,7 @@ 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_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_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_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
|
## UI configuration
|
||||||
@ -78,3 +79,6 @@ MONITOR_TX_NUMBER_THRESHOLD | If estimated number of transaction is equal to or
|
|||||||
MONITOR_PORT | The port for the Monitor. | 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_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_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`
|
||||||
|
BIN
audit/quantstamp/POA-Network-TokenBridge-contracts-5.4.1-security-assessment-report.pdf
Normal file
BIN
audit/quantstamp/POA-Network-TokenBridge-contracts-5.4.1-security-assessment-report.pdf
Normal file
Binary file not shown.
@ -5,7 +5,8 @@
|
|||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"no-unused-expressions": "off",
|
"no-unused-expressions": "off",
|
||||||
"import/no-extraneous-dependencies": "off"
|
"import/no-extraneous-dependencies": "off",
|
||||||
|
"no-bitwise": "off"
|
||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
"mocha": true
|
"mocha": true
|
||||||
|
@ -6,17 +6,30 @@ function addTxHashToData({ encodedData, transactionHash }) {
|
|||||||
return encodedData.slice(0, 2) + strip0x(transactionHash) + encodedData.slice(2)
|
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) {
|
function parseAMBMessage(message) {
|
||||||
message = strip0x(message)
|
message = strip0x(message)
|
||||||
|
|
||||||
const messageId = `0x${message.slice(0, 64)}`
|
const messageId = `0x${message.slice(0, 64)}`
|
||||||
const sender = `0x${message.slice(64, 104)}`
|
const sender = `0x${message.slice(64, 104)}`
|
||||||
const executor = `0x${message.slice(104, 144)}`
|
const executor = `0x${message.slice(104, 144)}`
|
||||||
|
const dataType = parseInt(message.slice(156, 158), 16)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sender,
|
sender,
|
||||||
executor,
|
executor,
|
||||||
messageId
|
messageId,
|
||||||
|
dataType,
|
||||||
|
decodedDataType: decodeAMBDataType(dataType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ const getPastEvents = async (
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.message.includes('query returned more than') && toBlock !== 'latest') {
|
if (e.message.includes('query returned more than') && toBlock !== 'latest') {
|
||||||
const middle = toBN(fromBlock)
|
const middle = toBN(fromBlock)
|
||||||
.add(toBlock)
|
.add(toBN(toBlock))
|
||||||
.divRound(toBN(2))
|
.divRound(toBN(2))
|
||||||
const middlePlusOne = middle.add(toBN(1))
|
const middlePlusOne = middle.add(toBN(1))
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit dd46135248dbb4684752735aab3cf64db170a405
|
Subproject commit 835742dfd8f1c869d4e7b61582155d250d6cf094
|
@ -1 +1,2 @@
|
|||||||
0xc9e38bfdB9c635F0796ad83CC8705dc379F41c04
|
0xc9e38bfdB9c635F0796ad83CC8705dc379F41c04
|
||||||
|
0x612E8bd50A7b1F009F43f2b8679E9B8eD91eb5CE
|
||||||
|
@ -23,3 +23,4 @@ ORACLE_FOREIGN_RPC_POLLING_INTERVAL=500
|
|||||||
ORACLE_ALLOW_HTTP_FOR_RPC=yes
|
ORACLE_ALLOW_HTTP_FOR_RPC=yes
|
||||||
ORACLE_HOME_START_BLOCK=1
|
ORACLE_HOME_START_BLOCK=1
|
||||||
ORACLE_FOREIGN_START_BLOCK=1
|
ORACLE_FOREIGN_START_BLOCK=1
|
||||||
|
ORACLE_HOME_TO_FOREIGN_BLOCK_LIST=/mono/oracle/access-lists/block_list.txt
|
||||||
|
@ -63,6 +63,7 @@
|
|||||||
"foreign": "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0",
|
"foreign": "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0",
|
||||||
"homeBox": "0x6C4EaAb8756d53Bf599FFe2347FAFF1123D6C8A1",
|
"homeBox": "0x6C4EaAb8756d53Bf599FFe2347FAFF1123D6C8A1",
|
||||||
"foreignBox": "0x6C4EaAb8756d53Bf599FFe2347FAFF1123D6C8A1",
|
"foreignBox": "0x6C4EaAb8756d53Bf599FFe2347FAFF1123D6C8A1",
|
||||||
|
"blockedHomeBox": "0x612E8bd50A7b1F009F43f2b8679E9B8eD91eb5CE",
|
||||||
"monitor": "http://monitor-amb:3013/bridge"
|
"monitor": "http://monitor-amb:3013/bridge"
|
||||||
},
|
},
|
||||||
"ambStakeErcToErc": {
|
"ambStakeErcToErc": {
|
||||||
|
@ -61,6 +61,9 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- NODE_ENV=production
|
- NODE_ENV=production
|
||||||
command: "true"
|
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:
|
networks:
|
||||||
- ultimate
|
- ultimate
|
||||||
ui:
|
ui:
|
||||||
|
@ -53,3 +53,8 @@ node deploy.js
|
|||||||
cd - > /dev/null
|
cd - > /dev/null
|
||||||
node setupStakeTokens.js
|
node setupStakeTokens.js
|
||||||
cd - > /dev/null
|
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
|
||||||
|
@ -17,21 +17,29 @@ docker-compose up -d parity1 parity2 e2e
|
|||||||
startValidator () {
|
startValidator () {
|
||||||
docker-compose $1 run -d --name $4 redis
|
docker-compose $1 run -d --name $4 redis
|
||||||
docker-compose $1 run -d --name $5 rabbit
|
docker-compose $1 run -d --name $5 rabbit
|
||||||
docker-compose $1 run $2 $3 -d oracle yarn watcher:signature-request
|
if [[ -z "$MODE" || "$MODE" == native-to-erc ]]; then
|
||||||
docker-compose $1 run $2 $3 -d oracle yarn watcher:collected-signatures
|
docker-compose $1 run $2 $3 -d oracle yarn watcher:signature-request
|
||||||
docker-compose $1 run $2 $3 -d oracle yarn watcher:affirmation-request
|
docker-compose $1 run $2 $3 -d oracle yarn watcher:collected-signatures
|
||||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:signature-request
|
docker-compose $1 run $2 $3 -d oracle yarn watcher:affirmation-request
|
||||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:collected-signatures
|
fi
|
||||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:affirmation-request
|
if [[ -z "$MODE" || "$MODE" == erc-to-erc ]]; then
|
||||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:transfer
|
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:signature-request
|
||||||
docker-compose $1 run $2 $3 -d oracle-erc20-native 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-native 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-native yarn watcher:affirmation-request
|
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:transfer
|
||||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:transfer
|
fi
|
||||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn worker:convert-to-chai
|
if [[ -z "$MODE" || "$MODE" == erc-to-native ]]; then
|
||||||
docker-compose $1 run $2 $3 -d oracle-amb yarn watcher:signature-request
|
docker-compose $1 run $2 $3 -d oracle-erc20-native 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-erc20-native yarn watcher:collected-signatures
|
||||||
docker-compose $1 run $2 $3 -d oracle-amb yarn watcher:affirmation-request
|
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:affirmation-request
|
||||||
|
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:transfer
|
||||||
|
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn 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:home
|
||||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn sender:foreign
|
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn sender:foreign
|
||||||
}
|
}
|
||||||
@ -48,25 +56,7 @@ startAMBValidator () {
|
|||||||
|
|
||||||
while [ "$1" != "" ]; do
|
while [ "$1" != "" ]; do
|
||||||
if [ "$1" == "oracle" ]; then
|
if [ "$1" == "oracle" ]; then
|
||||||
docker-compose up -d redis rabbit
|
startValidator "" "" "" "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
|
fi
|
||||||
|
|
||||||
if [ "$1" == "oracle-validator-2" ]; then
|
if [ "$1" == "oracle-validator-2" ]; then
|
||||||
@ -110,7 +100,23 @@ while [ "$1" != "" ]; do
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$1" == "monitor" ]; then
|
if [ "$1" == "monitor" ]; then
|
||||||
docker-compose up -d monitor monitor-erc20 monitor-erc20-native monitor-amb
|
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
|
fi
|
||||||
|
|
||||||
if [ "$1" == "alm-e2e" ]; then
|
if [ "$1" == "alm-e2e" ]; then
|
||||||
|
@ -1,7 +1,15 @@
|
|||||||
while true; do
|
while true; do
|
||||||
sleep 5
|
docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor yarn check-all
|
||||||
docker-compose -f ../e2e-commons/docker-compose.yml exec -d monitor yarn check-all
|
pid1=$!
|
||||||
docker-compose -f ../e2e-commons/docker-compose.yml exec -d monitor-erc20 yarn check-all
|
docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20 yarn check-all
|
||||||
docker-compose -f ../e2e-commons/docker-compose.yml exec -d monitor-erc20-native yarn check-all
|
pid2=$!
|
||||||
docker-compose -f ../e2e-commons/docker-compose.yml exec -d monitor-amb yarn check-all
|
docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20-native yarn check-all
|
||||||
|
pid3=$!
|
||||||
|
docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-amb yarn check-all
|
||||||
|
pid4=$!
|
||||||
|
|
||||||
|
wait $pid1
|
||||||
|
wait $pid2
|
||||||
|
wait $pid3
|
||||||
|
wait $pid4
|
||||||
done
|
done
|
||||||
|
@ -1,12 +1,28 @@
|
|||||||
cd $(dirname $0)
|
cd $(dirname $0)
|
||||||
|
|
||||||
../e2e-commons/up.sh deploy blocks monitor
|
mode="$1"
|
||||||
|
case "$mode" in
|
||||||
|
amb)
|
||||||
|
script=./test/amb.js
|
||||||
|
;;
|
||||||
|
native-to-erc)
|
||||||
|
script=./test/nativeToErc.js
|
||||||
|
;;
|
||||||
|
erc-to-erc)
|
||||||
|
script=./test/ercToErc.js
|
||||||
|
;;
|
||||||
|
erc-to-native)
|
||||||
|
script=./test/ercToNative.js
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
./wait-for-monitor.sh
|
MODE="$mode" ../e2e-commons/up.sh deploy blocks monitor
|
||||||
|
|
||||||
|
MODE="$mode" ./wait-for-monitor.sh
|
||||||
nohup ./periodically-check-all.sh < /dev/null > /dev/null 2>&1 &
|
nohup ./periodically-check-all.sh < /dev/null > /dev/null 2>&1 &
|
||||||
checkPID=$!
|
checkPID=$!
|
||||||
|
|
||||||
docker-compose -f ../e2e-commons/docker-compose.yml run e2e yarn workspace monitor-e2e run start
|
docker-compose -f ../e2e-commons/docker-compose.yml run e2e yarn workspace monitor-e2e run start $script
|
||||||
rc=$?
|
rc=$?
|
||||||
|
|
||||||
../e2e-commons/down.sh
|
../e2e-commons/down.sh
|
||||||
|
@ -25,6 +25,7 @@ describe('AMB', () => {
|
|||||||
|
|
||||||
describe('general', async () => {
|
describe('general', async () => {
|
||||||
it('should contain fromHomeToForeignDiff', () => assert(data.fromHomeToForeignDiff === 0))
|
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 fromForeignToHomeDiff', () => assert(data.fromForeignToHomeDiff === 0))
|
||||||
it('should contain lastChecked', () => assert(data.lastChecked >= 0))
|
it('should contain lastChecked', () => assert(data.lastChecked >= 0))
|
||||||
it('should contain timeDiff', () => assert(data.timeDiff >= 0))
|
it('should contain timeDiff', () => assert(data.timeDiff >= 0))
|
||||||
@ -114,7 +115,16 @@ describe('AMB', () => {
|
|||||||
|
|
||||||
await waitUntil(async () => {
|
await waitUntil(async () => {
|
||||||
;({ data } = await axios.get(`${baseUrl}`))
|
;({ data } = await axios.get(`${baseUrl}`))
|
||||||
return data.fromHomeToForeignDiff !== 0
|
return data.fromHomeToForeignDiff === 1 && data.fromHomeToForeignPBUDiff === 0
|
||||||
|
})
|
||||||
|
})
|
||||||
|
it('should change fromHomeToForeignPBUDiff', async () => {
|
||||||
|
// send message
|
||||||
|
await sendAMBMessage(homeRPC.URL, user, amb.homeBox, amb.home, amb.foreignBox, true)
|
||||||
|
|
||||||
|
await waitUntil(async () => {
|
||||||
|
;({ data } = await axios.get(`${baseUrl}`))
|
||||||
|
return data.fromHomeToForeignDiff === 1 && data.fromHomeToForeignPBUDiff === 1
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
it('should change validatorsMatch', async () => {
|
it('should change validatorsMatch', async () => {
|
||||||
|
@ -54,16 +54,16 @@ describe('ERC TO NATIVE with changing state of contracts', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should consider chai token balance', async function() {
|
it('should consider chai token balance', async function() {
|
||||||
this.timeout(60000)
|
this.timeout(120000)
|
||||||
await initializeChaiToken(foreignRPC.URL, ercToNativeBridge.foreign)
|
await initializeChaiToken(foreignRPC.URL, ercToNativeBridge.foreign)
|
||||||
await sendTokens(foreignRPC.URL, user, ercToNativeBridge.foreignToken, ercToNativeBridge.foreign)
|
await sendTokens(foreignRPC.URL, user, ercToNativeBridge.foreignToken, ercToNativeBridge.foreign)
|
||||||
|
|
||||||
await waitUntil(async () => {
|
await waitUntil(async () => {
|
||||||
;({ data } = await axios.get(`${baseUrl}`))
|
;({ data } = await axios.get(`${baseUrl}`))
|
||||||
const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
|
|
||||||
if (!data.foreign) {
|
if (!data.foreign) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
|
||||||
return (
|
return (
|
||||||
data.balanceDiff === 0.02 &&
|
data.balanceDiff === 0.02 &&
|
||||||
erc20Balance === '0.02' &&
|
erc20Balance === '0.02' &&
|
||||||
@ -77,10 +77,10 @@ describe('ERC TO NATIVE with changing state of contracts', () => {
|
|||||||
|
|
||||||
await waitUntil(async () => {
|
await waitUntil(async () => {
|
||||||
;({ data } = await axios.get(`${baseUrl}`))
|
;({ data } = await axios.get(`${baseUrl}`))
|
||||||
const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
|
|
||||||
if (!data.foreign) {
|
if (!data.foreign) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
|
||||||
return (
|
return (
|
||||||
data.balanceDiff === 0.02 &&
|
data.balanceDiff === 0.02 &&
|
||||||
erc20Balance === '0.01' &&
|
erc20Balance === '0.01' &&
|
||||||
@ -94,10 +94,10 @@ describe('ERC TO NATIVE with changing state of contracts', () => {
|
|||||||
|
|
||||||
await waitUntil(async () => {
|
await waitUntil(async () => {
|
||||||
;({ data } = await axios.get(`${baseUrl}`))
|
;({ data } = await axios.get(`${baseUrl}`))
|
||||||
const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
|
|
||||||
if (!data.foreign) {
|
if (!data.foreign) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
|
||||||
return (
|
return (
|
||||||
data.balanceDiff === 0.02 &&
|
data.balanceDiff === 0.02 &&
|
||||||
erc20Balance === '0.005' &&
|
erc20Balance === '0.005' &&
|
||||||
|
@ -44,12 +44,16 @@ const sendTokens = async (rpcUrl, account, tokenAddress, recipientAddress) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendAMBMessage = async (rpcUrl, account, boxAddress, bridgeAddress, boxOtherSideAddress) => {
|
const sendAMBMessage = async (rpcUrl, account, boxAddress, bridgeAddress, boxOtherSideAddress, manualLane = false) => {
|
||||||
const web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl))
|
const web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl))
|
||||||
web3.eth.accounts.wallet.add(account.privateKey)
|
web3.eth.accounts.wallet.add(account.privateKey)
|
||||||
const homeBox = new web3.eth.Contract(BOX_ABI, boxAddress)
|
const homeBox = new web3.eth.Contract(BOX_ABI, boxAddress)
|
||||||
|
|
||||||
await homeBox.methods.setValueOnOtherNetwork(3, bridgeAddress, boxOtherSideAddress).send({
|
await homeBox.methods[manualLane ? 'setValueOnOtherNetworkUsingManualLane' : 'setValueOnOtherNetwork'](
|
||||||
|
3,
|
||||||
|
bridgeAddress,
|
||||||
|
boxOtherSideAddress
|
||||||
|
).send({
|
||||||
from: account.address,
|
from: account.address,
|
||||||
gas: '400000'
|
gas: '400000'
|
||||||
})
|
})
|
||||||
|
@ -6,10 +6,18 @@ check_files_exist() {
|
|||||||
rc=0
|
rc=0
|
||||||
for f in "${FILES[@]}"; do
|
for f in "${FILES[@]}"; do
|
||||||
command="test -f responses/bridge/$f"
|
command="test -f responses/bridge/$f"
|
||||||
(docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor /bin/bash -c "$command") || rc=1
|
if [[ -z "$MODE" || "$MODE" == native-to-erc ]]; then
|
||||||
(docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20 /bin/bash -c "$command") || rc=1
|
(docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor /bin/bash -c "$command") || rc=1
|
||||||
(docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20-native /bin/bash -c "$command") || rc=1
|
fi
|
||||||
(docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-amb /bin/bash -c "$command") || rc=1
|
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
|
done
|
||||||
return $rc
|
return $rc
|
||||||
}
|
}
|
||||||
|
@ -22,3 +22,6 @@ COMMON_FOREIGN_GAS_PRICE_FACTOR=1
|
|||||||
MONITOR_TX_NUMBER_THRESHOLD=100
|
MONITOR_TX_NUMBER_THRESHOLD=100
|
||||||
MONITOR_PORT=3003
|
MONITOR_PORT=3003
|
||||||
MONITOR_CACHE_EVENTS=true
|
MONITOR_CACHE_EVENTS=true
|
||||||
|
|
||||||
|
MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST=
|
||||||
|
MONITOR_HOME_TO_FOREIGN_BLOCK_LIST=
|
||||||
|
@ -1,18 +1,9 @@
|
|||||||
require('dotenv').config()
|
require('dotenv').config()
|
||||||
const Web3 = require('web3')
|
|
||||||
const logger = require('./logger')('alerts')
|
const logger = require('./logger')('alerts')
|
||||||
const eventsInfo = require('./utils/events')
|
const eventsInfo = require('./utils/events')
|
||||||
const { getBlockNumber } = require('./utils/contract')
|
|
||||||
const { processedMsgNotDelivered, eventWithoutReference } = require('./utils/message')
|
const { processedMsgNotDelivered, eventWithoutReference } = require('./utils/message')
|
||||||
const { BRIDGE_MODES } = require('../commons')
|
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() {
|
async function main() {
|
||||||
const {
|
const {
|
||||||
@ -33,7 +24,8 @@ async function main() {
|
|||||||
xAffirmations = foreignToHomeConfirmations.filter(eventWithoutReference(foreignToHomeRequests))
|
xAffirmations = foreignToHomeConfirmations.filter(eventWithoutReference(foreignToHomeRequests))
|
||||||
}
|
}
|
||||||
logger.debug('building misbehavior blocks')
|
logger.debug('building misbehavior blocks')
|
||||||
const [homeBlockNumber, foreignBlockNumber] = await getBlockNumber(web3Home, web3Foreign)
|
const homeBlockNumber = await getHomeBlockNumber()
|
||||||
|
const foreignBlockNumber = await getForeignBlockNumber()
|
||||||
|
|
||||||
const baseRange = [false, false, false, false, false]
|
const baseRange = [false, false, false, false, false]
|
||||||
const xSignaturesMisbehavior = buildRangesObject(
|
const xSignaturesMisbehavior = buildRangesObject(
|
||||||
@ -73,21 +65,21 @@ async function main() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the location for the blockNumber in a specific range starting from currentBlockNumber
|
* Finds the location for the blockNumber in a specific range starting from currentBlockNumber
|
||||||
* @param {BN} currentBlockNumber
|
* @param {Number} currentBlockNumber
|
||||||
* @returns {function({blockNumber?: *}): boolean[]}
|
* @returns {function({blockNumber?: *}): boolean[]}
|
||||||
*/
|
*/
|
||||||
const findMisbehaviorRange = currentBlockNumber => ({ blockNumber }) => {
|
const findMisbehaviorRange = currentBlockNumber => ({ blockNumber }) => {
|
||||||
const minus60 = currentBlockNumber.sub(Web3.utils.toBN(60))
|
const minus60 = currentBlockNumber - 60
|
||||||
const minus180 = currentBlockNumber.sub(Web3.utils.toBN(180))
|
const minus180 = currentBlockNumber - 180
|
||||||
const minus720 = currentBlockNumber.sub(Web3.utils.toBN(720))
|
const minus720 = currentBlockNumber - 720
|
||||||
const minus17280 = currentBlockNumber.sub(Web3.utils.toBN(17280))
|
const minus17280 = currentBlockNumber - 17280
|
||||||
|
|
||||||
return [
|
return [
|
||||||
minus60.lte(blockNumber),
|
minus60 <= blockNumber,
|
||||||
minus180.lte(blockNumber) && minus60.gt(blockNumber),
|
minus180 <= blockNumber && minus60 > blockNumber,
|
||||||
minus720.lte(blockNumber) && minus180.gt(blockNumber),
|
minus720 <= blockNumber && minus180 > blockNumber,
|
||||||
minus17280.lte(blockNumber) && minus720.gt(blockNumber),
|
minus17280 <= blockNumber && minus720 > blockNumber,
|
||||||
minus17280.gt(blockNumber)
|
minus17280 > blockNumber
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
0
monitor/cache/.gitkeep
vendored
Normal file
0
monitor/cache/.gitkeep
vendored
Normal file
@ -1,21 +1,21 @@
|
|||||||
require('dotenv').config()
|
require('dotenv').config()
|
||||||
const Web3 = require('web3')
|
const BN = require('bignumber.js')
|
||||||
const logger = require('./logger')('checkWorker')
|
const logger = require('./logger')('checkWorker')
|
||||||
const { getBridgeMode } = require('../commons')
|
const { getBridgeMode } = require('../commons')
|
||||||
const getBalances = require('./getBalances')
|
const getBalances = require('./getBalances')
|
||||||
const getShortEventStats = require('./getShortEventStats')
|
const getShortEventStats = require('./getShortEventStats')
|
||||||
const validators = require('./validators')
|
const validators = require('./validators')
|
||||||
|
const getEventsInfo = require('./utils/events')
|
||||||
const { writeFile, createDir } = require('./utils/file')
|
const { writeFile, createDir } = require('./utils/file')
|
||||||
|
const { saveCache } = require('./utils/web3Cache')
|
||||||
|
const { web3Home } = require('./utils/web3')
|
||||||
|
|
||||||
const { COMMON_HOME_BRIDGE_ADDRESS, COMMON_HOME_RPC_URL, MONITOR_BRIDGE_NAME } = process.env
|
const { COMMON_HOME_BRIDGE_ADDRESS, MONITOR_BRIDGE_NAME } = process.env
|
||||||
|
|
||||||
const MONITOR_VALIDATOR_HOME_TX_LIMIT = Number(process.env.MONITOR_VALIDATOR_HOME_TX_LIMIT) || 0
|
const MONITOR_VALIDATOR_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_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 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')
|
const { HOME_ERC_TO_ERC_ABI } = require('../commons')
|
||||||
|
|
||||||
async function checkWorker() {
|
async function checkWorker() {
|
||||||
@ -24,16 +24,22 @@ async function checkWorker() {
|
|||||||
const homeBridge = new web3Home.eth.Contract(HOME_ERC_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
const homeBridge = new web3Home.eth.Contract(HOME_ERC_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
||||||
const bridgeMode = await getBridgeMode(homeBridge)
|
const bridgeMode = await getBridgeMode(homeBridge)
|
||||||
logger.debug('Bridge mode:', bridgeMode)
|
logger.debug('Bridge mode:', bridgeMode)
|
||||||
|
logger.debug('calling getEventsInfo()')
|
||||||
|
const eventsInfo = await getEventsInfo(bridgeMode)
|
||||||
logger.debug('calling getBalances()')
|
logger.debug('calling getBalances()')
|
||||||
const balances = await getBalances(bridgeMode)
|
const balances = await getBalances(bridgeMode, eventsInfo)
|
||||||
logger.debug('calling getShortEventStats()')
|
logger.debug('calling getShortEventStats()')
|
||||||
const events = await getShortEventStats(bridgeMode)
|
const events = await getShortEventStats(bridgeMode, eventsInfo)
|
||||||
const home = Object.assign({}, balances.home, events.home)
|
const home = Object.assign({}, balances.home, events.home)
|
||||||
const foreign = Object.assign({}, balances.foreign, events.foreign)
|
const foreign = Object.assign({}, balances.foreign, events.foreign)
|
||||||
const status = Object.assign({}, balances, events, { home }, { 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))
|
if (!status) throw new Error('status is empty: ' + JSON.stringify(status))
|
||||||
status.health = true
|
status.health = true
|
||||||
writeFile(`/responses/${MONITOR_BRIDGE_NAME}/getBalances.json`, status)
|
writeFile(`/responses/${MONITOR_BRIDGE_NAME}/getBalances.json`, status)
|
||||||
|
saveCache()
|
||||||
|
|
||||||
logger.debug('calling validators()')
|
logger.debug('calling validators()')
|
||||||
const vBalances = await validators(bridgeMode)
|
const vBalances = await validators(bridgeMode)
|
||||||
|
@ -3,6 +3,7 @@ const logger = require('./logger')('checkWorker2')
|
|||||||
const eventsStats = require('./eventsStats')
|
const eventsStats = require('./eventsStats')
|
||||||
const alerts = require('./alerts')
|
const alerts = require('./alerts')
|
||||||
const { writeFile, createDir } = require('./utils/file')
|
const { writeFile, createDir } = require('./utils/file')
|
||||||
|
const { saveCache } = require('./utils/web3Cache')
|
||||||
|
|
||||||
const { MONITOR_BRIDGE_NAME } = process.env
|
const { MONITOR_BRIDGE_NAME } = process.env
|
||||||
|
|
||||||
@ -26,6 +27,7 @@ async function checkWorker2() {
|
|||||||
_alerts.ok = !_alerts.executeAffirmations.mostRecentTxHash && !_alerts.executeSignatures.mostRecentTxHash
|
_alerts.ok = !_alerts.executeAffirmations.mostRecentTxHash && !_alerts.executeSignatures.mostRecentTxHash
|
||||||
_alerts.health = true
|
_alerts.health = true
|
||||||
writeFile(`/responses/${MONITOR_BRIDGE_NAME}/alerts.json`, _alerts)
|
writeFile(`/responses/${MONITOR_BRIDGE_NAME}/alerts.json`, _alerts)
|
||||||
|
saveCache()
|
||||||
logger.debug('Done x2')
|
logger.debug('Done x2')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
require('dotenv').config()
|
require('dotenv').config()
|
||||||
const Web3 = require('web3')
|
|
||||||
const logger = require('./logger')('checkWorker3')
|
const logger = require('./logger')('checkWorker3')
|
||||||
const stuckTransfers = require('./stuckTransfers')
|
const stuckTransfers = require('./stuckTransfers')
|
||||||
const { writeFile, createDir } = require('./utils/file')
|
const { writeFile, createDir } = require('./utils/file')
|
||||||
|
const { web3Home } = require('./utils/web3')
|
||||||
|
|
||||||
const { MONITOR_BRIDGE_NAME, COMMON_HOME_BRIDGE_ADDRESS, COMMON_HOME_RPC_URL } = process.env
|
const { MONITOR_BRIDGE_NAME, COMMON_HOME_BRIDGE_ADDRESS } = process.env
|
||||||
const { getBridgeMode, HOME_NATIVE_TO_ERC_ABI, BRIDGE_MODES } = require('../commons')
|
const { 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() {
|
async function checkWorker3() {
|
||||||
try {
|
try {
|
||||||
const homeBridge = new web3Home.eth.Contract(HOME_NATIVE_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
const homeBridge = new web3Home.eth.Contract(HOME_NATIVE_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
||||||
|
@ -4,11 +4,12 @@ services:
|
|||||||
monitor:
|
monitor:
|
||||||
image: poanetwork/tokenbridge-monitor:latest
|
image: poanetwork/tokenbridge-monitor:latest
|
||||||
ports:
|
ports:
|
||||||
- "${MONITOR_PORT}:${MONITOR_PORT}"
|
- "${MONITOR_PORT}:${MONITOR_PORT}"
|
||||||
env_file: ./.env
|
env_file: ./.env
|
||||||
environment:
|
environment:
|
||||||
- NODE_ENV=production
|
- NODE_ENV=production
|
||||||
volumes:
|
volumes:
|
||||||
- ./responses:/mono/monitor/responses
|
- ./responses:/mono/monitor/responses
|
||||||
|
- ./cache:/mono/monitor/cache
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
entrypoint: "yarn start"
|
entrypoint: "yarn start"
|
||||||
|
@ -1,8 +1,20 @@
|
|||||||
require('dotenv').config()
|
require('dotenv').config()
|
||||||
const eventsInfo = require('./utils/events')
|
const eventsInfo = require('./utils/events')
|
||||||
const { processedMsgNotDelivered, deliveredMsgNotProcessed, eventWithoutReference } = require('./utils/message')
|
const {
|
||||||
|
processedMsgNotDelivered,
|
||||||
|
deliveredMsgNotProcessed,
|
||||||
|
eventWithoutReference,
|
||||||
|
unclaimedHomeToForeignRequests
|
||||||
|
} = require('./utils/message')
|
||||||
|
const { getHomeTxSender } = require('./utils/web3Cache')
|
||||||
const { BRIDGE_MODES } = require('../commons')
|
const { 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() {
|
async function main() {
|
||||||
const {
|
const {
|
||||||
homeToForeignRequests,
|
homeToForeignRequests,
|
||||||
@ -33,17 +45,30 @@ async function main() {
|
|||||||
lastChecked: Math.floor(Date.now() / 1000)
|
lastChecked: Math.floor(Date.now() / 1000)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const onlyInHomeDeposits = homeToForeignRequests.filter(eventWithoutReference(homeToForeignConfirmations))
|
let onlyInHomeDeposits = homeToForeignRequests.filter(eventWithoutReference(homeToForeignConfirmations))
|
||||||
const onlyInForeignDeposits = homeToForeignConfirmations.filter(eventWithoutReference(homeToForeignRequests))
|
const onlyInForeignDeposits = homeToForeignConfirmations.filter(eventWithoutReference(homeToForeignRequests))
|
||||||
|
|
||||||
const onlyInHomeWithdrawals = foreignToHomeConfirmations.filter(eventWithoutReference(foreignToHomeRequests))
|
const onlyInHomeWithdrawals = foreignToHomeConfirmations.filter(eventWithoutReference(foreignToHomeRequests))
|
||||||
const onlyInForeignWithdrawals = foreignToHomeRequests.filter(eventWithoutReference(foreignToHomeConfirmations))
|
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 {
|
return {
|
||||||
onlyInHomeDeposits,
|
onlyInHomeDeposits,
|
||||||
onlyInForeignDeposits,
|
onlyInForeignDeposits,
|
||||||
onlyInHomeWithdrawals,
|
onlyInHomeWithdrawals,
|
||||||
onlyInForeignWithdrawals,
|
onlyInForeignWithdrawals,
|
||||||
|
...unclaimedStats,
|
||||||
lastChecked: Math.floor(Date.now() / 1000)
|
lastChecked: Math.floor(Date.now() / 1000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,11 @@
|
|||||||
require('dotenv').config()
|
require('dotenv').config()
|
||||||
const BN = require('bignumber.js')
|
const BN = require('bignumber.js')
|
||||||
const Web3 = require('web3')
|
const Web3Utils = require('web3').utils
|
||||||
const logger = require('./logger')('getBalances')
|
const logger = require('./logger')('getBalances')
|
||||||
const { BRIDGE_MODES } = require('../commons')
|
const { BRIDGE_MODES } = require('../commons')
|
||||||
|
const { web3Home, web3Foreign, getHomeBlockNumber } = require('./utils/web3')
|
||||||
|
|
||||||
const Web3Utils = Web3.utils
|
const { COMMON_HOME_BRIDGE_ADDRESS, COMMON_FOREIGN_BRIDGE_ADDRESS } = process.env
|
||||||
|
|
||||||
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 {
|
const {
|
||||||
ERC20_ABI,
|
ERC20_ABI,
|
||||||
@ -30,21 +18,50 @@ const {
|
|||||||
FOREIGN_NATIVE_TO_ERC_ABI
|
FOREIGN_NATIVE_TO_ERC_ABI
|
||||||
} = require('../commons')
|
} = require('../commons')
|
||||||
|
|
||||||
async function main(bridgeMode) {
|
async function main(bridgeMode, eventsInfo) {
|
||||||
|
const {
|
||||||
|
homeToForeignConfirmations,
|
||||||
|
foreignToHomeConfirmations,
|
||||||
|
homeDelayedBlockNumber,
|
||||||
|
foreignDelayedBlockNumber
|
||||||
|
} = eventsInfo
|
||||||
|
|
||||||
|
// Events in the ./utils/events.js are fetched for different block ranges,
|
||||||
|
// In order to be consistent with the balance values, the following values might be needed
|
||||||
|
|
||||||
|
// Foreign balance should represent all UserRequestForAffirmation events up to block `N - requiredBlockConfirmation()`
|
||||||
|
// and all RelayedMessage events up to block `N`.
|
||||||
|
// This constant tells the difference between bridge balance at block `N - requiredBlockConfirmation() + 1`
|
||||||
|
// and the actual value monitor is interested in.
|
||||||
|
const lateForeignConfirmationsTotalValue = BN.sum(
|
||||||
|
0,
|
||||||
|
...homeToForeignConfirmations.filter(e => e.blockNumber > foreignDelayedBlockNumber).map(e => e.value)
|
||||||
|
)
|
||||||
|
// Home balance should represent all UserRequestForSignature events up to block `M - requiredBlockConfirmation()`
|
||||||
|
// and all AffirmationCompleted events up to block `M`.
|
||||||
|
// This constant tells the difference between bridge balance at block `M - requiredBlockConfirmation() + 1`
|
||||||
|
// and the actual value monitor is interested in.
|
||||||
|
const lateHomeConfirmationsTotalValue = BN.sum(
|
||||||
|
0,
|
||||||
|
...foreignToHomeConfirmations.filter(e => e.blockNumber > homeDelayedBlockNumber).map(e => e.value)
|
||||||
|
)
|
||||||
|
|
||||||
if (bridgeMode === BRIDGE_MODES.ERC_TO_ERC) {
|
if (bridgeMode === BRIDGE_MODES.ERC_TO_ERC) {
|
||||||
const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||||
const erc20Address = await foreignBridge.methods.erc20token().call()
|
const erc20Address = await foreignBridge.methods.erc20token().call()
|
||||||
const erc20Contract = new web3Foreign.eth.Contract(ERC20_ABI, erc20Address)
|
const erc20Contract = new web3Foreign.eth.Contract(ERC20_ABI, erc20Address)
|
||||||
logger.debug('calling erc20Contract.methods.balanceOf')
|
logger.debug('calling erc20Contract.methods.balanceOf')
|
||||||
const foreignErc20Balance = await erc20Contract.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
const foreignErc20Balance = await erc20Contract.methods
|
||||||
|
.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||||
|
.call({}, foreignDelayedBlockNumber)
|
||||||
const homeBridge = new web3Home.eth.Contract(HOME_ERC_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
const homeBridge = new web3Home.eth.Contract(HOME_ERC_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
||||||
logger.debug('calling homeBridge.methods.erc677token')
|
logger.debug('calling homeBridge.methods.erc677token')
|
||||||
const tokenAddress = await homeBridge.methods.erc677token().call()
|
const tokenAddress = await homeBridge.methods.erc677token().call()
|
||||||
const tokenContract = new web3Home.eth.Contract(ERC677_ABI, tokenAddress)
|
const tokenContract = new web3Home.eth.Contract(ERC677_ABI, tokenAddress)
|
||||||
logger.debug('calling tokenContract.methods.totalSupply()')
|
logger.debug('calling tokenContract.methods.totalSupply()')
|
||||||
const totalSupply = await tokenContract.methods.totalSupply().call()
|
const totalSupply = await tokenContract.methods.totalSupply().call({}, homeDelayedBlockNumber)
|
||||||
const foreignBalanceBN = new BN(foreignErc20Balance)
|
const foreignBalanceBN = new BN(foreignErc20Balance).plus(lateForeignConfirmationsTotalValue)
|
||||||
const foreignTotalSupplyBN = new BN(totalSupply)
|
const foreignTotalSupplyBN = new BN(totalSupply).plus(lateHomeConfirmationsTotalValue)
|
||||||
const diff = foreignBalanceBN.minus(foreignTotalSupplyBN).toString(10)
|
const diff = foreignBalanceBN.minus(foreignTotalSupplyBN).toString(10)
|
||||||
logger.debug('Done')
|
logger.debug('Done')
|
||||||
return {
|
return {
|
||||||
@ -61,12 +78,12 @@ async function main(bridgeMode) {
|
|||||||
logger.debug('calling web3Home.eth.getBalance')
|
logger.debug('calling web3Home.eth.getBalance')
|
||||||
const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_NATIVE_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_NATIVE_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||||
const erc20Address = await foreignBridge.methods.erc677token().call()
|
const erc20Address = await foreignBridge.methods.erc677token().call()
|
||||||
const homeBalance = await web3Home.eth.getBalance(COMMON_HOME_BRIDGE_ADDRESS)
|
const homeBalance = await web3Home.eth.getBalance(COMMON_HOME_BRIDGE_ADDRESS, homeDelayedBlockNumber)
|
||||||
const tokenContract = new web3Foreign.eth.Contract(ERC20_ABI, erc20Address)
|
const tokenContract = new web3Foreign.eth.Contract(ERC20_ABI, erc20Address)
|
||||||
logger.debug('calling tokenContract.methods.totalSupply()')
|
logger.debug('calling tokenContract.methods.totalSupply()')
|
||||||
const totalSupply = await tokenContract.methods.totalSupply().call()
|
const totalSupply = await tokenContract.methods.totalSupply().call({}, foreignDelayedBlockNumber)
|
||||||
const homeBalanceBN = new BN(homeBalance)
|
const homeBalanceBN = new BN(homeBalance).plus(lateHomeConfirmationsTotalValue)
|
||||||
const foreignTotalSupplyBN = new BN(totalSupply)
|
const foreignTotalSupplyBN = new BN(totalSupply).plus(lateForeignConfirmationsTotalValue)
|
||||||
const diff = homeBalanceBN.minus(foreignTotalSupplyBN).toString(10)
|
const diff = homeBalanceBN.minus(foreignTotalSupplyBN).toString(10)
|
||||||
logger.debug('Done')
|
logger.debug('Done')
|
||||||
return {
|
return {
|
||||||
@ -103,21 +120,25 @@ async function main(bridgeMode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.debug('calling erc20Contract.methods.balanceOf')
|
logger.debug('calling erc20Contract.methods.balanceOf')
|
||||||
const foreignErc20Balance = await erc20Contract.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
const foreignErc20Balance = await erc20Contract.methods
|
||||||
|
.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||||
|
.call({}, foreignDelayedBlockNumber)
|
||||||
|
|
||||||
const homeBridge = new web3Home.eth.Contract(HOME_ERC_TO_NATIVE_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
const homeBridge = new web3Home.eth.Contract(HOME_ERC_TO_NATIVE_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
||||||
logger.debug('calling homeBridge.methods.blockRewardContract')
|
logger.debug('calling homeBridge.methods.blockRewardContract')
|
||||||
const blockRewardAddress = await homeBridge.methods.blockRewardContract().call()
|
const blockRewardAddress = await homeBridge.methods.blockRewardContract().call()
|
||||||
const blockRewardContract = new web3Home.eth.Contract(BLOCK_REWARD_ABI, blockRewardAddress)
|
const blockRewardContract = new web3Home.eth.Contract(BLOCK_REWARD_ABI, blockRewardAddress)
|
||||||
|
const homeBlockNumber = await getHomeBlockNumber()
|
||||||
logger.debug('calling blockReward.methods.mintedTotally')
|
logger.debug('calling blockReward.methods.mintedTotally')
|
||||||
const mintedCoins = await blockRewardContract.methods.mintedTotallyByBridge(COMMON_HOME_BRIDGE_ADDRESS).call()
|
const mintedCoins = await blockRewardContract.methods
|
||||||
|
.mintedTotallyByBridge(COMMON_HOME_BRIDGE_ADDRESS)
|
||||||
|
.call({}, homeBlockNumber)
|
||||||
logger.debug('calling homeBridge.methods.totalBurntCoins')
|
logger.debug('calling homeBridge.methods.totalBurntCoins')
|
||||||
const burntCoins = await homeBridge.methods.totalBurntCoins().call()
|
const burntCoins = await homeBridge.methods.totalBurntCoins().call({}, homeDelayedBlockNumber)
|
||||||
|
|
||||||
const mintedCoinsBN = new BN(mintedCoins)
|
const mintedCoinsBN = new BN(mintedCoins)
|
||||||
const burntCoinsBN = new BN(burntCoins)
|
const burntCoinsBN = new BN(burntCoins)
|
||||||
const totalSupplyBN = mintedCoinsBN.minus(burntCoinsBN)
|
const totalSupplyBN = mintedCoinsBN.minus(burntCoinsBN)
|
||||||
const foreignErc20BalanceBN = new BN(foreignErc20Balance)
|
const foreignErc20BalanceBN = new BN(foreignErc20Balance).plus(lateForeignConfirmationsTotalValue)
|
||||||
const investedAmountInDaiBN = new BN(investedAmountInDai)
|
const investedAmountInDaiBN = new BN(investedAmountInDai)
|
||||||
const bridgeDsrBalanceBN = new BN(bridgeDsrBalance)
|
const bridgeDsrBalanceBN = new BN(bridgeDsrBalance)
|
||||||
|
|
||||||
|
@ -1,18 +1,36 @@
|
|||||||
require('dotenv').config()
|
require('dotenv').config()
|
||||||
const eventsInfo = require('./utils/events')
|
const BN = require('bignumber.js')
|
||||||
|
const Web3Utils = require('web3').utils
|
||||||
|
const {
|
||||||
|
eventWithoutReference,
|
||||||
|
deliveredMsgNotProcessed,
|
||||||
|
unclaimedHomeToForeignRequests,
|
||||||
|
manuallyProcessedAMBHomeToForeignRequests
|
||||||
|
} = require('./utils/message')
|
||||||
const { BRIDGE_MODES } = require('../commons')
|
const { BRIDGE_MODES } = require('../commons')
|
||||||
|
const { getHomeTxSender } = require('./utils/web3Cache')
|
||||||
|
|
||||||
async function main(bridgeMode) {
|
const {
|
||||||
|
MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST,
|
||||||
|
MONITOR_HOME_TO_FOREIGN_BLOCK_LIST,
|
||||||
|
MONITOR_HOME_TO_FOREIGN_CHECK_SENDER
|
||||||
|
} = process.env
|
||||||
|
|
||||||
|
async function main(bridgeMode, eventsInfo) {
|
||||||
const {
|
const {
|
||||||
homeToForeignConfirmations,
|
homeToForeignConfirmations,
|
||||||
homeToForeignRequests,
|
homeToForeignRequests,
|
||||||
foreignToHomeConfirmations,
|
foreignToHomeConfirmations,
|
||||||
foreignToHomeRequests
|
foreignToHomeRequests
|
||||||
} = await eventsInfo(bridgeMode)
|
} = eventsInfo
|
||||||
|
|
||||||
if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) {
|
if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) {
|
||||||
|
const onlyInHomeRequests = homeToForeignRequests.filter(deliveredMsgNotProcessed(homeToForeignConfirmations))
|
||||||
|
const manuallyProcessedRequests = onlyInHomeRequests.filter(manuallyProcessedAMBHomeToForeignRequests())
|
||||||
return {
|
return {
|
||||||
fromHomeToForeignDiff: homeToForeignRequests.length - homeToForeignConfirmations.length,
|
fromHomeToForeignDiff:
|
||||||
|
homeToForeignRequests.length - homeToForeignConfirmations.length - manuallyProcessedRequests.length,
|
||||||
|
fromHomeToForeignPBUDiff: manuallyProcessedRequests.length,
|
||||||
fromForeignToHomeDiff: foreignToHomeConfirmations.length - foreignToHomeRequests.length,
|
fromForeignToHomeDiff: foreignToHomeConfirmations.length - foreignToHomeRequests.length,
|
||||||
home: {
|
home: {
|
||||||
toForeign: homeToForeignRequests.length,
|
toForeign: homeToForeignRequests.length,
|
||||||
@ -24,9 +42,26 @@ async function main(bridgeMode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return {
|
const stats = {
|
||||||
depositsDiff: homeToForeignRequests.length - homeToForeignConfirmations.length,
|
depositsDiff: homeToForeignRequests.length - homeToForeignConfirmations.length,
|
||||||
withdrawalDiff: foreignToHomeConfirmations.length - foreignToHomeRequests.length,
|
withdrawalDiff: foreignToHomeConfirmations.length - foreignToHomeRequests.length
|
||||||
|
}
|
||||||
|
if (MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST || MONITOR_HOME_TO_FOREIGN_BLOCK_LIST) {
|
||||||
|
const onlyInHomeDeposits = homeToForeignRequests.filter(eventWithoutReference(homeToForeignConfirmations))
|
||||||
|
if (MONITOR_HOME_TO_FOREIGN_CHECK_SENDER === 'true') {
|
||||||
|
for (let i = 0; i < onlyInHomeDeposits.length; i++) {
|
||||||
|
onlyInHomeDeposits[i].sender = await getHomeTxSender(onlyInHomeDeposits[i].transactionHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const unclaimedPool = onlyInHomeDeposits.filter(unclaimedHomeToForeignRequests())
|
||||||
|
|
||||||
|
stats.depositsDiff -= unclaimedPool.length
|
||||||
|
stats.unclaimedDiff = unclaimedPool.length
|
||||||
|
stats.unclaimedBalance = Web3Utils.fromWei(BN.sum(0, ...unclaimedPool.map(e => e.value)).toFixed())
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...stats,
|
||||||
home: {
|
home: {
|
||||||
deposits: homeToForeignRequests.length,
|
deposits: homeToForeignRequests.length,
|
||||||
withdrawals: foreignToHomeConfirmations.length
|
withdrawals: foreignToHomeConfirmations.length
|
||||||
|
@ -14,12 +14,12 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bignumber.js": "^6.0.0",
|
"bignumber.js": "^9.0.1",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^5.0.1",
|
"dotenv": "^5.0.1",
|
||||||
"express": "^4.16.3",
|
"express": "^4.16.3",
|
||||||
"node-fetch": "^2.1.2",
|
"node-fetch": "^2.1.2",
|
||||||
"web3": "1.0.0-beta.34"
|
"web3": "^1.3.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10.18"
|
"node": ">= 10.18"
|
||||||
|
@ -2,17 +2,21 @@
|
|||||||
|
|
||||||
CONFIGDIR="configs"
|
CONFIGDIR="configs"
|
||||||
RESPONSESDIR="responses"
|
RESPONSESDIR="responses"
|
||||||
|
ACLDIR="access-lists"
|
||||||
|
ALLOWANCEFILE="allowance_list.txt"
|
||||||
|
BLOCKFILE="block_list.txt"
|
||||||
|
CACHEDIR="cache"
|
||||||
IMAGETAG="latest"
|
IMAGETAG="latest"
|
||||||
|
|
||||||
cd $(dirname $0)/..
|
cd $(dirname $0)/..
|
||||||
|
|
||||||
if /usr/local/bin/docker-compose ps | grep -q -i 'monitor'; then
|
if /usr/local/bin/docker-compose ps | grep -q -i 'monitor'; then
|
||||||
tstart=`date +"%s"`
|
tstart=`date +"%s"`
|
||||||
|
|
||||||
for file in ${CONFIGDIR}/*.env
|
for file in ${CONFIGDIR}/*.env
|
||||||
do
|
do
|
||||||
echo "${file} handling..."
|
echo "${file} handling..."
|
||||||
|
|
||||||
bridgename=`source ${file} && echo ${MONITOR_BRIDGE_NAME}`
|
bridgename=`source ${file} && echo ${MONITOR_BRIDGE_NAME}`
|
||||||
reportdir=${RESPONSESDIR}"/"${bridgename}
|
reportdir=${RESPONSESDIR}"/"${bridgename}
|
||||||
if [ ! -d ${reportdir} ]; then
|
if [ ! -d ${reportdir} ]; then
|
||||||
@ -26,10 +30,18 @@ if /usr/local/bin/docker-compose ps | grep -q -i 'monitor'; then
|
|||||||
fi
|
fi
|
||||||
done
|
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"
|
containername=${bridgename}"-checker"
|
||||||
docker container stats --no-stream ${containername} 2>/dev/null 1>&2
|
docker container stats --no-stream ${containername} 2>/dev/null 1>&2
|
||||||
if [ ! "$?" == "0" ]; then
|
if [ ! "$?" == "0" ]; then
|
||||||
|
mkdir -p "$(pwd)/$CACHEDIR/$bridgename"
|
||||||
docker run --rm --env-file $file -v $(pwd)/${RESPONSESDIR}:/mono/monitor/responses \
|
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} \
|
--name ${containername} poanetwork/tokenbridge-monitor:${IMAGETAG} \
|
||||||
/bin/bash -c 'yarn check-all'
|
/bin/bash -c 'yarn check-all'
|
||||||
shasum -a 256 -s -c ${checksumfile}
|
shasum -a 256 -s -c ${checksumfile}
|
||||||
@ -46,15 +58,15 @@ if /usr/local/bin/docker-compose ps | grep -q -i 'monitor'; then
|
|||||||
else
|
else
|
||||||
echo "${containername} have not finished yet" >&2
|
echo "${containername} have not finished yet" >&2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm ${checksumfile}
|
rm ${checksumfile}
|
||||||
echo "========================================"
|
echo "========================================"
|
||||||
done
|
done
|
||||||
|
|
||||||
tend=`date +"%s"`
|
tend=`date +"%s"`
|
||||||
tdiff=`expr ${tend} - ${tstart}`
|
tdiff=`expr ${tend} - ${tstart}`
|
||||||
echo "Total time to run: ${tdiff}"
|
echo "Total time to run: ${tdiff}"
|
||||||
|
|
||||||
else
|
else
|
||||||
echo "Monitor is not running, skipping checks."
|
echo "Monitor is not running, skipping checks."
|
||||||
fi
|
fi
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
require('dotenv').config()
|
require('dotenv').config()
|
||||||
const Web3 = require('web3')
|
|
||||||
const logger = require('./logger')('stuckTransfers.js')
|
const logger = require('./logger')('stuckTransfers.js')
|
||||||
const { FOREIGN_V1_ABI } = require('../commons/abis')
|
const { FOREIGN_V1_ABI } = require('../commons/abis')
|
||||||
|
const { web3Foreign, getForeignBlockNumber } = require('./utils/web3')
|
||||||
|
const { getPastEvents } = require('./utils/web3Cache')
|
||||||
|
|
||||||
const { COMMON_FOREIGN_RPC_URL, COMMON_FOREIGN_BRIDGE_ADDRESS } = process.env
|
const { COMMON_FOREIGN_BRIDGE_ADDRESS } = process.env
|
||||||
const MONITOR_FOREIGN_START_BLOCK = Number(process.env.MONITOR_FOREIGN_START_BLOCK) || 0
|
const 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 = [
|
const ABITransferWithoutData = [
|
||||||
{
|
{
|
||||||
anonymous: false,
|
anonymous: false,
|
||||||
@ -64,38 +62,39 @@ const ABIWithData = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
function compareTransfers(transfersNormal) {
|
function transferWithoutCallback(transfersNormal) {
|
||||||
return withData => {
|
const txHashes = new Set()
|
||||||
return (
|
transfersNormal.forEach(transfer => txHashes.add(transfer.transactionHash))
|
||||||
transfersNormal.filter(normal => {
|
return withData => !txHashes.has(withData.transactionHash)
|
||||||
return normal.transactionHash === withData.transactionHash
|
|
||||||
}).length === 0
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_V1_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
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 erc20Address = await foreignBridge.methods.erc677token().call()
|
||||||
const tokenContract = new web3Foreign.eth.Contract(ABITransferWithoutData, erc20Address)
|
const tokenContract = new web3Foreign.eth.Contract(ABITransferWithoutData, erc20Address)
|
||||||
const tokenContractWithData = new web3Foreign.eth.Contract(ABIWithData, 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')
|
logger.debug('calling tokenContract.getPastEvents Transfer')
|
||||||
const transfersNormal = await tokenContract.getPastEvents('Transfer', {
|
const options = {
|
||||||
filter: {
|
event: 'Transfer',
|
||||||
to: COMMON_FOREIGN_BRIDGE_ADDRESS
|
options: {
|
||||||
|
filter: {
|
||||||
|
to: COMMON_FOREIGN_BRIDGE_ADDRESS
|
||||||
|
}
|
||||||
},
|
},
|
||||||
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
||||||
toBlock: 'latest'
|
toBlock: foreignBlockNumber,
|
||||||
})
|
chain: 'foreign',
|
||||||
|
safeToBlock: foreignDelayedBlockNumber
|
||||||
|
}
|
||||||
|
const transfersNormal = await getPastEvents(tokenContract, options)
|
||||||
logger.debug('calling tokenContractWithData.getPastEvents Transfer')
|
logger.debug('calling tokenContractWithData.getPastEvents Transfer')
|
||||||
const transfersWithData = await tokenContractWithData.getPastEvents('Transfer', {
|
const transfersWithData = await getPastEvents(tokenContractWithData, options)
|
||||||
filter: {
|
const stuckTransfers = transfersNormal.filter(transferWithoutCallback(transfersWithData))
|
||||||
to: COMMON_FOREIGN_BRIDGE_ADDRESS
|
|
||||||
},
|
|
||||||
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
|
||||||
toBlock: 'latest'
|
|
||||||
})
|
|
||||||
const stuckTransfers = transfersNormal.filter(compareTransfers(transfersWithData))
|
|
||||||
logger.debug('Done')
|
logger.debug('Done')
|
||||||
return {
|
return {
|
||||||
stuckTransfers,
|
stuckTransfers,
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
const { toBN } = require('web3').utils
|
|
||||||
|
|
||||||
const getBlockNumberCall = web3 => web3.eth.getBlockNumber()
|
|
||||||
|
|
||||||
async function getBlockNumber(web3Home, web3Foreign) {
|
|
||||||
return (await Promise.all([web3Home, web3Foreign].map(getBlockNumberCall))).map(toBN)
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getBlockNumber
|
|
||||||
}
|
|
@ -1,6 +1,4 @@
|
|||||||
require('dotenv').config()
|
require('dotenv').config()
|
||||||
const Web3 = require('web3')
|
|
||||||
const { toBN } = require('web3').utils
|
|
||||||
const logger = require('../logger')('eventsUtils')
|
const logger = require('../logger')('eventsUtils')
|
||||||
const {
|
const {
|
||||||
BRIDGE_MODES,
|
BRIDGE_MODES,
|
||||||
@ -11,7 +9,6 @@ const {
|
|||||||
ERC20_ABI,
|
ERC20_ABI,
|
||||||
ERC677_BRIDGE_TOKEN_ABI,
|
ERC677_BRIDGE_TOKEN_ABI,
|
||||||
getTokenType,
|
getTokenType,
|
||||||
getPastEvents,
|
|
||||||
ZERO_ADDRESS,
|
ZERO_ADDRESS,
|
||||||
OLD_AMB_USER_REQUEST_FOR_SIGNATURE_ABI,
|
OLD_AMB_USER_REQUEST_FOR_SIGNATURE_ABI,
|
||||||
OLD_AMB_USER_REQUEST_FOR_AFFIRMATION_ABI
|
OLD_AMB_USER_REQUEST_FOR_AFFIRMATION_ABI
|
||||||
@ -19,24 +16,12 @@ const {
|
|||||||
const { normalizeEventInformation } = require('./message')
|
const { normalizeEventInformation } = require('./message')
|
||||||
const { filterTransferBeforeES } = require('./tokenUtils')
|
const { filterTransferBeforeES } = require('./tokenUtils')
|
||||||
const { writeFile, readCacheFile } = require('./file')
|
const { writeFile, readCacheFile } = require('./file')
|
||||||
|
const { web3Home, web3Foreign, getHomeBlockNumber, getForeignBlockNumber } = require('./web3')
|
||||||
|
const { getPastEvents } = require('./web3Cache')
|
||||||
|
|
||||||
const {
|
const { COMMON_HOME_BRIDGE_ADDRESS, COMMON_FOREIGN_BRIDGE_ADDRESS, MONITOR_CACHE_EVENTS } = process.env
|
||||||
COMMON_HOME_RPC_URL,
|
const MONITOR_HOME_START_BLOCK = Number(process.env.MONITOR_HOME_START_BLOCK) || 0
|
||||||
COMMON_FOREIGN_RPC_URL,
|
const MONITOR_FOREIGN_START_BLOCK = Number(process.env.MONITOR_FOREIGN_START_BLOCK) || 0
|
||||||
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'
|
const cacheFilePath = '/tmp/cachedEvents.json'
|
||||||
async function main(mode) {
|
async function main(mode) {
|
||||||
@ -73,11 +58,12 @@ async function main(mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.debug('getting last block numbers')
|
logger.debug('getting last block numbers')
|
||||||
const [homeBlockNumber, foreignBlockNumber] = await getBlockNumber(web3Home, web3Foreign)
|
const homeBlockNumber = await getHomeBlockNumber()
|
||||||
const homeConfirmations = toBN(await homeBridge.methods.requiredBlockConfirmations().call())
|
const foreignBlockNumber = await getForeignBlockNumber()
|
||||||
const foreignConfirmations = toBN(await foreignBridge.methods.requiredBlockConfirmations().call())
|
const homeConfirmations = await homeBridge.methods.requiredBlockConfirmations().call()
|
||||||
const homeDelayedBlockNumber = homeBlockNumber.sub(homeConfirmations)
|
const foreignConfirmations = await foreignBridge.methods.requiredBlockConfirmations().call()
|
||||||
const foreignDelayedBlockNumber = foreignBlockNumber.sub(foreignConfirmations)
|
const homeDelayedBlockNumber = homeBlockNumber - homeConfirmations
|
||||||
|
const foreignDelayedBlockNumber = foreignBlockNumber - foreignConfirmations
|
||||||
|
|
||||||
let homeToForeignRequests = []
|
let homeToForeignRequests = []
|
||||||
let foreignToHomeRequests = []
|
let foreignToHomeRequests = []
|
||||||
@ -95,22 +81,24 @@ async function main(mode) {
|
|||||||
homeToForeignRequests = (await getPastEvents(oldHomeBridge, {
|
homeToForeignRequests = (await getPastEvents(oldHomeBridge, {
|
||||||
event: 'UserRequestForSignature',
|
event: 'UserRequestForSignature',
|
||||||
fromBlock: MONITOR_HOME_START_BLOCK,
|
fromBlock: MONITOR_HOME_START_BLOCK,
|
||||||
toBlock: homeDelayedBlockNumber
|
toBlock: homeDelayedBlockNumber,
|
||||||
|
chain: 'home'
|
||||||
})).map(normalizeEvent)
|
})).map(normalizeEvent)
|
||||||
logger.debug(`found ${homeToForeignRequests.length} events`)
|
logger.debug(`found ${homeToForeignRequests.length} events`)
|
||||||
if (homeToForeignRequests.length > 0) {
|
if (homeToForeignRequests.length > 0) {
|
||||||
homeMigrationBlock = toBN(Math.max(...homeToForeignRequests.map(x => x.blockNumber)))
|
homeMigrationBlock = Math.max(...homeToForeignRequests.map(x => x.blockNumber))
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug("calling oldForeignBridge.getPastEvents('UserRequestForAffirmation(bytes)')")
|
logger.debug("calling oldForeignBridge.getPastEvents('UserRequestForAffirmation(bytes)')")
|
||||||
foreignToHomeRequests = (await getPastEvents(oldForeignBridge, {
|
foreignToHomeRequests = (await getPastEvents(oldForeignBridge, {
|
||||||
event: 'UserRequestForAffirmation',
|
event: 'UserRequestForAffirmation',
|
||||||
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
||||||
toBlock: foreignDelayedBlockNumber
|
toBlock: foreignDelayedBlockNumber,
|
||||||
|
chain: 'foreign'
|
||||||
})).map(normalizeEvent)
|
})).map(normalizeEvent)
|
||||||
logger.debug(`found ${foreignToHomeRequests.length} events`)
|
logger.debug(`found ${foreignToHomeRequests.length} events`)
|
||||||
if (foreignToHomeRequests.length > 0) {
|
if (foreignToHomeRequests.length > 0) {
|
||||||
foreignMigrationBlock = toBN(Math.max(...foreignToHomeRequests.map(x => x.blockNumber)))
|
foreignMigrationBlock = Math.max(...foreignToHomeRequests.map(x => x.blockNumber))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +106,8 @@ async function main(mode) {
|
|||||||
const homeToForeignRequestsNew = (await getPastEvents(homeBridge, {
|
const homeToForeignRequestsNew = (await getPastEvents(homeBridge, {
|
||||||
event: v1Bridge ? 'Deposit' : 'UserRequestForSignature',
|
event: v1Bridge ? 'Deposit' : 'UserRequestForSignature',
|
||||||
fromBlock: homeMigrationBlock,
|
fromBlock: homeMigrationBlock,
|
||||||
toBlock: homeDelayedBlockNumber
|
toBlock: homeDelayedBlockNumber,
|
||||||
|
chain: 'home'
|
||||||
})).map(normalizeEvent)
|
})).map(normalizeEvent)
|
||||||
homeToForeignRequests = [...homeToForeignRequests, ...homeToForeignRequestsNew]
|
homeToForeignRequests = [...homeToForeignRequests, ...homeToForeignRequestsNew]
|
||||||
|
|
||||||
@ -126,21 +115,26 @@ async function main(mode) {
|
|||||||
const homeToForeignConfirmations = (await getPastEvents(foreignBridge, {
|
const homeToForeignConfirmations = (await getPastEvents(foreignBridge, {
|
||||||
event: v1Bridge ? 'Deposit' : 'RelayedMessage',
|
event: v1Bridge ? 'Deposit' : 'RelayedMessage',
|
||||||
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
||||||
toBlock: foreignBlockNumber
|
toBlock: foreignBlockNumber,
|
||||||
|
chain: 'foreign',
|
||||||
|
safeToBlock: foreignDelayedBlockNumber
|
||||||
})).map(normalizeEvent)
|
})).map(normalizeEvent)
|
||||||
|
|
||||||
logger.debug("calling homeBridge.getPastEvents('AffirmationCompleted')")
|
logger.debug("calling homeBridge.getPastEvents('AffirmationCompleted')")
|
||||||
const foreignToHomeConfirmations = (await getPastEvents(homeBridge, {
|
const foreignToHomeConfirmations = (await getPastEvents(homeBridge, {
|
||||||
event: v1Bridge ? 'Withdraw' : 'AffirmationCompleted',
|
event: v1Bridge ? 'Withdraw' : 'AffirmationCompleted',
|
||||||
fromBlock: MONITOR_HOME_START_BLOCK,
|
fromBlock: MONITOR_HOME_START_BLOCK,
|
||||||
toBlock: homeBlockNumber
|
toBlock: homeBlockNumber,
|
||||||
|
chain: 'home',
|
||||||
|
safeToBlock: homeDelayedBlockNumber
|
||||||
})).map(normalizeEvent)
|
})).map(normalizeEvent)
|
||||||
|
|
||||||
logger.debug("calling foreignBridge.getPastEvents('UserRequestForAffirmation')")
|
logger.debug("calling foreignBridge.getPastEvents('UserRequestForAffirmation')")
|
||||||
const foreignToHomeRequestsNew = (await getPastEvents(foreignBridge, {
|
const foreignToHomeRequestsNew = (await getPastEvents(foreignBridge, {
|
||||||
event: v1Bridge ? 'Withdraw' : 'UserRequestForAffirmation',
|
event: v1Bridge ? 'Withdraw' : 'UserRequestForAffirmation',
|
||||||
fromBlock: foreignMigrationBlock,
|
fromBlock: foreignMigrationBlock,
|
||||||
toBlock: foreignDelayedBlockNumber
|
toBlock: foreignDelayedBlockNumber,
|
||||||
|
chain: 'foreign'
|
||||||
})).map(normalizeEvent)
|
})).map(normalizeEvent)
|
||||||
foreignToHomeRequests = [...foreignToHomeRequests, ...foreignToHomeRequestsNew]
|
foreignToHomeRequests = [...foreignToHomeRequests, ...foreignToHomeRequestsNew]
|
||||||
|
|
||||||
@ -152,7 +146,8 @@ async function main(mode) {
|
|||||||
toBlock: foreignDelayedBlockNumber,
|
toBlock: foreignDelayedBlockNumber,
|
||||||
options: {
|
options: {
|
||||||
filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS }
|
filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS }
|
||||||
}
|
},
|
||||||
|
chain: 'foreign'
|
||||||
})).map(normalizeEvent)
|
})).map(normalizeEvent)
|
||||||
|
|
||||||
let directTransfers = transferEvents
|
let directTransfers = transferEvents
|
||||||
@ -163,7 +158,9 @@ async function main(mode) {
|
|||||||
const tokensSwappedEvents = await getPastEvents(foreignBridge, {
|
const tokensSwappedEvents = await getPastEvents(foreignBridge, {
|
||||||
event: 'TokensSwapped',
|
event: 'TokensSwapped',
|
||||||
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
||||||
toBlock: foreignBlockNumber
|
toBlock: foreignBlockNumber,
|
||||||
|
chain: 'foreign',
|
||||||
|
safeToBlock: foreignDelayedBlockNumber
|
||||||
})
|
})
|
||||||
|
|
||||||
// Get token swap events emitted by foreign bridge
|
// Get token swap events emitted by foreign bridge
|
||||||
@ -202,7 +199,8 @@ async function main(mode) {
|
|||||||
toBlock: foreignDelayedBlockNumber,
|
toBlock: foreignDelayedBlockNumber,
|
||||||
options: {
|
options: {
|
||||||
filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS }
|
filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS }
|
||||||
}
|
},
|
||||||
|
chain: 'foreign'
|
||||||
})).map(normalizeEvent)
|
})).map(normalizeEvent)
|
||||||
|
|
||||||
// Remove events after the ES
|
// Remove events after the ES
|
||||||
@ -237,7 +235,9 @@ async function main(mode) {
|
|||||||
foreignToHomeConfirmations,
|
foreignToHomeConfirmations,
|
||||||
foreignToHomeRequests,
|
foreignToHomeRequests,
|
||||||
isExternalErc20,
|
isExternalErc20,
|
||||||
bridgeMode
|
bridgeMode,
|
||||||
|
homeDelayedBlockNumber,
|
||||||
|
foreignDelayedBlockNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MONITOR_CACHE_EVENTS === 'true') {
|
if (MONITOR_CACHE_EVENTS === 'true') {
|
||||||
|
@ -38,9 +38,25 @@ function readCacheFile(filePath) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function writeCacheFile(filePath, object) {
|
||||||
|
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
||||||
|
fs.writeFileSync(filePath, JSON.stringify(object))
|
||||||
|
}
|
||||||
|
|
||||||
|
function readAccessListFile(filePath) {
|
||||||
|
const data = fs.readFileSync(filePath)
|
||||||
|
return data
|
||||||
|
.toString()
|
||||||
|
.split('\n')
|
||||||
|
.map(addr => addr.trim().toLowerCase())
|
||||||
|
.filter(addr => addr.length === 42)
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
readFile,
|
readFile,
|
||||||
writeFile,
|
writeFile,
|
||||||
createDir,
|
createDir,
|
||||||
readCacheFile
|
readCacheFile,
|
||||||
|
writeCacheFile,
|
||||||
|
readAccessListFile
|
||||||
}
|
}
|
||||||
|
93
monitor/utils/getValidatorsList.js
Normal file
93
monitor/utils/getValidatorsList.js
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
const { REWARDABLE_VALIDATORS_ABI, processValidatorsEvents } = require('../../commons')
|
||||||
|
const { getPastEvents } = require('./web3Cache')
|
||||||
|
|
||||||
|
const VALIDATORS_INDEXED_EVENTS_ABI = [
|
||||||
|
{
|
||||||
|
anonymous: false,
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
name: 'validator',
|
||||||
|
type: 'address'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: 'ValidatorRemoved',
|
||||||
|
type: 'event'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
anonymous: false,
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
name: 'validator',
|
||||||
|
type: 'address'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: 'ValidatorAdded',
|
||||||
|
type: 'event'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
anonymous: false,
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
name: 'validator',
|
||||||
|
type: 'address'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
name: 'reward',
|
||||||
|
type: 'address'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: 'ValidatorAdded',
|
||||||
|
type: 'event'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const tryCall = async (method, fallbackValue) => {
|
||||||
|
try {
|
||||||
|
return await method.call()
|
||||||
|
} catch (e) {
|
||||||
|
return fallbackValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getValidatorList = async (address, eth, options) => {
|
||||||
|
const { logger } = options
|
||||||
|
logger.debug('getting validatorList')
|
||||||
|
|
||||||
|
const validatorsContract = new eth.Contract(REWARDABLE_VALIDATORS_ABI, address) // in monitor, BRIDGE_VALIDATORS_ABI was used
|
||||||
|
const validators = await tryCall(validatorsContract.methods.validatorList(), [])
|
||||||
|
|
||||||
|
if (validators.length) {
|
||||||
|
return validators
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug('getting validatorsEvents')
|
||||||
|
|
||||||
|
options.fromBlock = Number(await tryCall(validatorsContract.methods.deployedAtBlock(), 0))
|
||||||
|
|
||||||
|
const contract = new eth.Contract(VALIDATORS_INDEXED_EVENTS_ABI, address)
|
||||||
|
|
||||||
|
const validatorsEvents = [
|
||||||
|
...(await getPastEvents(contract, {
|
||||||
|
event: 'ValidatorAdded(address)',
|
||||||
|
...options
|
||||||
|
})),
|
||||||
|
...(await getPastEvents(contract, {
|
||||||
|
event: 'ValidatorAdded(address,address)',
|
||||||
|
...options
|
||||||
|
})),
|
||||||
|
...(await getPastEvents(contract, {
|
||||||
|
event: 'ValidatorRemoved(address)',
|
||||||
|
...options
|
||||||
|
}))
|
||||||
|
].sort((a, b) => a.blockNumber - b.blockNumber || a.transactionIndex - b.transactionIndex)
|
||||||
|
|
||||||
|
return processValidatorsEvents(validatorsEvents)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getValidatorList
|
||||||
|
}
|
@ -1,44 +1,30 @@
|
|||||||
const web3Utils = require('web3').utils
|
|
||||||
const { parseAMBMessage } = require('../../commons')
|
const { 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) {
|
function deliveredMsgNotProcessed(processedList) {
|
||||||
return deliveredMsg => {
|
const keys = new Set()
|
||||||
let msgData = deliveredMsg.returnValues.encodedData
|
processedList.forEach(processedMsg => keys.add(keyAMB(processedMsg.returnValues)))
|
||||||
if (!deliveredMsg.returnValues.messageId) {
|
return deliveredMsg => !keys.has(keyAMB(normalizeAMBMessage(deliveredMsg)))
|
||||||
// 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) {
|
function processedMsgNotDelivered(deliveredList) {
|
||||||
return processedMsg => {
|
const keys = new Set()
|
||||||
return (
|
deliveredList.forEach(deliveredMsg => keys.add(keyAMB(normalizeAMBMessage(deliveredMsg))))
|
||||||
deliveredList.filter(deliveredMsg => {
|
return processedMsg => !keys.has(keyAMB(processedMsg.returnValues))
|
||||||
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
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,13 +46,49 @@ const normalizeEventInformation = event => ({
|
|||||||
value: event.returnValues.value
|
value: event.returnValues.value
|
||||||
})
|
})
|
||||||
|
|
||||||
const eventWithoutReference = otherSideEvents => e =>
|
const key = e => [e.referenceTx, e.recipient, e.value].join(',').toLowerCase()
|
||||||
otherSideEvents.filter(a => a.referenceTx === e.referenceTx && a.recipient === e.recipient && a.value === e.value)
|
|
||||||
.length === 0
|
const eventWithoutReference = otherSideEvents => {
|
||||||
|
const keys = new Set()
|
||||||
|
otherSideEvents.forEach(e => keys.add(key(e)))
|
||||||
|
return e => !keys.has(key(e))
|
||||||
|
}
|
||||||
|
|
||||||
|
const unclaimedHomeToForeignRequests = () => {
|
||||||
|
if (MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST) {
|
||||||
|
const allowanceList = readAccessListFile(MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST)
|
||||||
|
return e => !allowanceList.includes(e.recipient.toLowerCase()) && !(e.sender && allowanceList.includes(e.sender))
|
||||||
|
} else if (MONITOR_HOME_TO_FOREIGN_BLOCK_LIST) {
|
||||||
|
const blockList = readAccessListFile(MONITOR_HOME_TO_FOREIGN_BLOCK_LIST)
|
||||||
|
return e => blockList.includes(e.recipient.toLowerCase()) || (e.sender && blockList.includes(e.sender))
|
||||||
|
} else {
|
||||||
|
return () => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const manuallyProcessedAMBHomeToForeignRequests = () => {
|
||||||
|
if (MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST) {
|
||||||
|
const allowanceList = readAccessListFile(MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST)
|
||||||
|
return e => {
|
||||||
|
const { sender, executor, decodedDataType } = normalizeAMBMessage(e)
|
||||||
|
return (!allowanceList.includes(sender) && !allowanceList.includes(executor)) || decodedDataType.manualLane
|
||||||
|
}
|
||||||
|
} else if (MONITOR_HOME_TO_FOREIGN_BLOCK_LIST) {
|
||||||
|
const blockList = readAccessListFile(MONITOR_HOME_TO_FOREIGN_BLOCK_LIST)
|
||||||
|
return e => {
|
||||||
|
const { sender, executor, decodedDataType } = normalizeAMBMessage(e)
|
||||||
|
return blockList.includes(sender) || blockList.includes(executor) || decodedDataType.manualLane
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return e => normalizeAMBMessage(e).decodedDataType.manualLane
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
deliveredMsgNotProcessed,
|
deliveredMsgNotProcessed,
|
||||||
processedMsgNotDelivered,
|
processedMsgNotDelivered,
|
||||||
normalizeEventInformation,
|
normalizeEventInformation,
|
||||||
eventWithoutReference
|
eventWithoutReference,
|
||||||
|
unclaimedHomeToForeignRequests,
|
||||||
|
manuallyProcessedAMBHomeToForeignRequests
|
||||||
}
|
}
|
||||||
|
27
monitor/utils/web3.js
Normal file
27
monitor/utils/web3.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
require('dotenv').config()
|
||||||
|
const Web3 = require('web3')
|
||||||
|
|
||||||
|
const { COMMON_HOME_RPC_URL, COMMON_FOREIGN_RPC_URL } = process.env
|
||||||
|
|
||||||
|
const homeProvider = new Web3.providers.HttpProvider(COMMON_HOME_RPC_URL)
|
||||||
|
const web3Home = new Web3(homeProvider)
|
||||||
|
|
||||||
|
const foreignProvider = new Web3.providers.HttpProvider(COMMON_FOREIGN_RPC_URL)
|
||||||
|
const web3Foreign = new Web3(foreignProvider)
|
||||||
|
|
||||||
|
function blockNumberWrapper(web3) {
|
||||||
|
let blockNumber = null
|
||||||
|
return async () => {
|
||||||
|
if (!blockNumber) {
|
||||||
|
blockNumber = await web3.eth.getBlockNumber()
|
||||||
|
}
|
||||||
|
return blockNumber
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
web3Home,
|
||||||
|
web3Foreign,
|
||||||
|
getHomeBlockNumber: blockNumberWrapper(web3Home),
|
||||||
|
getForeignBlockNumber: blockNumberWrapper(web3Foreign)
|
||||||
|
}
|
133
monitor/utils/web3Cache.js
Normal file
133
monitor/utils/web3Cache.js
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
const logger = require('../logger')('web3Cache')
|
||||||
|
const { readCacheFile, writeCacheFile } = require('./file')
|
||||||
|
const { web3Home } = require('./web3')
|
||||||
|
const { getPastEvents: commonGetPastEvents } = require('../../commons')
|
||||||
|
|
||||||
|
const { MONITOR_BRIDGE_NAME, MONITOR_CACHE_EVENTS } = process.env
|
||||||
|
|
||||||
|
let isDirty = false
|
||||||
|
|
||||||
|
const homeTxSendersCacheFile = `./cache/${MONITOR_BRIDGE_NAME}/home/txSenders.json`
|
||||||
|
const cachedHomeTxSenders = readCacheFile(homeTxSendersCacheFile) || {}
|
||||||
|
|
||||||
|
async function getHomeTxSender(txHash) {
|
||||||
|
if (!cachedHomeTxSenders[txHash]) {
|
||||||
|
logger.debug(`Fetching sender for tx ${txHash}`)
|
||||||
|
cachedHomeTxSenders[txHash] = (await web3Home.eth.getTransaction(txHash)).from.toLowerCase()
|
||||||
|
isDirty = true
|
||||||
|
}
|
||||||
|
return cachedHomeTxSenders[txHash]
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getPastEvents(contract, options) {
|
||||||
|
if (MONITOR_CACHE_EVENTS !== 'true') {
|
||||||
|
return commonGetPastEvents(contract, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
const contractAddr = contract.options.address
|
||||||
|
|
||||||
|
let eventSignature
|
||||||
|
if (options.event.includes('(')) {
|
||||||
|
eventSignature = options.event
|
||||||
|
options.event = web3Home.utils.sha3(eventSignature)
|
||||||
|
const eventABI = contract.options.jsonInterface.find(e => e.type === 'event' && e.signature === options.event)
|
||||||
|
if (!eventABI) {
|
||||||
|
throw new Error(`Event ${eventSignature} not found`)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const eventABI = contract.options.jsonInterface.find(
|
||||||
|
e => e.type === 'event' && (e.name === options.event || e.signature === options.event)
|
||||||
|
)
|
||||||
|
if (!eventABI) {
|
||||||
|
throw new Error(`Event ${options.event} not found`)
|
||||||
|
}
|
||||||
|
eventSignature = `${eventABI.name}(${eventABI.inputs.map(i => i.type).join(',')})`
|
||||||
|
}
|
||||||
|
|
||||||
|
const cacheFile = `./cache/${MONITOR_BRIDGE_NAME}/${options.chain}/${contractAddr}/${eventSignature}.json`
|
||||||
|
|
||||||
|
const { fromBlock, toBlock } = options
|
||||||
|
const { fromBlock: cachedFromBlock, toBlock: cachedToBlock, events: cachedEvents } = readCacheFile(cacheFile) || {
|
||||||
|
fromBlock: 0,
|
||||||
|
toBlock: 0,
|
||||||
|
events: []
|
||||||
|
}
|
||||||
|
|
||||||
|
let result
|
||||||
|
if (cachedFromBlock > toBlock || fromBlock > cachedToBlock) {
|
||||||
|
// requested: A...B
|
||||||
|
// cached: C...D
|
||||||
|
// OR
|
||||||
|
// requested: A...B
|
||||||
|
// cached: C...D
|
||||||
|
logger.debug(`Fetching events for blocks ${fromBlock}...${toBlock}`)
|
||||||
|
result = await commonGetPastEvents(contract, options)
|
||||||
|
} else if (fromBlock < cachedFromBlock && toBlock <= cachedToBlock) {
|
||||||
|
// requested: A...B
|
||||||
|
// cached: C...D
|
||||||
|
logger.debug(`Cache hit for blocks ${cachedFromBlock}...${toBlock}`)
|
||||||
|
logger.debug(`Fetching events for blocks ${fromBlock}...${cachedFromBlock - 1}`)
|
||||||
|
result = [
|
||||||
|
...(await commonGetPastEvents(contract, { ...options, toBlock: cachedFromBlock - 1 })),
|
||||||
|
...cachedEvents.filter(e => e.blockNumber <= toBlock)
|
||||||
|
]
|
||||||
|
} else if (fromBlock < cachedFromBlock && cachedToBlock < toBlock) {
|
||||||
|
// requested: A.....B
|
||||||
|
// cached: C.D
|
||||||
|
logger.debug(`Cache hit for blocks ${cachedFromBlock}...${cachedToBlock}`)
|
||||||
|
logger.debug(`Fetching events for blocks ${fromBlock}...${cachedFromBlock - 1}`)
|
||||||
|
logger.debug(`Fetching events for blocks ${cachedToBlock + 1}...${toBlock}`)
|
||||||
|
result = [
|
||||||
|
...(await commonGetPastEvents(contract, { ...options, toBlock: cachedFromBlock - 1 })),
|
||||||
|
...cachedEvents,
|
||||||
|
...(await commonGetPastEvents(contract, { ...options, fromBlock: cachedToBlock + 1 }))
|
||||||
|
]
|
||||||
|
} else if (cachedFromBlock <= fromBlock && toBlock <= cachedToBlock) {
|
||||||
|
// requested: A.B
|
||||||
|
// cached: C.....D
|
||||||
|
logger.debug(`Cache hit for blocks ${fromBlock}...${toBlock}`)
|
||||||
|
result = cachedEvents.filter(e => fromBlock <= e.blockNumber && e.blockNumber <= toBlock)
|
||||||
|
} else if (fromBlock >= cachedFromBlock && toBlock > cachedToBlock) {
|
||||||
|
// requested: A...B
|
||||||
|
// cached: C...D
|
||||||
|
logger.debug(`Cache hit for blocks ${fromBlock}...${cachedToBlock}`)
|
||||||
|
logger.debug(`Fetching events for blocks ${cachedToBlock + 1}...${toBlock}`)
|
||||||
|
result = [
|
||||||
|
...cachedEvents.filter(e => e.blockNumber >= fromBlock),
|
||||||
|
...(await commonGetPastEvents(contract, { ...options, fromBlock: cachedToBlock + 1 }))
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
`Something is broken with cache resolution for getPastEvents,
|
||||||
|
requested blocks ${fromBlock}...${toBlock},
|
||||||
|
cached blocks ${cachedFromBlock}...${cachedToBlock}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// it is not safe to cache events with too low block confirmations
|
||||||
|
// so, only events from finalized blocks are included into the cache
|
||||||
|
const safeToBlock = options.safeToBlock || toBlock
|
||||||
|
const cacheToSave = result.filter(e => e.blockNumber <= safeToBlock)
|
||||||
|
logger.debug(
|
||||||
|
`Saving events cache for ${MONITOR_BRIDGE_NAME}/${options.chain}/${contractAddr}/${eventSignature} on disk`
|
||||||
|
)
|
||||||
|
writeCacheFile(cacheFile, {
|
||||||
|
fromBlock,
|
||||||
|
toBlock: safeToBlock,
|
||||||
|
events: cacheToSave
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveCache() {
|
||||||
|
if (isDirty) {
|
||||||
|
logger.debug('Saving cache on disk')
|
||||||
|
writeCacheFile(homeTxSendersCacheFile, cachedHomeTxSenders)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getHomeTxSender,
|
||||||
|
getPastEvents,
|
||||||
|
saveCache
|
||||||
|
}
|
@ -1,13 +1,12 @@
|
|||||||
require('dotenv').config()
|
require('dotenv').config()
|
||||||
const Web3 = require('web3')
|
const Web3Utils = require('web3').utils
|
||||||
const fetch = require('node-fetch')
|
const fetch = require('node-fetch')
|
||||||
const logger = require('./logger')('validators')
|
const logger = require('./logger')('validators')
|
||||||
const { getBridgeABIs, BRIDGE_VALIDATORS_ABI, getValidatorList, gasPriceFromSupplier } = require('../commons')
|
const { getBridgeABIs, BRIDGE_VALIDATORS_ABI, gasPriceFromSupplier } = require('../commons')
|
||||||
const { getBlockNumber } = require('./utils/contract')
|
const { web3Home, web3Foreign, getHomeBlockNumber, getForeignBlockNumber } = require('./utils/web3')
|
||||||
|
const { getValidatorList } = require('./utils/getValidatorsList')
|
||||||
|
|
||||||
const {
|
const {
|
||||||
COMMON_HOME_RPC_URL,
|
|
||||||
COMMON_FOREIGN_RPC_URL,
|
|
||||||
COMMON_HOME_BRIDGE_ADDRESS,
|
COMMON_HOME_BRIDGE_ADDRESS,
|
||||||
COMMON_FOREIGN_BRIDGE_ADDRESS,
|
COMMON_FOREIGN_BRIDGE_ADDRESS,
|
||||||
COMMON_HOME_GAS_PRICE_SUPPLIER_URL,
|
COMMON_HOME_GAS_PRICE_SUPPLIER_URL,
|
||||||
@ -19,19 +18,9 @@ const {
|
|||||||
COMMON_FOREIGN_GAS_PRICE_FALLBACK,
|
COMMON_FOREIGN_GAS_PRICE_FALLBACK,
|
||||||
COMMON_FOREIGN_GAS_PRICE_FACTOR
|
COMMON_FOREIGN_GAS_PRICE_FACTOR
|
||||||
} = process.env
|
} = 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_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_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 = {
|
const homeGasPriceSupplierOpts = {
|
||||||
speedType: COMMON_HOME_GAS_PRICE_SPEED_TYPE,
|
speedType: COMMON_HOME_GAS_PRICE_SPEED_TYPE,
|
||||||
factor: COMMON_HOME_GAS_PRICE_FACTOR,
|
factor: COMMON_HOME_GAS_PRICE_FACTOR,
|
||||||
@ -58,7 +47,12 @@ async function main(bridgeMode) {
|
|||||||
const homeBridgeValidators = new web3Home.eth.Contract(BRIDGE_VALIDATORS_ABI, homeValidatorsAddress)
|
const homeBridgeValidators = new web3Home.eth.Contract(BRIDGE_VALIDATORS_ABI, homeValidatorsAddress)
|
||||||
|
|
||||||
logger.debug('getting last block numbers')
|
logger.debug('getting last block numbers')
|
||||||
const [homeBlockNumber, foreignBlockNumber] = await getBlockNumber(web3Home, web3Foreign)
|
const homeBlockNumber = await getHomeBlockNumber()
|
||||||
|
const foreignBlockNumber = await getForeignBlockNumber()
|
||||||
|
const homeConfirmations = await homeBridge.methods.requiredBlockConfirmations().call()
|
||||||
|
const foreignConfirmations = await foreignBridge.methods.requiredBlockConfirmations().call()
|
||||||
|
const homeDelayedBlockNumber = homeBlockNumber - homeConfirmations
|
||||||
|
const foreignDelayedBlockNumber = foreignBlockNumber - foreignConfirmations
|
||||||
|
|
||||||
logger.debug('calling foreignBridge.methods.validatorContract().call()')
|
logger.debug('calling foreignBridge.methods.validatorContract().call()')
|
||||||
const foreignValidatorsAddress = await foreignBridge.methods.validatorContract().call()
|
const foreignValidatorsAddress = await foreignBridge.methods.validatorContract().call()
|
||||||
@ -66,16 +60,18 @@ async function main(bridgeMode) {
|
|||||||
|
|
||||||
logger.debug('calling foreignBridgeValidators getValidatorList()')
|
logger.debug('calling foreignBridgeValidators getValidatorList()')
|
||||||
const foreignValidators = (await getValidatorList(foreignValidatorsAddress, web3Foreign.eth, {
|
const foreignValidators = (await getValidatorList(foreignValidatorsAddress, web3Foreign.eth, {
|
||||||
from: MONITOR_FOREIGN_START_BLOCK,
|
toBlock: foreignBlockNumber,
|
||||||
to: foreignBlockNumber,
|
logger,
|
||||||
logger
|
chain: 'foreign',
|
||||||
|
safeToBlock: foreignDelayedBlockNumber
|
||||||
})).map(web3Foreign.utils.toChecksumAddress)
|
})).map(web3Foreign.utils.toChecksumAddress)
|
||||||
|
|
||||||
logger.debug('calling homeBridgeValidators getValidatorList()')
|
logger.debug('calling homeBridgeValidators getValidatorList()')
|
||||||
const homeValidators = (await getValidatorList(homeValidatorsAddress, web3Home.eth, {
|
const homeValidators = (await getValidatorList(homeValidatorsAddress, web3Home.eth, {
|
||||||
from: MONITOR_HOME_START_BLOCK,
|
toBlock: homeBlockNumber,
|
||||||
to: homeBlockNumber,
|
logger,
|
||||||
logger
|
chain: 'home',
|
||||||
|
safeToBlock: homeDelayedBlockNumber
|
||||||
})).map(web3Home.utils.toChecksumAddress)
|
})).map(web3Home.utils.toChecksumAddress)
|
||||||
|
|
||||||
const foreignVBalances = {}
|
const foreignVBalances = {}
|
||||||
|
@ -1,8 +1,24 @@
|
|||||||
cd $(dirname $0)
|
cd $(dirname $0)
|
||||||
|
|
||||||
../e2e-commons/up.sh deploy blocks oracle oracle-validator-2 oracle-validator-3
|
mode="$1"
|
||||||
|
case "$mode" in
|
||||||
|
amb)
|
||||||
|
script=./test/amb.js
|
||||||
|
;;
|
||||||
|
native-to-erc)
|
||||||
|
script=./test/nativeToErc.js
|
||||||
|
;;
|
||||||
|
erc-to-erc)
|
||||||
|
script=./test/ercToErc.js
|
||||||
|
;;
|
||||||
|
erc-to-native)
|
||||||
|
script=./test/ercToNative.js
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
docker-compose -f ../e2e-commons/docker-compose.yml run e2e yarn workspace oracle-e2e run start
|
MODE="$mode" ../e2e-commons/up.sh deploy blocks oracle oracle-validator-2 oracle-validator-3
|
||||||
|
|
||||||
|
docker-compose -f ../e2e-commons/docker-compose.yml run e2e yarn workspace oracle-e2e run start $script
|
||||||
rc=$?
|
rc=$?
|
||||||
|
|
||||||
../e2e-commons/down.sh
|
../e2e-commons/down.sh
|
||||||
|
@ -3,7 +3,7 @@ const assert = require('assert')
|
|||||||
const { user, homeRPC, foreignRPC, amb, validator } = require('../../e2e-commons/constants.json')
|
const { user, homeRPC, foreignRPC, amb, validator } = require('../../e2e-commons/constants.json')
|
||||||
const { uniformRetry } = require('../../e2e-commons/utils')
|
const { uniformRetry } = require('../../e2e-commons/utils')
|
||||||
const { BOX_ABI, HOME_AMB_ABI, FOREIGN_AMB_ABI } = require('../../commons')
|
const { BOX_ABI, HOME_AMB_ABI, FOREIGN_AMB_ABI } = require('../../commons')
|
||||||
const { setRequiredSignatures } = require('./utils')
|
const { delay, setRequiredSignatures } = require('./utils')
|
||||||
|
|
||||||
const { toBN } = Web3.utils
|
const { toBN } = Web3.utils
|
||||||
|
|
||||||
@ -19,14 +19,17 @@ foreignWeb3.eth.accounts.wallet.add(user.privateKey)
|
|||||||
foreignWeb3.eth.accounts.wallet.add(validator.privateKey)
|
foreignWeb3.eth.accounts.wallet.add(validator.privateKey)
|
||||||
|
|
||||||
const homeBox = new homeWeb3.eth.Contract(BOX_ABI, amb.homeBox)
|
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 foreignBox = new foreignWeb3.eth.Contract(BOX_ABI, amb.foreignBox)
|
||||||
const homeBridge = new homeWeb3.eth.Contract(HOME_AMB_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
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)
|
const foreignBridge = new foreignWeb3.eth.Contract(FOREIGN_AMB_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||||
|
|
||||||
describe('arbitrary message bridging', () => {
|
describe('arbitrary message bridging', () => {
|
||||||
|
let requiredSignatures = 1
|
||||||
before(async () => {
|
before(async () => {
|
||||||
// Only 1 validator is used in ultimate tests
|
// Only 1 validator is used in ultimate tests
|
||||||
if (process.env.ULTIMATE !== 'true') {
|
if (process.env.ULTIMATE !== 'true') {
|
||||||
|
requiredSignatures = 2
|
||||||
// Set 2 required signatures for home bridge
|
// Set 2 required signatures for home bridge
|
||||||
await setRequiredSignatures({
|
await setRequiredSignatures({
|
||||||
bridgeContract: homeBridge,
|
bridgeContract: homeBridge,
|
||||||
@ -76,6 +79,85 @@ describe('arbitrary message bridging', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// allowance/block lists files are not mounted to the host during the ultimate test
|
||||||
|
if (process.env.ULTIMATE !== 'true') {
|
||||||
|
it('should confirm but not relay message from blocked contract', async () => {
|
||||||
|
const newValue = 4
|
||||||
|
|
||||||
|
const initialValue = await foreignBox.methods.value().call()
|
||||||
|
assert(!toBN(initialValue).eq(toBN(newValue)), 'initial value should be different from new value')
|
||||||
|
|
||||||
|
const signatures = await homeBridge.getPastEvents('SignedForUserRequest', {
|
||||||
|
fromBlock: 0,
|
||||||
|
toBlock: 'latest'
|
||||||
|
})
|
||||||
|
|
||||||
|
await blockHomeBox.methods
|
||||||
|
.setValueOnOtherNetwork(newValue, amb.home, amb.foreignBox)
|
||||||
|
.send({
|
||||||
|
from: user.address,
|
||||||
|
gas: '400000'
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
console.error(e)
|
||||||
|
})
|
||||||
|
|
||||||
|
await delay(5000)
|
||||||
|
|
||||||
|
const newSignatures = await homeBridge.getPastEvents('SignedForUserRequest', {
|
||||||
|
fromBlock: 0,
|
||||||
|
toBlock: 'latest'
|
||||||
|
})
|
||||||
|
|
||||||
|
assert(
|
||||||
|
newSignatures.length === signatures.length + requiredSignatures,
|
||||||
|
`Incorrect amount of signatures submitted, got ${newSignatures.length}, expected ${signatures.length +
|
||||||
|
requiredSignatures}`
|
||||||
|
)
|
||||||
|
|
||||||
|
const value = await foreignBox.methods.value().call()
|
||||||
|
assert(!toBN(value).eq(toBN(newValue)), 'Message should not be relayed by oracle automatically')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should confirm but not relay message from manual lane', async () => {
|
||||||
|
const newValue = 5
|
||||||
|
|
||||||
|
const initialValue = await foreignBox.methods.value().call()
|
||||||
|
assert(!toBN(initialValue).eq(toBN(newValue)), 'initial value should be different from new value')
|
||||||
|
|
||||||
|
const signatures = await homeBridge.getPastEvents('SignedForUserRequest', {
|
||||||
|
fromBlock: 0,
|
||||||
|
toBlock: 'latest'
|
||||||
|
})
|
||||||
|
|
||||||
|
await homeBox.methods
|
||||||
|
.setValueOnOtherNetworkUsingManualLane(newValue, amb.home, amb.foreignBox)
|
||||||
|
.send({
|
||||||
|
from: user.address,
|
||||||
|
gas: '400000'
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
console.error(e)
|
||||||
|
})
|
||||||
|
|
||||||
|
await delay(5000)
|
||||||
|
|
||||||
|
const newSignatures = await homeBridge.getPastEvents('SignedForUserRequest', {
|
||||||
|
fromBlock: 0,
|
||||||
|
toBlock: 'latest'
|
||||||
|
})
|
||||||
|
|
||||||
|
assert(
|
||||||
|
newSignatures.length === signatures.length + requiredSignatures,
|
||||||
|
`Incorrect amount of signatures submitted, got ${newSignatures.length}, expected ${signatures.length +
|
||||||
|
requiredSignatures}`
|
||||||
|
)
|
||||||
|
|
||||||
|
const value = await foreignBox.methods.value().call()
|
||||||
|
assert(!toBN(value).eq(toBN(newValue)), 'Message should not be relayed by oracle automatically')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
describe('Foreign to Home', () => {
|
describe('Foreign to Home', () => {
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
const { BRIDGE_VALIDATORS_ABI } = require('../../commons')
|
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 setRequiredSignatures = async ({ bridgeContract, web3, requiredSignatures, options }) => {
|
||||||
const validatorAddress = await bridgeContract.methods.validatorContract().call()
|
const validatorAddress = await bridgeContract.methods.validatorContract().call()
|
||||||
const validatorContract = new web3.eth.Contract(BRIDGE_VALIDATORS_ABI, validatorAddress)
|
const validatorContract = new web3.eth.Contract(BRIDGE_VALIDATORS_ABI, validatorAddress)
|
||||||
@ -8,5 +12,6 @@ const setRequiredSignatures = async ({ bridgeContract, web3, requiredSignatures,
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
delay,
|
||||||
setRequiredSignatures
|
setRequiredSignatures
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ ORACLE_FOREIGN_START_BLOCK=
|
|||||||
|
|
||||||
ORACLE_LOG_LEVEL=debug
|
ORACLE_LOG_LEVEL=debug
|
||||||
ORACLE_MAX_PROCESSING_TIME=20000
|
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_ALLOWANCE_LIST=access-lists/allowance_list.txt
|
||||||
ORACLE_HOME_TO_FOREIGN_BLOCK_LIST=access-lists/block_list.txt
|
ORACLE_HOME_TO_FOREIGN_BLOCK_LIST=access-lists/block_list.txt
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const baseConfig = require('./base.config')
|
const baseConfig = require('./base.config')
|
||||||
|
|
||||||
const { web3Foreign } = require('../src/services/web3')
|
const { web3Foreign, web3ForeignRedundant } = require('../src/services/web3')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
...baseConfig.bridgeConfig,
|
...baseConfig.bridgeConfig,
|
||||||
@ -8,5 +8,6 @@ module.exports = {
|
|||||||
oldQueue: 'foreign',
|
oldQueue: 'foreign',
|
||||||
id: 'foreign',
|
id: 'foreign',
|
||||||
name: 'sender-foreign',
|
name: 'sender-foreign',
|
||||||
web3: web3Foreign
|
web3: web3Foreign,
|
||||||
|
web3Redundant: web3ForeignRedundant
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const baseConfig = require('./base.config')
|
const baseConfig = require('./base.config')
|
||||||
|
|
||||||
const { web3Home } = require('../src/services/web3')
|
const { web3Home, web3HomeRedundant } = require('../src/services/web3')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
...baseConfig.bridgeConfig,
|
...baseConfig.bridgeConfig,
|
||||||
@ -8,5 +8,6 @@ module.exports = {
|
|||||||
oldQueue: 'home',
|
oldQueue: 'home',
|
||||||
id: 'home',
|
id: 'home',
|
||||||
name: 'sender-home',
|
name: 'sender-home',
|
||||||
web3: web3Home
|
web3: web3Home,
|
||||||
|
web3Redundant: web3HomeRedundant
|
||||||
}
|
}
|
||||||
|
@ -26,15 +26,13 @@
|
|||||||
"amqplib": "^0.5.2",
|
"amqplib": "^0.5.2",
|
||||||
"bignumber.js": "^7.2.1",
|
"bignumber.js": "^7.2.1",
|
||||||
"dotenv": "^5.0.1",
|
"dotenv": "^5.0.1",
|
||||||
"http-list-provider": "0.0.5",
|
|
||||||
"ioredis": "^3.2.2",
|
"ioredis": "^3.2.2",
|
||||||
"node-fetch": "^2.1.2",
|
"node-fetch": "^2.1.2",
|
||||||
"pino": "^4.17.3",
|
"pino": "^4.17.3",
|
||||||
"pino-pretty": "^2.0.1",
|
"pino-pretty": "^2.0.1",
|
||||||
"promise-limit": "^2.7.0",
|
"promise-limit": "^2.7.0",
|
||||||
"promise-retry": "^1.1.1",
|
"promise-retry": "^1.1.1",
|
||||||
"web3": "1.0.0-beta.34",
|
"web3": "^1.3.0"
|
||||||
"web3-utils": "1.0.0-beta.34"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"bn-chai": "^1.0.1",
|
"bn-chai": "^1.0.1",
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
require('../../env')
|
require('../../env')
|
||||||
const Web3 = require('web3')
|
const { toWei } = require('web3').utils
|
||||||
const Web3Utils = require('web3-utils')
|
const { web3Foreign } = require('../../src/services/web3')
|
||||||
const rpcUrlsManager = require('../../src/services/getRpcUrlsManager')
|
const { sendTx } = require('../../src/tx/sendTx')
|
||||||
const { sendTx, sendRawTx } = require('../../src/tx/sendTx')
|
|
||||||
const { ERC20_ABI } = require('../../../commons')
|
const { ERC20_ABI } = require('../../../commons')
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -17,37 +16,23 @@ const NUMBER_OF_DEPOSITS_TO_SEND = process.argv[2] || process.env.NUMBER_OF_DEPO
|
|||||||
|
|
||||||
const { FOREIGN_ERC_TO_ERC_ABI } = require('../../../commons')
|
const { 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() {
|
async function main() {
|
||||||
const bridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
const bridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||||
const bridgeableTokenAddress = await bridge.methods.erc20token().call()
|
const bridgeableTokenAddress = await bridge.methods.erc20token().call()
|
||||||
const poa20 = new web3Foreign.eth.Contract(ERC20_ABI, bridgeableTokenAddress)
|
const poa20 = new web3Foreign.eth.Contract(ERC20_ABI, bridgeableTokenAddress)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const foreignChainId = await sendRawTx({
|
const foreignChainId = await web3Foreign.eth.getChainId()
|
||||||
chain: 'foreign',
|
let nonce = await web3Foreign.eth.getTransactionCount(USER_ADDRESS)
|
||||||
params: [],
|
|
||||||
method: 'net_version'
|
|
||||||
})
|
|
||||||
let nonce = await sendRawTx({
|
|
||||||
chain: 'foreign',
|
|
||||||
method: 'eth_getTransactionCount',
|
|
||||||
params: [USER_ADDRESS, 'latest']
|
|
||||||
})
|
|
||||||
nonce = Web3Utils.hexToNumber(nonce)
|
|
||||||
let actualSent = 0
|
let actualSent = 0
|
||||||
for (let i = 0; i < Number(NUMBER_OF_DEPOSITS_TO_SEND); i++) {
|
for (let i = 0; i < Number(NUMBER_OF_DEPOSITS_TO_SEND); i++) {
|
||||||
const gasLimit = await poa20.methods
|
const gasLimit = await poa20.methods
|
||||||
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX))
|
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, toWei(FOREIGN_MIN_AMOUNT_PER_TX))
|
||||||
.estimateGas({ from: USER_ADDRESS })
|
.estimateGas({ from: USER_ADDRESS })
|
||||||
const data = await poa20.methods
|
const data = await poa20.methods
|
||||||
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX))
|
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, toWei(FOREIGN_MIN_AMOUNT_PER_TX))
|
||||||
.encodeABI({ from: USER_ADDRESS })
|
.encodeABI({ from: USER_ADDRESS })
|
||||||
const txHash = await sendTx({
|
const txHash = await sendTx({
|
||||||
chain: 'foreign',
|
|
||||||
privateKey: USER_ADDRESS_PRIVATE_KEY,
|
privateKey: USER_ADDRESS_PRIVATE_KEY,
|
||||||
data,
|
data,
|
||||||
nonce,
|
nonce,
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
require('../../env')
|
require('../../env')
|
||||||
const Web3 = require('web3')
|
const { toWei } = require('web3').utils
|
||||||
const Web3Utils = require('web3-utils')
|
const { web3Home } = require('../../src/services/web3')
|
||||||
const rpcUrlsManager = require('../../src/services/getRpcUrlsManager')
|
const { sendTx } = require('../../src/tx/sendTx')
|
||||||
const { sendTx, sendRawTx } = require('../../src/tx/sendTx')
|
|
||||||
const { isValidAmount } = require('../utils/utils')
|
const { isValidAmount } = require('../utils/utils')
|
||||||
const { HOME_ERC_TO_ERC_ABI } = require('../../../commons')
|
const { HOME_ERC_TO_ERC_ABI } = require('../../../commons')
|
||||||
|
|
||||||
@ -46,10 +45,6 @@ const BRIDGEABLE_TOKEN_ABI = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
const homeRpcUrl = rpcUrlsManager.homeUrls[0]
|
|
||||||
const homeProvider = new Web3.providers.HttpProvider(homeRpcUrl)
|
|
||||||
const web3Home = new Web3(homeProvider)
|
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const bridge = new web3Home.eth.Contract(HOME_ERC_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
const bridge = new web3Home.eth.Contract(HOME_ERC_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
||||||
const BRIDGEABLE_TOKEN_ADDRESS = await bridge.methods.erc677token().call()
|
const BRIDGEABLE_TOKEN_ADDRESS = await bridge.methods.erc677token().call()
|
||||||
@ -58,27 +53,17 @@ async function main() {
|
|||||||
try {
|
try {
|
||||||
await isValidAmount(HOME_MIN_AMOUNT_PER_TX, bridge)
|
await isValidAmount(HOME_MIN_AMOUNT_PER_TX, bridge)
|
||||||
|
|
||||||
const homeChainId = await sendRawTx({
|
const homeChainId = await web3Home.eth.getChainId()
|
||||||
chain: 'home',
|
let nonce = await web3Home.eth.getTransactionCount(USER_ADDRESS)
|
||||||
params: [],
|
|
||||||
method: 'net_version'
|
|
||||||
})
|
|
||||||
let nonce = await sendRawTx({
|
|
||||||
chain: 'home',
|
|
||||||
method: 'eth_getTransactionCount',
|
|
||||||
params: [USER_ADDRESS, 'latest']
|
|
||||||
})
|
|
||||||
nonce = Web3Utils.hexToNumber(nonce)
|
|
||||||
let actualSent = 0
|
let actualSent = 0
|
||||||
for (let i = 0; i < Number(NUMBER_OF_WITHDRAWALS_TO_SEND); i++) {
|
for (let i = 0; i < Number(NUMBER_OF_WITHDRAWALS_TO_SEND); i++) {
|
||||||
const gasLimit = await erc677.methods
|
const gasLimit = await erc677.methods
|
||||||
.transferAndCall(COMMON_HOME_BRIDGE_ADDRESS, Web3Utils.toWei(HOME_MIN_AMOUNT_PER_TX), '0x')
|
.transferAndCall(COMMON_HOME_BRIDGE_ADDRESS, toWei(HOME_MIN_AMOUNT_PER_TX), '0x')
|
||||||
.estimateGas({ from: USER_ADDRESS })
|
.estimateGas({ from: USER_ADDRESS })
|
||||||
const data = await erc677.methods
|
const data = await erc677.methods
|
||||||
.transferAndCall(COMMON_HOME_BRIDGE_ADDRESS, Web3Utils.toWei(HOME_MIN_AMOUNT_PER_TX), '0x')
|
.transferAndCall(COMMON_HOME_BRIDGE_ADDRESS, toWei(HOME_MIN_AMOUNT_PER_TX), '0x')
|
||||||
.encodeABI({ from: USER_ADDRESS })
|
.encodeABI({ from: USER_ADDRESS })
|
||||||
const txHash = await sendTx({
|
const txHash = await sendTx({
|
||||||
chain: 'home',
|
|
||||||
privateKey: USER_ADDRESS_PRIVATE_KEY,
|
privateKey: USER_ADDRESS_PRIVATE_KEY,
|
||||||
data,
|
data,
|
||||||
nonce,
|
nonce,
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
require('../../env')
|
require('../../env')
|
||||||
const Web3 = require('web3')
|
const { toWei } = require('web3').utils
|
||||||
const Web3Utils = require('web3-utils')
|
const { web3Foreign } = require('../../src/services/web3')
|
||||||
const rpcUrlsManager = require('../../src/services/getRpcUrlsManager')
|
const { sendTx } = require('../../src/tx/sendTx')
|
||||||
const { sendTx, sendRawTx } = require('../../src/tx/sendTx')
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
USER_ADDRESS,
|
USER_ADDRESS,
|
||||||
@ -16,37 +15,23 @@ const NUMBER_OF_DEPOSITS_TO_SEND = process.argv[2] || process.env.NUMBER_OF_DEPO
|
|||||||
|
|
||||||
const { ERC20_ABI, FOREIGN_ERC_TO_NATIVE_ABI } = require('../../../commons')
|
const { 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() {
|
async function main() {
|
||||||
const bridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
const bridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||||
const bridgeableTokenAddress = await bridge.methods.erc20token().call()
|
const bridgeableTokenAddress = await bridge.methods.erc20token().call()
|
||||||
const poa20 = new web3Foreign.eth.Contract(ERC20_ABI, bridgeableTokenAddress)
|
const poa20 = new web3Foreign.eth.Contract(ERC20_ABI, bridgeableTokenAddress)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const foreignChainId = await sendRawTx({
|
const foreignChainId = await web3Foreign.eth.getChainId()
|
||||||
chain: 'foreign',
|
let nonce = await web3Foreign.eth.getTransactionCount(USER_ADDRESS)
|
||||||
params: [],
|
|
||||||
method: 'net_version'
|
|
||||||
})
|
|
||||||
let nonce = await sendRawTx({
|
|
||||||
chain: 'foreign',
|
|
||||||
method: 'eth_getTransactionCount',
|
|
||||||
params: [USER_ADDRESS, 'latest']
|
|
||||||
})
|
|
||||||
nonce = Web3Utils.hexToNumber(nonce)
|
|
||||||
let actualSent = 0
|
let actualSent = 0
|
||||||
for (let i = 0; i < Number(NUMBER_OF_DEPOSITS_TO_SEND); i++) {
|
for (let i = 0; i < Number(NUMBER_OF_DEPOSITS_TO_SEND); i++) {
|
||||||
const gasLimit = await poa20.methods
|
const gasLimit = await poa20.methods
|
||||||
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX))
|
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, toWei(FOREIGN_MIN_AMOUNT_PER_TX))
|
||||||
.estimateGas({ from: USER_ADDRESS })
|
.estimateGas({ from: USER_ADDRESS })
|
||||||
const data = await poa20.methods
|
const data = await poa20.methods
|
||||||
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX))
|
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, toWei(FOREIGN_MIN_AMOUNT_PER_TX))
|
||||||
.encodeABI({ from: USER_ADDRESS })
|
.encodeABI({ from: USER_ADDRESS })
|
||||||
const txHash = await sendTx({
|
const txHash = await sendTx({
|
||||||
chain: 'foreign',
|
|
||||||
privateKey: USER_ADDRESS_PRIVATE_KEY,
|
privateKey: USER_ADDRESS_PRIVATE_KEY,
|
||||||
data,
|
data,
|
||||||
nonce,
|
nonce,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
require('../../env')
|
require('../../env')
|
||||||
const Web3Utils = require('web3-utils')
|
|
||||||
const { web3Home } = require('../../src/services/web3')
|
const { web3Home } = require('../../src/services/web3')
|
||||||
const { sendTx, sendRawTx } = require('../../src/tx/sendTx')
|
const { sendTx } = require('../../src/tx/sendTx')
|
||||||
const { isValidAmount } = require('../utils/utils')
|
const { isValidAmount } = require('../utils/utils')
|
||||||
const { HOME_ERC_TO_NATIVE_ABI } = require('../../../commons')
|
const { HOME_ERC_TO_NATIVE_ABI } = require('../../../commons')
|
||||||
|
|
||||||
@ -21,21 +20,11 @@ async function main() {
|
|||||||
try {
|
try {
|
||||||
await isValidAmount(HOME_MIN_AMOUNT_PER_TX, bridge)
|
await isValidAmount(HOME_MIN_AMOUNT_PER_TX, bridge)
|
||||||
|
|
||||||
const homeChainId = await sendRawTx({
|
const homeChainId = await web3Home.eth.getChainId()
|
||||||
chain: 'home',
|
let nonce = await web3Home.eth.getTransactionCount(USER_ADDRESS)
|
||||||
params: [],
|
|
||||||
method: 'net_version'
|
|
||||||
})
|
|
||||||
let nonce = await sendRawTx({
|
|
||||||
chain: 'home',
|
|
||||||
method: 'eth_getTransactionCount',
|
|
||||||
params: [USER_ADDRESS, 'latest']
|
|
||||||
})
|
|
||||||
nonce = Web3Utils.hexToNumber(nonce)
|
|
||||||
let actualSent = 0
|
let actualSent = 0
|
||||||
for (let i = 0; i < Number(NUMBER_OF_DEPOSITS_TO_SEND); i++) {
|
for (let i = 0; i < Number(NUMBER_OF_DEPOSITS_TO_SEND); i++) {
|
||||||
const txHash = await sendTx({
|
const txHash = await sendTx({
|
||||||
chain: 'home',
|
|
||||||
privateKey: USER_ADDRESS_PRIVATE_KEY,
|
privateKey: USER_ADDRESS_PRIVATE_KEY,
|
||||||
data: '0x',
|
data: '0x',
|
||||||
nonce,
|
nonce,
|
||||||
|
@ -1,23 +1,20 @@
|
|||||||
require('../env')
|
require('../env')
|
||||||
const Web3 = require('web3')
|
|
||||||
|
|
||||||
const { BRIDGE_VALIDATORS_ABI } = require('../../commons')
|
const { BRIDGE_VALIDATORS_ABI } = require('../../commons')
|
||||||
const rpcUrlsManager = require('../src/services/getRpcUrlsManager')
|
const { web3Home, web3Foreign } = require('../src/services/web3')
|
||||||
const { bridgeConfig } = require('../config/base.config')
|
const { bridgeConfig } = require('../config/base.config')
|
||||||
|
|
||||||
const homeABI = bridgeConfig.homeBridgeAbi
|
const homeABI = bridgeConfig.homeBridgeAbi
|
||||||
const foreignABI = bridgeConfig.foreignBridgeAbi
|
const foreignABI = bridgeConfig.foreignBridgeAbi
|
||||||
|
|
||||||
async function getStartBlock(rpcUrl, bridgeAddress, bridgeAbi) {
|
async function getStartBlock(web3, bridgeAddress, bridgeAbi) {
|
||||||
try {
|
try {
|
||||||
const web3Provider = new Web3.providers.HttpProvider(rpcUrl)
|
const bridgeContract = new web3.eth.Contract(bridgeAbi, bridgeAddress)
|
||||||
const web3Instance = new Web3(web3Provider)
|
|
||||||
const bridgeContract = new web3Instance.eth.Contract(bridgeAbi, bridgeAddress)
|
|
||||||
|
|
||||||
const deployedAtBlock = await bridgeContract.methods.deployedAtBlock().call()
|
const deployedAtBlock = await bridgeContract.methods.deployedAtBlock().call()
|
||||||
|
|
||||||
const validatorContractAddress = await bridgeContract.methods.validatorContract().call()
|
const validatorContractAddress = await bridgeContract.methods.validatorContract().call()
|
||||||
const validatorContract = new web3Instance.eth.Contract(BRIDGE_VALIDATORS_ABI, validatorContractAddress)
|
const validatorContract = new web3.eth.Contract(BRIDGE_VALIDATORS_ABI, validatorContractAddress)
|
||||||
|
|
||||||
const validatorDeployedAtBlock = await validatorContract.methods.deployedAtBlock().call()
|
const validatorDeployedAtBlock = await validatorContract.methods.deployedAtBlock().call()
|
||||||
|
|
||||||
@ -35,10 +32,8 @@ async function getStartBlock(rpcUrl, bridgeAddress, bridgeAbi) {
|
|||||||
async function main() {
|
async function main() {
|
||||||
const { COMMON_HOME_BRIDGE_ADDRESS, COMMON_FOREIGN_BRIDGE_ADDRESS } = process.env
|
const { COMMON_HOME_BRIDGE_ADDRESS, COMMON_FOREIGN_BRIDGE_ADDRESS } = process.env
|
||||||
|
|
||||||
const homeRpcUrl = rpcUrlsManager.homeUrls[0]
|
const homeStartBlock = await getStartBlock(web3Home, COMMON_HOME_BRIDGE_ADDRESS, homeABI)
|
||||||
const foreignRpcUrl = rpcUrlsManager.foreignUrls[0]
|
const foreignStartBlock = await getStartBlock(web3Foreign, COMMON_FOREIGN_BRIDGE_ADDRESS, foreignABI)
|
||||||
const homeStartBlock = await getStartBlock(homeRpcUrl, COMMON_HOME_BRIDGE_ADDRESS, homeABI)
|
|
||||||
const foreignStartBlock = await getStartBlock(foreignRpcUrl, COMMON_FOREIGN_BRIDGE_ADDRESS, foreignABI)
|
|
||||||
const result = {
|
const result = {
|
||||||
homeStartBlock,
|
homeStartBlock,
|
||||||
foreignStartBlock
|
foreignStartBlock
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
require('../env')
|
require('../env')
|
||||||
const Web3 = require('web3')
|
|
||||||
const { getTokensState } = require('../src/utils/tokenState')
|
const { getTokensState } = require('../src/utils/tokenState')
|
||||||
const {
|
const {
|
||||||
ERC677_BRIDGE_TOKEN_ABI,
|
ERC677_BRIDGE_TOKEN_ABI,
|
||||||
@ -7,6 +6,7 @@ const {
|
|||||||
FOREIGN_ERC_TO_NATIVE_ABI,
|
FOREIGN_ERC_TO_NATIVE_ABI,
|
||||||
getTokenType
|
getTokenType
|
||||||
} = require('../../commons')
|
} = require('../../commons')
|
||||||
|
const { web3Foreign } = require('../src/services/web3')
|
||||||
|
|
||||||
const emptyLogger = {
|
const emptyLogger = {
|
||||||
debug: () => {},
|
debug: () => {},
|
||||||
@ -14,26 +14,25 @@ const emptyLogger = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function initialChecks() {
|
async function initialChecks() {
|
||||||
const { ORACLE_BRIDGE_MODE, COMMON_FOREIGN_RPC_URL, COMMON_FOREIGN_BRIDGE_ADDRESS } = process.env
|
const { ORACLE_BRIDGE_MODE, COMMON_FOREIGN_BRIDGE_ADDRESS } = process.env
|
||||||
let result = {}
|
let result = {}
|
||||||
const foreignWeb3 = new Web3(new Web3.providers.HttpProvider(COMMON_FOREIGN_RPC_URL))
|
|
||||||
|
|
||||||
if (ORACLE_BRIDGE_MODE === 'ERC_TO_ERC') {
|
if (ORACLE_BRIDGE_MODE === 'ERC_TO_ERC') {
|
||||||
const bridge = new foreignWeb3.eth.Contract(FOREIGN_ERC_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
const bridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||||
result.bridgeableTokenAddress = await bridge.methods.erc20token().call()
|
result.bridgeableTokenAddress = await bridge.methods.erc20token().call()
|
||||||
} else if (ORACLE_BRIDGE_MODE === 'ERC_TO_NATIVE') {
|
} else if (ORACLE_BRIDGE_MODE === 'ERC_TO_NATIVE') {
|
||||||
const bridge = new foreignWeb3.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
const bridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||||
result = await getTokensState(bridge, emptyLogger)
|
result = await getTokensState(bridge, emptyLogger)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ORACLE_BRIDGE_MODE === 'ERC_TO_ERC') {
|
if (ORACLE_BRIDGE_MODE === 'ERC_TO_ERC') {
|
||||||
const bridgeTokenContract = new foreignWeb3.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, result.bridgeableTokenAddress)
|
const bridgeTokenContract = new web3Foreign.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, result.bridgeableTokenAddress)
|
||||||
result.foreignERC = await getTokenType(bridgeTokenContract, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
result.foreignERC = await getTokenType(bridgeTokenContract, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||||
}
|
}
|
||||||
console.log(JSON.stringify(result))
|
console.log(JSON.stringify(result))
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
initialChecks()
|
const result = initialChecks()
|
||||||
|
|
||||||
module.exports = initialChecks
|
module.exports = result
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
require('../../env')
|
require('../../env')
|
||||||
const Web3Utils = require('web3-utils')
|
const { toWei } = require('web3').utils
|
||||||
const { web3Foreign } = require('../../src/services/web3')
|
const { web3Foreign } = require('../../src/services/web3')
|
||||||
const { sendTx, sendRawTx } = require('../../src/tx/sendTx')
|
const { sendTx } = require('../../src/tx/sendTx')
|
||||||
const { isValidAmount } = require('../utils/utils')
|
const { isValidAmount } = require('../utils/utils')
|
||||||
const { FOREIGN_NATIVE_TO_ERC_ABI } = require('../../../commons')
|
const { FOREIGN_NATIVE_TO_ERC_ABI } = require('../../../commons')
|
||||||
|
|
||||||
@ -53,27 +53,17 @@ async function main() {
|
|||||||
try {
|
try {
|
||||||
await isValidAmount(FOREIGN_MIN_AMOUNT_PER_TX, bridge)
|
await isValidAmount(FOREIGN_MIN_AMOUNT_PER_TX, bridge)
|
||||||
|
|
||||||
const foreignChainId = await sendRawTx({
|
const foreignChainId = await web3Foreign.eth.getChainId()
|
||||||
chain: 'foreign',
|
let nonce = await web3Foreign.eth.getTransactionCount(USER_ADDRESS)
|
||||||
params: [],
|
|
||||||
method: 'net_version'
|
|
||||||
})
|
|
||||||
let nonce = await sendRawTx({
|
|
||||||
chain: 'foreign',
|
|
||||||
method: 'eth_getTransactionCount',
|
|
||||||
params: [USER_ADDRESS, 'latest']
|
|
||||||
})
|
|
||||||
nonce = Web3Utils.hexToNumber(nonce)
|
|
||||||
let actualSent = 0
|
let actualSent = 0
|
||||||
for (let i = 0; i < Number(NUMBER_OF_WITHDRAWALS_TO_SEND); i++) {
|
for (let i = 0; i < Number(NUMBER_OF_WITHDRAWALS_TO_SEND); i++) {
|
||||||
const gasLimit = await poa20.methods
|
const gasLimit = await poa20.methods
|
||||||
.transferAndCall(COMMON_FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX), '0x')
|
.transferAndCall(COMMON_FOREIGN_BRIDGE_ADDRESS, toWei(FOREIGN_MIN_AMOUNT_PER_TX), '0x')
|
||||||
.estimateGas({ from: USER_ADDRESS })
|
.estimateGas({ from: USER_ADDRESS })
|
||||||
const data = await poa20.methods
|
const data = await poa20.methods
|
||||||
.transferAndCall(COMMON_FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX), '0x')
|
.transferAndCall(COMMON_FOREIGN_BRIDGE_ADDRESS, toWei(FOREIGN_MIN_AMOUNT_PER_TX), '0x')
|
||||||
.encodeABI({ from: USER_ADDRESS })
|
.encodeABI({ from: USER_ADDRESS })
|
||||||
const txHash = await sendTx({
|
const txHash = await sendTx({
|
||||||
chain: 'foreign',
|
|
||||||
privateKey: USER_ADDRESS_PRIVATE_KEY,
|
privateKey: USER_ADDRESS_PRIVATE_KEY,
|
||||||
data,
|
data,
|
||||||
nonce,
|
nonce,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
require('../../env')
|
require('../../env')
|
||||||
const Web3Utils = require('web3-utils')
|
|
||||||
const { web3Home } = require('../../src/services/web3')
|
const { web3Home } = require('../../src/services/web3')
|
||||||
const { sendTx, sendRawTx } = require('../../src/tx/sendTx')
|
const { sendTx } = require('../../src/tx/sendTx')
|
||||||
const { isValidAmount } = require('../utils/utils')
|
const { isValidAmount } = require('../utils/utils')
|
||||||
const { HOME_NATIVE_TO_ERC_ABI } = require('../../../commons')
|
const { HOME_NATIVE_TO_ERC_ABI } = require('../../../commons')
|
||||||
|
|
||||||
@ -21,21 +20,11 @@ async function main() {
|
|||||||
try {
|
try {
|
||||||
await isValidAmount(HOME_MIN_AMOUNT_PER_TX, bridge)
|
await isValidAmount(HOME_MIN_AMOUNT_PER_TX, bridge)
|
||||||
|
|
||||||
const homeChainId = await sendRawTx({
|
const homeChainId = await web3Home.eth.getChainId()
|
||||||
chain: 'home',
|
let nonce = await web3Home.eth.getTransactionCount(USER_ADDRESS)
|
||||||
params: [],
|
|
||||||
method: 'net_version'
|
|
||||||
})
|
|
||||||
let nonce = await sendRawTx({
|
|
||||||
chain: 'home',
|
|
||||||
method: 'eth_getTransactionCount',
|
|
||||||
params: [USER_ADDRESS, 'latest']
|
|
||||||
})
|
|
||||||
nonce = Web3Utils.hexToNumber(nonce)
|
|
||||||
let actualSent = 0
|
let actualSent = 0
|
||||||
for (let i = 0; i < Number(NUMBER_OF_DEPOSITS_TO_SEND); i++) {
|
for (let i = 0; i < Number(NUMBER_OF_DEPOSITS_TO_SEND); i++) {
|
||||||
const txHash = await sendTx({
|
const txHash = await sendTx({
|
||||||
chain: 'home',
|
|
||||||
privateKey: USER_ADDRESS_PRIVATE_KEY,
|
privateKey: USER_ADDRESS_PRIVATE_KEY,
|
||||||
data: '0x',
|
data: '0x',
|
||||||
nonce,
|
nonce,
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
const Web3Utils = require('web3-utils')
|
const { fromWei } = require('web3').utils
|
||||||
|
|
||||||
async function getMinPerTxLimit(bridge) {
|
async function getMinPerTxLimit(bridge) {
|
||||||
const minPerTx = await bridge.methods.minPerTx().call()
|
const minPerTx = await bridge.methods.minPerTx().call()
|
||||||
return Web3Utils.fromWei(minPerTx)
|
return fromWei(minPerTx)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function isValidAmount(amount, bridge) {
|
async function isValidAmount(amount, bridge) {
|
||||||
|
@ -3,7 +3,6 @@ const path = require('path')
|
|||||||
const { isAttached, connectWatcherToQueue, connection } = require('./services/amqpClient')
|
const { isAttached, connectWatcherToQueue, connection } = require('./services/amqpClient')
|
||||||
const logger = require('./services/logger')
|
const logger = require('./services/logger')
|
||||||
const GasPrice = require('./services/gasPrice')
|
const GasPrice = require('./services/gasPrice')
|
||||||
const rpcUrlsManager = require('./services/getRpcUrlsManager')
|
|
||||||
const { getNonce, getChainId, getEventsFromTx } = require('./tx/web3')
|
const { getNonce, getChainId, getEventsFromTx } = require('./tx/web3')
|
||||||
const { sendTx } = require('./tx/sendTx')
|
const { sendTx } = require('./tx/sendTx')
|
||||||
const { checkHTTPS, watchdog, syncForEach, addExtraGas } = require('./utils/utils')
|
const { checkHTTPS, watchdog, syncForEach, addExtraGas } = require('./utils/utils')
|
||||||
@ -37,8 +36,7 @@ async function initialize() {
|
|||||||
try {
|
try {
|
||||||
const checkHttps = checkHTTPS(ORACLE_ALLOW_HTTP_FOR_RPC, logger)
|
const checkHttps = checkHTTPS(ORACLE_ALLOW_HTTP_FOR_RPC, logger)
|
||||||
|
|
||||||
rpcUrlsManager.homeUrls.forEach(checkHttps('home'))
|
web3Instance.currentProvider.urls.forEach(checkHttps(config.chain))
|
||||||
rpcUrlsManager.foreignUrls.forEach(checkHttps('foreign'))
|
|
||||||
|
|
||||||
attached = await isAttached()
|
attached = await isAttached()
|
||||||
if (attached) {
|
if (attached) {
|
||||||
@ -139,7 +137,7 @@ async function main({ sendJob, txHash }) {
|
|||||||
|
|
||||||
async function sendJobTx(jobs) {
|
async function sendJobTx(jobs) {
|
||||||
const gasPrice = await GasPrice.start(config.chain, true)
|
const gasPrice = await GasPrice.start(config.chain, true)
|
||||||
const chainId = await getChainId(config.chain)
|
const chainId = await getChainId(web3Instance)
|
||||||
let nonce = await getNonce(web3Instance, ORACLE_VALIDATOR_ADDRESS)
|
let nonce = await getNonce(web3Instance, ORACLE_VALIDATOR_ADDRESS)
|
||||||
|
|
||||||
await syncForEach(jobs, async job => {
|
await syncForEach(jobs, async job => {
|
||||||
@ -153,7 +151,6 @@ async function sendJobTx(jobs) {
|
|||||||
try {
|
try {
|
||||||
logger.info(`Sending transaction with nonce ${nonce}`)
|
logger.info(`Sending transaction with nonce ${nonce}`)
|
||||||
const txHash = await sendTx({
|
const txHash = await sendTx({
|
||||||
chain: config.chain,
|
|
||||||
data: job.data,
|
data: job.data,
|
||||||
nonce,
|
nonce,
|
||||||
gasPrice: gasPrice.toString(10),
|
gasPrice: gasPrice.toString(10),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const { HttpListProviderError } = require('http-list-provider')
|
const { HttpListProviderError } = require('../../services/HttpListProvider')
|
||||||
const { AlreadyProcessedError, AlreadySignedError, InvalidValidatorError } = require('../../utils/errors')
|
const { AlreadyProcessedError, AlreadySignedError, InvalidValidatorError } = require('../../utils/errors')
|
||||||
const logger = require('../../services/logger').child({
|
const logger = require('../../services/logger').child({
|
||||||
module: 'processAffirmationRequests:estimateGas'
|
module: 'processAffirmationRequests:estimateGas'
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
require('dotenv').config()
|
require('dotenv').config()
|
||||||
const { HttpListProviderError } = require('http-list-provider')
|
|
||||||
const promiseLimit = require('promise-limit')
|
const promiseLimit = require('promise-limit')
|
||||||
|
const { HttpListProviderError } = require('../../services/HttpListProvider')
|
||||||
const rootLogger = require('../../services/logger')
|
const rootLogger = require('../../services/logger')
|
||||||
const { web3Home } = require('../../services/web3')
|
const { web3Home } = require('../../services/web3')
|
||||||
const bridgeValidatorsABI = require('../../../../contracts/build/contracts/BridgeValidators').abi
|
const bridgeValidatorsABI = require('../../../../contracts/build/contracts/BridgeValidators').abi
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
const Web3 = require('web3')
|
const Web3 = require('web3')
|
||||||
const { HttpListProviderError } = require('http-list-provider')
|
const { HttpListProviderError } = require('../../services/HttpListProvider')
|
||||||
const { AlreadyProcessedError, IncompatibleContractError, InvalidValidatorError } = require('../../utils/errors')
|
const { AlreadyProcessedError, IncompatibleContractError, InvalidValidatorError } = require('../../utils/errors')
|
||||||
const logger = require('../../services/logger').child({
|
const logger = require('../../services/logger').child({
|
||||||
module: 'processCollectedSignatures:estimateGas'
|
module: 'processCollectedSignatures:estimateGas'
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
require('dotenv').config()
|
require('dotenv').config()
|
||||||
const promiseLimit = require('promise-limit')
|
const promiseLimit = require('promise-limit')
|
||||||
const { HttpListProviderError } = require('http-list-provider')
|
const { HttpListProviderError } = require('../../services/HttpListProvider')
|
||||||
const bridgeValidatorsABI = require('../../../../contracts/build/contracts/BridgeValidators').abi
|
const bridgeValidatorsABI = require('../../../../contracts/build/contracts/BridgeValidators').abi
|
||||||
const rootLogger = require('../../services/logger')
|
const rootLogger = require('../../services/logger')
|
||||||
const { web3Home, web3Foreign } = require('../../services/web3')
|
const { web3Home, web3Foreign } = require('../../services/web3')
|
||||||
const { signatureToVRS, packSignatures } = require('../../utils/message')
|
const { signatureToVRS, packSignatures } = require('../../utils/message')
|
||||||
|
const { readAccessListFile } = require('../../utils/utils')
|
||||||
const { parseAMBMessage } = require('../../../../commons')
|
const { parseAMBMessage } = require('../../../../commons')
|
||||||
const estimateGas = require('./estimateGas')
|
const estimateGas = require('./estimateGas')
|
||||||
const { AlreadyProcessedError, IncompatibleContractError, InvalidValidatorError } = require('../../utils/errors')
|
const { AlreadyProcessedError, IncompatibleContractError, InvalidValidatorError } = require('../../utils/errors')
|
||||||
@ -12,7 +13,11 @@ const { MAX_CONCURRENT_EVENTS, EXTRA_GAS_ABSOLUTE } = require('../../utils/const
|
|||||||
|
|
||||||
const limit = promiseLimit(MAX_CONCURRENT_EVENTS)
|
const limit = promiseLimit(MAX_CONCURRENT_EVENTS)
|
||||||
|
|
||||||
const { ORACLE_ALWAYS_RELAY_SIGNATURES } = process.env
|
const {
|
||||||
|
ORACLE_HOME_TO_FOREIGN_ALLOWANCE_LIST,
|
||||||
|
ORACLE_HOME_TO_FOREIGN_BLOCK_LIST,
|
||||||
|
ORACLE_ALWAYS_RELAY_SIGNATURES
|
||||||
|
} = process.env
|
||||||
|
|
||||||
let validatorContract = null
|
let validatorContract = null
|
||||||
|
|
||||||
@ -50,6 +55,41 @@ function processCollectedSignaturesBuilder(config) {
|
|||||||
|
|
||||||
logger.info(`Processing CollectedSignatures ${colSignature.transactionHash}`)
|
logger.info(`Processing CollectedSignatures ${colSignature.transactionHash}`)
|
||||||
const message = await homeBridge.methods.message(messageHash).call()
|
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')
|
logger.debug({ NumberOfCollectedSignatures }, 'Number of signatures to get')
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
require('dotenv').config()
|
require('dotenv').config()
|
||||||
const promiseLimit = require('promise-limit')
|
const promiseLimit = require('promise-limit')
|
||||||
const { HttpListProviderError } = require('http-list-provider')
|
const { HttpListProviderError } = require('../../services/HttpListProvider')
|
||||||
const bridgeValidatorsABI = require('../../../../contracts/build/contracts/BridgeValidators').abi
|
const bridgeValidatorsABI = require('../../../../contracts/build/contracts/BridgeValidators').abi
|
||||||
const rootLogger = require('../../services/logger')
|
const rootLogger = require('../../services/logger')
|
||||||
const { web3Home } = require('../../services/web3')
|
const { web3Home } = require('../../services/web3')
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const { HttpListProviderError } = require('http-list-provider')
|
const { HttpListProviderError } = require('../../services/HttpListProvider')
|
||||||
const { AlreadyProcessedError, AlreadySignedError, InvalidValidatorError } = require('../../utils/errors')
|
const { AlreadyProcessedError, AlreadySignedError, InvalidValidatorError } = require('../../utils/errors')
|
||||||
const logger = require('../../services/logger').child({
|
const logger = require('../../services/logger').child({
|
||||||
module: 'processAffirmationRequests:estimateGas'
|
module: 'processAffirmationRequests:estimateGas'
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
require('../../../env')
|
require('../../../env')
|
||||||
const promiseLimit = require('promise-limit')
|
const promiseLimit = require('promise-limit')
|
||||||
const { HttpListProviderError } = require('http-list-provider')
|
const { HttpListProviderError } = require('../../services/HttpListProvider')
|
||||||
const rootLogger = require('../../services/logger')
|
const rootLogger = require('../../services/logger')
|
||||||
const { web3Home } = require('../../services/web3')
|
const { web3Home } = require('../../services/web3')
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
const Web3 = require('web3')
|
const Web3 = require('web3')
|
||||||
const { HttpListProviderError } = require('http-list-provider')
|
const { HttpListProviderError } = require('../../services/HttpListProvider')
|
||||||
const { AlreadyProcessedError, IncompatibleContractError, InvalidValidatorError } = require('../../utils/errors')
|
const { AlreadyProcessedError, IncompatibleContractError, InvalidValidatorError } = require('../../utils/errors')
|
||||||
const { parseMessage } = require('../../utils/message')
|
const { parseMessage } = require('../../utils/message')
|
||||||
const logger = require('../../services/logger').child({
|
const logger = require('../../services/logger').child({
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
require('../../../env')
|
require('../../../env')
|
||||||
const promiseLimit = require('promise-limit')
|
const promiseLimit = require('promise-limit')
|
||||||
const { HttpListProviderError } = require('http-list-provider')
|
const { HttpListProviderError } = require('../../services/HttpListProvider')
|
||||||
const { BRIDGE_VALIDATORS_ABI } = require('../../../../commons')
|
const { BRIDGE_VALIDATORS_ABI } = require('../../../../commons')
|
||||||
const rootLogger = require('../../services/logger')
|
const rootLogger = require('../../services/logger')
|
||||||
const { web3Home, web3Foreign } = require('../../services/web3')
|
const { web3Home, web3Foreign } = require('../../services/web3')
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const { HttpListProviderError } = require('http-list-provider')
|
const { HttpListProviderError } = require('../../services/HttpListProvider')
|
||||||
const { AlreadyProcessedError, AlreadySignedError, InvalidValidatorError } = require('../../utils/errors')
|
const { AlreadyProcessedError, AlreadySignedError, InvalidValidatorError } = require('../../utils/errors')
|
||||||
const logger = require('../../services/logger').child({
|
const logger = require('../../services/logger').child({
|
||||||
module: 'processSignatureRequests:estimateGas'
|
module: 'processSignatureRequests:estimateGas'
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
require('../../../env')
|
require('../../../env')
|
||||||
const promiseLimit = require('promise-limit')
|
const promiseLimit = require('promise-limit')
|
||||||
const { HttpListProviderError } = require('http-list-provider')
|
const { HttpListProviderError } = require('../../services/HttpListProvider')
|
||||||
const { BRIDGE_VALIDATORS_ABI } = require('../../../../commons')
|
const { BRIDGE_VALIDATORS_ABI } = require('../../../../commons')
|
||||||
const rootLogger = require('../../services/logger')
|
const rootLogger = require('../../services/logger')
|
||||||
const { web3Home } = require('../../services/web3')
|
const { web3Home } = require('../../services/web3')
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
require('../../../env')
|
require('../../../env')
|
||||||
const promiseLimit = require('promise-limit')
|
const promiseLimit = require('promise-limit')
|
||||||
const { HttpListProviderError } = require('http-list-provider')
|
const { HttpListProviderError } = require('../../services/HttpListProvider')
|
||||||
const { BRIDGE_VALIDATORS_ABI, ZERO_ADDRESS } = require('../../../../commons')
|
const { BRIDGE_VALIDATORS_ABI, ZERO_ADDRESS } = require('../../../../commons')
|
||||||
const rootLogger = require('../../services/logger')
|
const rootLogger = require('../../services/logger')
|
||||||
const { web3Home, web3Foreign } = require('../../services/web3')
|
const { web3Home, web3Foreign } = require('../../services/web3')
|
||||||
|
@ -4,7 +4,6 @@ const { connectSenderToQueue } = require('./services/amqpClient')
|
|||||||
const { redis } = require('./services/redisClient')
|
const { redis } = require('./services/redisClient')
|
||||||
const GasPrice = require('./services/gasPrice')
|
const GasPrice = require('./services/gasPrice')
|
||||||
const logger = require('./services/logger')
|
const logger = require('./services/logger')
|
||||||
const rpcUrlsManager = require('./services/getRpcUrlsManager')
|
|
||||||
const { sendTx } = require('./tx/sendTx')
|
const { sendTx } = require('./tx/sendTx')
|
||||||
const { getNonce, getChainId } = require('./tx/web3')
|
const { getNonce, getChainId } = require('./tx/web3')
|
||||||
const {
|
const {
|
||||||
@ -18,7 +17,7 @@ const {
|
|||||||
} = require('./utils/utils')
|
} = require('./utils/utils')
|
||||||
const { EXIT_CODES, EXTRA_GAS_PERCENTAGE, MAX_GAS_LIMIT } = require('./utils/constants')
|
const { EXIT_CODES, EXTRA_GAS_PERCENTAGE, MAX_GAS_LIMIT } = require('./utils/constants')
|
||||||
|
|
||||||
const { ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY } = process.env
|
const { ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY, ORACLE_TX_REDUNDANCY } = process.env
|
||||||
|
|
||||||
const ORACLE_VALIDATOR_ADDRESS = privateKeyToAddress(ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY)
|
const ORACLE_VALIDATOR_ADDRESS = privateKeyToAddress(ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY)
|
||||||
|
|
||||||
@ -30,6 +29,7 @@ if (process.argv.length < 3) {
|
|||||||
const config = require(path.join('../config/', process.argv[2]))
|
const config = require(path.join('../config/', process.argv[2]))
|
||||||
|
|
||||||
const web3Instance = config.web3
|
const web3Instance = config.web3
|
||||||
|
const web3Redundant = ORACLE_TX_REDUNDANCY === 'true' ? config.web3Redundant : config.web3
|
||||||
const nonceKey = `${config.id}:nonce`
|
const nonceKey = `${config.id}:nonce`
|
||||||
let chainId = 0
|
let chainId = 0
|
||||||
|
|
||||||
@ -37,12 +37,11 @@ async function initialize() {
|
|||||||
try {
|
try {
|
||||||
const checkHttps = checkHTTPS(process.env.ORACLE_ALLOW_HTTP_FOR_RPC, logger)
|
const checkHttps = checkHTTPS(process.env.ORACLE_ALLOW_HTTP_FOR_RPC, logger)
|
||||||
|
|
||||||
rpcUrlsManager.homeUrls.forEach(checkHttps('home'))
|
web3Instance.currentProvider.urls.forEach(checkHttps(config.chain))
|
||||||
rpcUrlsManager.foreignUrls.forEach(checkHttps('foreign'))
|
|
||||||
|
|
||||||
GasPrice.start(config.id)
|
GasPrice.start(config.id)
|
||||||
|
|
||||||
chainId = await getChainId(config.id)
|
chainId = await getChainId(web3Instance)
|
||||||
connectSenderToQueue({
|
connectSenderToQueue({
|
||||||
queueName: config.queue,
|
queueName: config.queue,
|
||||||
oldQueueName: config.oldQueue,
|
oldQueueName: config.oldQueue,
|
||||||
@ -144,7 +143,6 @@ async function main({ msg, ackMsg, nackMsg, channel, scheduleForRetry, scheduleT
|
|||||||
}
|
}
|
||||||
logger.info(`Sending transaction with nonce ${nonce}`)
|
logger.info(`Sending transaction with nonce ${nonce}`)
|
||||||
const txHash = await sendTx({
|
const txHash = await sendTx({
|
||||||
chain: config.id,
|
|
||||||
data: job.data,
|
data: job.data,
|
||||||
nonce,
|
nonce,
|
||||||
gasPrice,
|
gasPrice,
|
||||||
@ -153,7 +151,7 @@ async function main({ msg, ackMsg, nackMsg, channel, scheduleForRetry, scheduleT
|
|||||||
privateKey: ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY,
|
privateKey: ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY,
|
||||||
to: job.to,
|
to: job.to,
|
||||||
chainId,
|
chainId,
|
||||||
web3: web3Instance
|
web3: web3Redundant
|
||||||
})
|
})
|
||||||
const resendJob = {
|
const resendJob = {
|
||||||
...job,
|
...job,
|
||||||
|
89
oracle/src/services/HttpListProvider.js
Normal file
89
oracle/src/services/HttpListProvider.js
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
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
|
||||||
|
}
|
40
oracle/src/services/RedundantHttpListProvider.js
Normal file
40
oracle/src/services/RedundantHttpListProvider.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
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
|
||||||
|
}
|
@ -1,50 +0,0 @@
|
|||||||
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
|
|
@ -1,3 +0,0 @@
|
|||||||
const RpcUrlsManager = require('./RpcUrlsManager')
|
|
||||||
|
|
||||||
module.exports = new RpcUrlsManager(process.env.COMMON_HOME_RPC_URL, process.env.COMMON_FOREIGN_RPC_URL)
|
|
@ -1,19 +1,55 @@
|
|||||||
const HttpListProvider = require('http-list-provider')
|
|
||||||
const Web3 = require('web3')
|
const Web3 = require('web3')
|
||||||
const rpcUrlsManager = require('./getRpcUrlsManager')
|
const { HttpListProvider } = require('./HttpListProvider')
|
||||||
|
const { RedundantHttpListProvider } = require('./RedundantHttpListProvider')
|
||||||
const { RETRY_CONFIG } = require('../utils/constants')
|
const { RETRY_CONFIG } = require('../utils/constants')
|
||||||
|
|
||||||
const homeProvider = new HttpListProvider(rpcUrlsManager.homeUrls, {
|
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,
|
||||||
retry: RETRY_CONFIG
|
retry: RETRY_CONFIG
|
||||||
})
|
}
|
||||||
|
|
||||||
|
const foreignOptions = {
|
||||||
|
requestTimeout: configuredTimeout || foreignDefaultTimeout,
|
||||||
|
retry: RETRY_CONFIG
|
||||||
|
}
|
||||||
|
|
||||||
|
const homeProvider = new HttpListProvider(homeUrls, homeOptions)
|
||||||
const web3Home = new Web3(homeProvider)
|
const web3Home = new Web3(homeProvider)
|
||||||
|
|
||||||
const foreignProvider = new HttpListProvider(rpcUrlsManager.foreignUrls, {
|
const foreignProvider = new HttpListProvider(foreignUrls, foreignOptions)
|
||||||
retry: RETRY_CONFIG
|
|
||||||
})
|
|
||||||
const web3Foreign = new Web3(foreignProvider)
|
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 = {
|
module.exports = {
|
||||||
web3Home,
|
web3Home,
|
||||||
web3Foreign
|
web3Foreign,
|
||||||
|
web3HomeRedundant,
|
||||||
|
web3ForeignRedundant
|
||||||
}
|
}
|
||||||
|
@ -1,67 +1,27 @@
|
|||||||
const Web3Utils = require('web3-utils')
|
const { toWei } = require('web3').utils
|
||||||
const fetch = require('node-fetch')
|
|
||||||
const rpcUrlsManager = require('../services/getRpcUrlsManager')
|
|
||||||
|
|
||||||
const { ORACLE_TX_REDUNDANCY } = process.env
|
async function sendTx({ privateKey, data, nonce, gasPrice, amount, gasLimit, to, chainId, web3 }) {
|
||||||
|
|
||||||
// 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(
|
const serializedTx = await web3.eth.accounts.signTransaction(
|
||||||
{
|
{
|
||||||
nonce: Number(nonce),
|
nonce: Number(nonce),
|
||||||
chainId,
|
chainId,
|
||||||
to,
|
to,
|
||||||
data,
|
data,
|
||||||
value: Web3Utils.toWei(amount),
|
value: toWei(amount),
|
||||||
gasPrice,
|
gasPrice,
|
||||||
gas: gasLimit
|
gas: gasLimit
|
||||||
},
|
},
|
||||||
`0x${privateKey}`
|
`0x${privateKey}`
|
||||||
)
|
)
|
||||||
|
|
||||||
return sendRawTx({
|
return new Promise((res, rej) =>
|
||||||
chain,
|
web3.eth
|
||||||
method: 'eth_sendRawTransaction',
|
.sendSignedTransaction(serializedTx.rawTransaction)
|
||||||
params: [serializedTx.rawTransaction]
|
.once('transactionHash', res)
|
||||||
})
|
.once('error', rej)
|
||||||
}
|
|
||||||
|
|
||||||
// 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 = {
|
module.exports = {
|
||||||
sendTx,
|
sendTx
|
||||||
sendRawTx
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
const { hexToNumber } = require('web3-utils')
|
|
||||||
const logger = require('../services/logger').child({
|
const logger = require('../services/logger').child({
|
||||||
module: 'web3'
|
module: 'web3'
|
||||||
})
|
})
|
||||||
const { sendRawTx } = require('./sendTx')
|
|
||||||
|
|
||||||
async function getNonce(web3, address) {
|
async function getNonce(web3, address) {
|
||||||
try {
|
try {
|
||||||
@ -26,15 +24,10 @@ async function getBlockNumber(web3) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getChainId(chain) {
|
async function getChainId(web3) {
|
||||||
try {
|
try {
|
||||||
logger.debug('Getting chain id')
|
logger.debug('Getting chain id')
|
||||||
const chainIdHex = await sendRawTx({
|
const chainId = await web3.eth.getChainId()
|
||||||
chain,
|
|
||||||
method: 'eth_chainId',
|
|
||||||
params: []
|
|
||||||
})
|
|
||||||
const chainId = hexToNumber(chainIdHex)
|
|
||||||
logger.debug({ chainId }, 'Chain id obtained')
|
logger.debug({ chainId }, 'Chain id obtained')
|
||||||
return chainId
|
return chainId
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const Web3Utils = require('web3-utils')
|
const { toHex, numberToHex, padLeft } = require('web3').utils
|
||||||
const { strip0x } = require('../../../commons')
|
const { strip0x } = require('../../../commons')
|
||||||
|
|
||||||
function createMessage({ recipient, value, transactionHash, bridgeAddress, expectedMessageLength }) {
|
function createMessage({ recipient, value, transactionHash, bridgeAddress, expectedMessageLength }) {
|
||||||
recipient = strip0x(recipient)
|
recipient = strip0x(recipient)
|
||||||
assert.strictEqual(recipient.length, 20 * 2)
|
assert.strictEqual(recipient.length, 20 * 2)
|
||||||
|
|
||||||
value = Web3Utils.numberToHex(value)
|
value = numberToHex(value)
|
||||||
value = Web3Utils.padLeft(value, 32 * 2)
|
value = padLeft(value, 32 * 2)
|
||||||
|
|
||||||
value = strip0x(value)
|
value = strip0x(value)
|
||||||
assert.strictEqual(value.length, 64)
|
assert.strictEqual(value.length, 64)
|
||||||
@ -60,7 +60,7 @@ function signatureToVRS(rawSignature) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function packSignatures(array) {
|
function packSignatures(array) {
|
||||||
const length = strip0x(Web3Utils.toHex(array.length))
|
const length = strip0x(toHex(array.length))
|
||||||
const msgLength = length.length === 1 ? `0${length}` : length
|
const msgLength = length.length === 1 ? `0${length}` : length
|
||||||
let v = ''
|
let v = ''
|
||||||
let r = ''
|
let r = ''
|
||||||
|
@ -118,7 +118,10 @@ async function readAccessListFile(fileName, logger) {
|
|||||||
.split('\n')
|
.split('\n')
|
||||||
.map(addr => addr.trim().toLowerCase())
|
.map(addr => addr.trim().toLowerCase())
|
||||||
.filter(addr => addr.length === 42)
|
.filter(addr => addr.length === 42)
|
||||||
logger.info({ fileName }, `Access list was read successfully, ${data.length} addresses found`)
|
logger.info(
|
||||||
|
{ fileName },
|
||||||
|
`Access list was read successfully, ${readAccessLists[fileName].length} addresses found`
|
||||||
|
)
|
||||||
logger.debug({ addresses: readAccessLists[fileName] }, `Read addresses from the file`)
|
logger.debug({ addresses: readAccessLists[fileName] }, `Read addresses from the file`)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
readAccessLists[fileName] = []
|
readAccessLists[fileName] = []
|
||||||
|
@ -5,7 +5,6 @@ const { connectWatcherToQueue, connection } = require('./services/amqpClient')
|
|||||||
const { getBlockNumber } = require('./tx/web3')
|
const { getBlockNumber } = require('./tx/web3')
|
||||||
const { redis } = require('./services/redisClient')
|
const { redis } = require('./services/redisClient')
|
||||||
const logger = require('./services/logger')
|
const logger = require('./services/logger')
|
||||||
const rpcUrlsManager = require('./services/getRpcUrlsManager')
|
|
||||||
const { getRequiredBlockConfirmations, getEvents } = require('./tx/web3')
|
const { getRequiredBlockConfirmations, getEvents } = require('./tx/web3')
|
||||||
const { checkHTTPS, watchdog } = require('./utils/utils')
|
const { checkHTTPS, watchdog } = require('./utils/utils')
|
||||||
const { EXIT_CODES } = require('./utils/constants')
|
const { EXIT_CODES } = require('./utils/constants')
|
||||||
@ -42,8 +41,7 @@ async function initialize() {
|
|||||||
try {
|
try {
|
||||||
const checkHttps = checkHTTPS(process.env.ORACLE_ALLOW_HTTP_FOR_RPC, logger)
|
const checkHttps = checkHTTPS(process.env.ORACLE_ALLOW_HTTP_FOR_RPC, logger)
|
||||||
|
|
||||||
rpcUrlsManager.homeUrls.forEach(checkHttps('home'))
|
web3Instance.currentProvider.urls.forEach(checkHttps(config.chain))
|
||||||
rpcUrlsManager.foreignUrls.forEach(checkHttps('foreign'))
|
|
||||||
|
|
||||||
await getLastProcessedBlock()
|
await getLastProcessedBlock()
|
||||||
connectWatcherToQueue({
|
connectWatcherToQueue({
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
const path = require('path')
|
const path = require('path')
|
||||||
const logger = require('./services/logger')
|
const logger = require('./services/logger')
|
||||||
const rpcUrlsManager = require('./services/getRpcUrlsManager')
|
|
||||||
const { checkHTTPS, watchdog } = require('./utils/utils')
|
const { checkHTTPS, watchdog } = require('./utils/utils')
|
||||||
const { EXIT_CODES } = require('./utils/constants')
|
const { EXIT_CODES } = require('./utils/constants')
|
||||||
const { connectWorkerToQueue } = require('./services/amqpClient')
|
const { connectWorkerToQueue } = require('./services/amqpClient')
|
||||||
@ -9,12 +8,13 @@ const config = require(path.join('../config/', process.argv[2]))
|
|||||||
|
|
||||||
const convertToChai = require('./workers/convertToChai')(config)
|
const convertToChai = require('./workers/convertToChai')(config)
|
||||||
|
|
||||||
|
const web3Instance = config.web3
|
||||||
|
|
||||||
async function initialize() {
|
async function initialize() {
|
||||||
try {
|
try {
|
||||||
const checkHttps = checkHTTPS(process.env.ORACLE_ALLOW_HTTP_FOR_RPC, logger)
|
const checkHttps = checkHTTPS(process.env.ORACLE_ALLOW_HTTP_FOR_RPC, logger)
|
||||||
|
|
||||||
rpcUrlsManager.homeUrls.forEach(checkHttps('home'))
|
web3Instance.currentProvider.urls.forEach(checkHttps(config.chain))
|
||||||
rpcUrlsManager.foreignUrls.forEach(checkHttps('foreign'))
|
|
||||||
|
|
||||||
connectWorkerToQueue({
|
connectWorkerToQueue({
|
||||||
queueName: config.workerQueue,
|
queueName: config.workerQueue,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
require('../../env')
|
require('../../env')
|
||||||
const { HttpListProviderError } = require('http-list-provider')
|
const { HttpListProviderError } = require('../services/HttpListProvider')
|
||||||
const rootLogger = require('../services/logger')
|
const rootLogger = require('../services/logger')
|
||||||
const { web3Foreign } = require('../services/web3')
|
const { web3Foreign } = require('../services/web3')
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ const chai = require('chai')
|
|||||||
const chaiAsPromised = require('chai-as-promised')
|
const chaiAsPromised = require('chai-as-promised')
|
||||||
const sinon = require('sinon')
|
const sinon = require('sinon')
|
||||||
const Web3 = require('web3')
|
const Web3 = require('web3')
|
||||||
const { HttpListProviderError } = require('http-list-provider')
|
const { HttpListProviderError } = require('../src/services/HttpListProvider')
|
||||||
const estimateGas = require('../src/events/processAffirmationRequests/estimateGas')
|
const estimateGas = require('../src/events/processAffirmationRequests/estimateGas')
|
||||||
const errors = require('../src/utils/errors')
|
const errors = require('../src/utils/errors')
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const { expect } = require('chai').use(require('chai-as-promised'))
|
const { expect } = require('chai').use(require('chai-as-promised'))
|
||||||
const sinon = require('sinon')
|
const sinon = require('sinon')
|
||||||
const Web3 = require('web3')
|
const Web3 = require('web3')
|
||||||
const { HttpListProviderError } = require('http-list-provider')
|
const { HttpListProviderError } = require('../src/services/HttpListProvider')
|
||||||
const { createMessage, signatureToVRS } = require('../src/utils/message')
|
const { createMessage, signatureToVRS } = require('../src/utils/message')
|
||||||
const estimateGas = require('../src/events/processCollectedSignatures/estimateGas')
|
const estimateGas = require('../src/events/processCollectedSignatures/estimateGas')
|
||||||
const errors = require('../src/utils/errors')
|
const errors = require('../src/utils/errors')
|
||||||
|
@ -2,7 +2,7 @@ const chai = require('chai')
|
|||||||
const chaiAsPromised = require('chai-as-promised')
|
const chaiAsPromised = require('chai-as-promised')
|
||||||
const sinon = require('sinon')
|
const sinon = require('sinon')
|
||||||
const Web3 = require('web3')
|
const Web3 = require('web3')
|
||||||
const { HttpListProviderError } = require('http-list-provider')
|
const { HttpListProviderError } = require('../src/services/HttpListProvider')
|
||||||
const estimateGas = require('../src/events/processSignatureRequests/estimateGas')
|
const estimateGas = require('../src/events/processSignatureRequests/estimateGas')
|
||||||
const errors = require('../src/utils/errors')
|
const errors = require('../src/utils/errors')
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
"build:ui": "yarn workspace ui run build",
|
"build:ui": "yarn workspace ui run build",
|
||||||
"build:alm": "yarn workspace alm run build",
|
"build:alm": "yarn workspace alm run build",
|
||||||
"build:plugin": "yarn workspace burner-wallet-plugin run build",
|
"build:plugin": "yarn workspace burner-wallet-plugin run build",
|
||||||
"lint": "yarn wsrun --exclude token-bridge-contracts lint",
|
"lint": "yarn wsrun --exclude tokenbridge-contracts lint",
|
||||||
"test": "yarn wsrun --exclude oracle-e2e --exclude ui-e2e --exclude monitor-e2e --exclude alm-e2e test",
|
"test": "yarn wsrun --exclude oracle-e2e --exclude ui-e2e --exclude monitor-e2e --exclude alm-e2e test",
|
||||||
"oracle-e2e": "./oracle-e2e/run-tests.sh",
|
"oracle-e2e": "./oracle-e2e/run-tests.sh",
|
||||||
"ui-e2e": "./ui-e2e/run-tests.sh",
|
"ui-e2e": "./ui-e2e/run-tests.sh",
|
||||||
@ -47,7 +47,7 @@
|
|||||||
"monitor-e2e": "./monitor-e2e/run-tests.sh",
|
"monitor-e2e": "./monitor-e2e/run-tests.sh",
|
||||||
"alm-e2e": "./alm-e2e/run-tests.sh",
|
"alm-e2e": "./alm-e2e/run-tests.sh",
|
||||||
"clean": "rm -rf ./node_modules ./**/node_modules ./**/**/node_modules ./**/build ./**/**/dist",
|
"clean": "rm -rf ./node_modules ./**/node_modules ./**/**/node_modules ./**/build ./**/**/dist",
|
||||||
"compile:contracts": "yarn workspace token-bridge-contracts run compile",
|
"compile:contracts": "yarn workspace tokenbridge-contracts run compile",
|
||||||
"install:deploy": "cd contracts/deploy && npm install --unsafe-perm --silent",
|
"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"
|
"postinstall": "test -n \"$NOYARNPOSTINSTALL\" || ln -sf $(pwd)/node_modules/openzeppelin-solidity/ contracts/node_modules/openzeppelin-solidity"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user