Merge the develop branch to the master branch, preparation to v3.0.0-rc0

This merge contains the following set of changes:
  * [Oracle, Improvement] Oracle watcher for AMB async calls (#509), 
  * [Common, Other] Update the contract's submodule to the release 6.0.0-rc0 (#562)
This commit is contained in:
Alexander Kolotov 2021-05-09 07:59:36 -06:00 committed by GitHub
commit 3b959776f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
140 changed files with 9177 additions and 3982 deletions

@ -15,7 +15,7 @@ jobs:
steps: steps:
- uses: actions/setup-node@v1 - uses: actions/setup-node@v1
with: with:
node-version: 10 node-version: 12
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
submodules: true submodules: true
@ -48,7 +48,7 @@ jobs:
steps: steps:
- uses: actions/setup-node@v1 - uses: actions/setup-node@v1
with: with:
node-version: 10 node-version: 12
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
submodules: true submodules: true
@ -70,7 +70,7 @@ jobs:
- name: Evaluate e2e docker images tags - name: Evaluate e2e docker images tags
run: | run: |
git submodule status > submodule.status git submodule status > submodule.status
echo "E2E_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}" >> $GITHUB_ENV echo "E2E_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e', 'e2e-commons') }}" >> $GITHUB_ENV
echo "ORACLE_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}" >> $GITHUB_ENV echo "ORACLE_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}" >> $GITHUB_ENV
echo "MONITOR_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}" >> $GITHUB_ENV echo "MONITOR_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}" >> $GITHUB_ENV
echo "ALM_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}" >> $GITHUB_ENV echo "ALM_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}" >> $GITHUB_ENV
@ -81,8 +81,8 @@ jobs:
} }
updated=() updated=()
if ! check_if_image_exists e2e ${E2E_TAG}; then updated+=("e2e"); fi if ! check_if_image_exists e2e ${E2E_TAG}; then updated+=("e2e"); fi
if ! check_if_image_exists oracle ${ORACLE_TAG}; then updated+=("oracle"); fi if ! check_if_image_exists oracle ${ORACLE_TAG}; then updated+=("oracle-amb"); fi
if ! check_if_image_exists monitor ${MONITOR_TAG}; then updated+=("monitor"); fi if ! check_if_image_exists monitor ${MONITOR_TAG}; then updated+=("monitor-amb"); fi
if ! check_if_image_exists alm ${ALM_TAG}; then updated+=("alm"); fi if ! check_if_image_exists alm ${ALM_TAG}; then updated+=("alm"); fi
if [ ${#updated[@]} -gt 0 ]; then if [ ${#updated[@]} -gt 0 ]; then
echo "Updated services: ${updated[@]}" echo "Updated services: ${updated[@]}"
@ -133,7 +133,7 @@ jobs:
- name: Evaluate e2e docker images tags - name: Evaluate e2e docker images tags
run: | run: |
git submodule status > submodule.status git submodule status > submodule.status
echo "E2E_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}" >> $GITHUB_ENV echo "E2E_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e', 'e2e-commons') }}" >> $GITHUB_ENV
echo "ORACLE_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}" >> $GITHUB_ENV echo "ORACLE_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}" >> $GITHUB_ENV
echo "MONITOR_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}" >> $GITHUB_ENV echo "MONITOR_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}" >> $GITHUB_ENV
echo "ALM_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}" >> $GITHUB_ENV echo "ALM_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}" >> $GITHUB_ENV
@ -176,7 +176,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
task: [amb, erc-to-erc, erc-to-native, native-to-erc] task: [amb, erc-to-native]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
@ -184,7 +184,7 @@ jobs:
- name: Evaluate e2e docker images tags - name: Evaluate e2e docker images tags
run: | run: |
git submodule status > submodule.status git submodule status > submodule.status
echo "E2E_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}" >> $GITHUB_ENV echo "E2E_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e', 'e2e-commons') }}" >> $GITHUB_ENV
echo "ORACLE_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}" >> $GITHUB_ENV echo "ORACLE_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}" >> $GITHUB_ENV
echo "MONITOR_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}" >> $GITHUB_ENV echo "MONITOR_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}" >> $GITHUB_ENV
echo "ALM_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}" >> $GITHUB_ENV echo "ALM_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}" >> $GITHUB_ENV
@ -202,7 +202,7 @@ jobs:
run: ${{ steps.cache-repo.outputs.cache-hit }} && e2e-commons/up.sh deploy blocks run: ${{ steps.cache-repo.outputs.cache-hit }} && e2e-commons/up.sh deploy blocks
- name: Pull e2e oracle image - name: Pull e2e oracle image
run: | run: |
docker-compose -f ./e2e-commons/docker-compose.yml pull oracle docker-compose -f ./e2e-commons/docker-compose.yml pull oracle-amb
docker tag ${DOCKER_IMAGE_BASE}/tokenbridge-e2e-oracle:${ORACLE_TAG} poanetwork/tokenbridge-oracle:latest docker tag ${DOCKER_IMAGE_BASE}/tokenbridge-e2e-oracle:${ORACLE_TAG} poanetwork/tokenbridge-oracle:latest
- name: Deploy oracle - name: Deploy oracle
run: deployment-e2e/molecule.sh ultimate-${{ matrix.task }} run: deployment-e2e/molecule.sh ultimate-${{ matrix.task }}

2
.nvmrc

@ -1 +1 @@
10.22 12.22

@ -22,7 +22,7 @@ COMMON_FOREIGN_GAS_PRICE_FACTOR | A value that will multiply the gas price of th
name | description | value name | description | value
--- | --- | --- --- | --- | ---
ORACLE_BRIDGE_MODE | The bridge mode. The bridge starts listening to a different set of events based on this parameter. | NATIVE_TO_ERC / ERC_TO_ERC / ERC_TO_NATIVE / ARBITRARY_MESSAGE ORACLE_BRIDGE_MODE | The bridge mode. The bridge starts listening to a different set of events based on this parameter. | ERC_TO_NATIVE / ARBITRARY_MESSAGE
ORACLE_ALLOW_HTTP_FOR_RPC | **Only use in test environments - must be omitted in production environments.**. If this parameter is specified and set to `yes`, RPC URLs can be specified in form of HTTP links. A warning that the connection is insecure will be written to the logs. | `yes` / `no` ORACLE_ALLOW_HTTP_FOR_RPC | **Only use in test environments - must be omitted in production environments.**. If this parameter is specified and set to `yes`, RPC URLs can be specified in form of HTTP links. A warning that the connection is insecure will be written to the logs. | `yes` / `no`
ORACLE_HOME_RPC_POLLING_INTERVAL | The interval in milliseconds used to request the RPC node in the Home network for new blocks. The interval should match the average production time for a new block. | integer ORACLE_HOME_RPC_POLLING_INTERVAL | The interval in milliseconds used to request the RPC node in the Home network for new blocks. The interval should match the average production time for a new block. | integer
ORACLE_FOREIGN_RPC_POLLING_INTERVAL | The interval in milliseconds used to request the RPC node in the Foreign network for new blocks. The interval should match the average production time for a new block. | integer ORACLE_FOREIGN_RPC_POLLING_INTERVAL | The interval in milliseconds used to request the RPC node in the Foreign network for new blocks. The interval should match the average production time for a new block. | integer
@ -47,6 +47,7 @@ ORACLE_FOREIGN_TX_RESEND_INTERVAL | Interval in milliseconds for automatic resen
ORACLE_SHUTDOWN_SERVICE_URL | Optional external URL to some other service/monitor/configuration manager that controls the remote shutdown process. GET request should return `application/json` message with the following schema: `{ shutdown: true/false }`. | URL ORACLE_SHUTDOWN_SERVICE_URL | Optional external URL to some other service/monitor/configuration manager that controls the remote shutdown process. GET request should return `application/json` message with the following schema: `{ shutdown: true/false }`. | URL
ORACLE_SHUTDOWN_SERVICE_POLLING_INTERVAL | Optional interval in milliseconds used to request the side RPC node or external shutdown service. Default is 120000. | integer ORACLE_SHUTDOWN_SERVICE_POLLING_INTERVAL | Optional interval in milliseconds used to request the side RPC node or external shutdown service. Default is 120000. | integer
ORACLE_SIDE_RPC_URL | Optional HTTPS URL(s) for communication with the external shutdown service or side RPC nodes, used for shutdown manager activities. Several URLs can be specified, delimited by spaces. If the connection to one of these nodes is lost the next URL is used for connection. | URL(s) ORACLE_SIDE_RPC_URL | Optional HTTPS URL(s) for communication with the external shutdown service or side RPC nodes, used for shutdown manager activities. Several URLs can be specified, delimited by spaces. If the connection to one of these nodes is lost the next URL is used for connection. | URL(s)
ORACLE_FOREIGN_ARCHIVE_RPC_URL | Optional HTTPS URL(s) for communication with the archive nodes on the foreign network. Only used in AMB bridge mode for async information request processing. Several URLs can be specified, delimited by spaces. If the connection to one of these nodes is lost the next URL is used for connection. | URL(s)
ORACLE_SHUTDOWN_CONTRACT_ADDRESS | Optional contract address in the side chain accessible through `ORACLE_SIDE_RPC_URL`, where the method passed in `ORACLE_SHUTDOWN_CONTRACT_METHOD` is implemented. | `address` ORACLE_SHUTDOWN_CONTRACT_ADDRESS | Optional contract address in the side chain accessible through `ORACLE_SIDE_RPC_URL`, where the method passed in `ORACLE_SHUTDOWN_CONTRACT_METHOD` is implemented. | `address`
ORACLE_SHUTDOWN_CONTRACT_METHOD | Method signature to be used in the side chain to identify the current shutdown status. Method should return boolean. Default value is `isShutdown()`. | `function signature` ORACLE_SHUTDOWN_CONTRACT_METHOD | Method signature to be used in the side chain to identify the current shutdown status. Method should return boolean. Default value is `isShutdown()`. | `function signature`
ORACLE_FOREIGN_RPC_BLOCK_POLLING_LIMIT | Max length for the block range used in `eth_getLogs` requests for polling contract events for the Foreign chain. Infinite, if not provided. | `integer` ORACLE_FOREIGN_RPC_BLOCK_POLLING_LIMIT | Max length for the block range used in `eth_getLogs` requests for polling contract events for the Foreign chain. Infinite, if not provided. | `integer`

@ -1,4 +1,4 @@
FROM node:10 as contracts FROM node:12 as contracts
WORKDIR /mono WORKDIR /mono
@ -11,7 +11,7 @@ COPY ./contracts/truffle-config.js ./
COPY ./contracts/contracts ./contracts COPY ./contracts/contracts ./contracts
RUN npm run compile RUN npm run compile
FROM node:10 FROM node:12
WORKDIR /mono WORKDIR /mono
COPY package.json . COPY package.json .

@ -54,8 +54,6 @@ Additionally there are [Smart Contracts](https://github.com/poanetwork/tokenbrid
The POA TokenBridge provides four operational modes: The POA TokenBridge provides four operational modes:
- [x] `Native-to-ERC20` **Coins** on a Home network can be converted to ERC20-compatible **tokens** on a Foreign network. Coins are locked on the Home side and the corresponding amount of ERC20 tokens are minted on the Foreign side. When the operation is reversed, tokens are burnt on the Foreign side and unlocked in the Home network. **More Information: [POA-to-POA20 Bridge](https://medium.com/poa-network/introducing-poa-bridge-and-poa20-55d8b78058ac)**
- [x] `ERC20-to-ERC20` ERC20-compatible tokens on the Foreign network are locked and minted as ERC20-compatible tokens (ERC677 tokens) on the Home network. When transferred from Home to Foreign, they are burnt on the Home side and unlocked in the Foreign network. This can be considered a form of atomic swap when a user swaps the token "X" in network "A" to the token "Y" in network "B". **More Information: [ERC20-to-ERC20](https://medium.com/poa-network/introducing-the-erc20-to-erc20-tokenbridge-ce266cc1a2d0)**
- [x] `ERC20-to-Native`: Pre-existing **tokens** in the Foreign network are locked and **coins** are minted in the `Home` network. In this mode, the Home network consensus engine invokes [Parity's Block Reward contract](https://wiki.parity.io/Block-Reward-Contract.html) to mint coins per the bridge contract request. **More Information: [xDai Chain](https://medium.com/poa-network/poa-network-partners-with-makerdao-on-xdai-chain-the-first-ever-usd-stable-blockchain-65a078c41e6a)** - [x] `ERC20-to-Native`: Pre-existing **tokens** in the Foreign network are locked and **coins** are minted in the `Home` network. In this mode, the Home network consensus engine invokes [Parity's Block Reward contract](https://wiki.parity.io/Block-Reward-Contract.html) to mint coins per the bridge contract request. **More Information: [xDai Chain](https://medium.com/poa-network/poa-network-partners-with-makerdao-on-xdai-chain-the-first-ever-usd-stable-blockchain-65a078c41e6a)**
- [x] `Arbitrary-Message`: Transfer arbitrary data between two networks as so the data could be interpreted as an arbitrary contract method invocation. - [x] `Arbitrary-Message`: Transfer arbitrary data between two networks as so the data could be interpreted as an arbitrary contract method invocation.

@ -19,6 +19,6 @@
"eslint-plugin-jest": "^23.18.0" "eslint-plugin-jest": "^23.18.0"
}, },
"engines": { "engines": {
"node": ">= 10.18" "node": ">= 12.22"
} }
} }

@ -6,8 +6,8 @@ jest.setTimeout(60000)
const statusText = 'Success' const statusText = 'Success'
const statusSelector = 'label[data-id="status"]' const statusSelector = 'label[data-id="status"]'
const homeToForeignTxURL = 'http://localhost:3004/77/0x58e7d63368335b9591d4dbb43889084f698fcee93ab7656fd7a39d8c66bc4b60' const homeToForeignTxURL = 'http://localhost:3004/77/0xbc83d43bdc675a615a2b820e43e52d25857aa5fdd77acf2dd92cd247af2c693c'
const foreignToHomeTxURL = 'http://localhost:3004/42/0x592bf28fc896419d2838f71cd0388775814b692688f1ecd5b1519081566b994a' const foreignToHomeTxURL = 'http://localhost:3004/42/0x09dfb947dbd17e27bcc117773b6e133829f7cef9646199a93ef019c4f7c0fec6'
describe('ALM', () => { describe('ALM', () => {
let browser let browser

@ -1,4 +1,4 @@
FROM node:10 as contracts FROM node:12 as contracts
WORKDIR /mono WORKDIR /mono

@ -1,13 +1,7 @@
const HOME_NATIVE_TO_ERC_ABI = require('../contracts/build/contracts/HomeBridgeNativeToErc').abi
const FOREIGN_NATIVE_TO_ERC_ABI = require('../contracts/build/contracts/ForeignBridgeNativeToErc').abi
const HOME_ERC_TO_ERC_ABI = require('../contracts/build/contracts/HomeBridgeErcToErc').abi
const FOREIGN_ERC_TO_ERC_ABI = require('../contracts/build/contracts/ForeignBridgeErc677ToErc677').abi
const HOME_ERC_TO_NATIVE_ABI = require('../contracts/build/contracts/HomeBridgeErcToNative').abi const HOME_ERC_TO_NATIVE_ABI = require('../contracts/build/contracts/HomeBridgeErcToNative').abi
const FOREIGN_ERC_TO_NATIVE_ABI = require('../contracts/build/contracts/ForeignBridgeErcToNative').abi const FOREIGN_ERC_TO_NATIVE_ABI = require('../contracts/build/contracts/ForeignBridgeErcToNative').abi
const ERC20_ABI = require('../contracts/build/contracts/ERC20').abi const ERC20_ABI = require('../contracts/build/contracts/ERC20').abi
const ERC677_ABI = require('../contracts/build/contracts/ERC677').abi const BLOCK_REWARD_ABI = require('../contracts/build/contracts/BlockRewardMock').abi
const ERC677_BRIDGE_TOKEN_ABI = require('../contracts/build/contracts/ERC677BridgeToken').abi
const BLOCK_REWARD_ABI = require('../contracts/build/contracts/BlockReward').abi
const BRIDGE_VALIDATORS_ABI = require('../contracts/build/contracts/BridgeValidators').abi const BRIDGE_VALIDATORS_ABI = require('../contracts/build/contracts/BridgeValidators').abi
const REWARDABLE_VALIDATORS_ABI = require('../contracts/build/contracts/RewardableValidators').abi const REWARDABLE_VALIDATORS_ABI = require('../contracts/build/contracts/RewardableValidators').abi
const HOME_AMB_ABI = require('../contracts/build/contracts/HomeAMB').abi const HOME_AMB_ABI = require('../contracts/build/contracts/HomeAMB').abi
@ -15,43 +9,9 @@ const FOREIGN_AMB_ABI = require('../contracts/build/contracts/ForeignAMB').abi
const BOX_ABI = require('../contracts/build/contracts/Box').abi const BOX_ABI = require('../contracts/build/contracts/Box').abi
const HOME_AMB_ERC_TO_ERC_ABI = require('../contracts/build/contracts/HomeAMBErc677ToErc677').abi const HOME_AMB_ERC_TO_ERC_ABI = require('../contracts/build/contracts/HomeAMBErc677ToErc677').abi
const FOREIGN_AMB_ERC_TO_ERC_ABI = require('../contracts/build/contracts/ForeignAMBErc677ToErc677').abi const FOREIGN_AMB_ERC_TO_ERC_ABI = require('../contracts/build/contracts/ForeignAMBErc677ToErc677').abi
const HOME_STAKE_ERC_TO_ERC_ABI = require('../contracts/build/contracts/HomeStakeTokenMediator').abi
const FOREIGN_STAKE_ERC_TO_ERC_ABI = require('../contracts/build/contracts/ForeignStakeTokenMediator').abi
const { HOME_V1_ABI, FOREIGN_V1_ABI } = require('./v1Abis')
const { BRIDGE_MODES } = require('./constants') const { BRIDGE_MODES } = require('./constants')
const ERC20_BYTES32_ABI = [
{
constant: true,
inputs: [],
name: 'name',
outputs: [
{
name: '',
type: 'bytes32'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
constant: true,
inputs: [],
name: 'symbol',
outputs: [
{
name: '',
type: 'bytes32'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
}
]
const OLD_AMB_USER_REQUEST_FOR_SIGNATURE_ABI = [ const OLD_AMB_USER_REQUEST_FOR_SIGNATURE_ABI = [
{ {
anonymous: false, anonymous: false,
@ -85,27 +45,15 @@ const OLD_AMB_USER_REQUEST_FOR_AFFIRMATION_ABI = [
function getBridgeABIs(bridgeMode) { function getBridgeABIs(bridgeMode) {
let HOME_ABI = null let HOME_ABI = null
let FOREIGN_ABI = null let FOREIGN_ABI = null
if (bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC) { if (bridgeMode === BRIDGE_MODES.ERC_TO_NATIVE) {
HOME_ABI = HOME_NATIVE_TO_ERC_ABI
FOREIGN_ABI = FOREIGN_NATIVE_TO_ERC_ABI
} else if (bridgeMode === BRIDGE_MODES.ERC_TO_ERC) {
HOME_ABI = HOME_ERC_TO_ERC_ABI
FOREIGN_ABI = FOREIGN_ERC_TO_ERC_ABI
} else if (bridgeMode === BRIDGE_MODES.ERC_TO_NATIVE) {
HOME_ABI = HOME_ERC_TO_NATIVE_ABI HOME_ABI = HOME_ERC_TO_NATIVE_ABI
FOREIGN_ABI = FOREIGN_ERC_TO_NATIVE_ABI FOREIGN_ABI = FOREIGN_ERC_TO_NATIVE_ABI
} else if (bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC_V1) {
HOME_ABI = HOME_V1_ABI
FOREIGN_ABI = FOREIGN_V1_ABI
} else if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) { } else if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) {
HOME_ABI = HOME_AMB_ABI HOME_ABI = HOME_AMB_ABI
FOREIGN_ABI = FOREIGN_AMB_ABI FOREIGN_ABI = FOREIGN_AMB_ABI
} else if (bridgeMode === BRIDGE_MODES.AMB_ERC_TO_ERC) { } else if (bridgeMode === BRIDGE_MODES.AMB_ERC_TO_ERC) {
HOME_ABI = HOME_AMB_ERC_TO_ERC_ABI HOME_ABI = HOME_AMB_ERC_TO_ERC_ABI
FOREIGN_ABI = FOREIGN_AMB_ERC_TO_ERC_ABI FOREIGN_ABI = FOREIGN_AMB_ERC_TO_ERC_ABI
} else if (bridgeMode === BRIDGE_MODES.STAKE_AMB_ERC_TO_ERC) {
HOME_ABI = HOME_STAKE_ERC_TO_ERC_ABI
FOREIGN_ABI = FOREIGN_STAKE_ERC_TO_ERC_ABI
} else { } else {
throw new Error(`Unrecognized bridge mode: ${bridgeMode}`) throw new Error(`Unrecognized bridge mode: ${bridgeMode}`)
} }
@ -115,26 +63,15 @@ function getBridgeABIs(bridgeMode) {
module.exports = { module.exports = {
getBridgeABIs, getBridgeABIs,
HOME_NATIVE_TO_ERC_ABI,
FOREIGN_NATIVE_TO_ERC_ABI,
HOME_ERC_TO_ERC_ABI,
FOREIGN_ERC_TO_ERC_ABI,
HOME_ERC_TO_NATIVE_ABI, HOME_ERC_TO_NATIVE_ABI,
FOREIGN_ERC_TO_NATIVE_ABI, FOREIGN_ERC_TO_NATIVE_ABI,
ERC20_ABI, ERC20_ABI,
ERC677_ABI,
ERC677_BRIDGE_TOKEN_ABI,
BLOCK_REWARD_ABI, BLOCK_REWARD_ABI,
BRIDGE_VALIDATORS_ABI, BRIDGE_VALIDATORS_ABI,
REWARDABLE_VALIDATORS_ABI, REWARDABLE_VALIDATORS_ABI,
HOME_V1_ABI,
FOREIGN_V1_ABI,
ERC20_BYTES32_ABI,
HOME_AMB_ABI, HOME_AMB_ABI,
FOREIGN_AMB_ABI, FOREIGN_AMB_ABI,
OLD_AMB_USER_REQUEST_FOR_AFFIRMATION_ABI, OLD_AMB_USER_REQUEST_FOR_AFFIRMATION_ABI,
OLD_AMB_USER_REQUEST_FOR_SIGNATURE_ABI, OLD_AMB_USER_REQUEST_FOR_SIGNATURE_ABI,
BOX_ABI, BOX_ABI
HOME_STAKE_ERC_TO_ERC_ABI,
FOREIGN_STAKE_ERC_TO_ERC_ABI
} }

@ -1,30 +1,12 @@
const BRIDGE_MODES = { const BRIDGE_MODES = {
NATIVE_TO_ERC: 'NATIVE_TO_ERC',
ERC_TO_ERC: 'ERC_TO_ERC',
ERC_TO_NATIVE: 'ERC_TO_NATIVE', ERC_TO_NATIVE: 'ERC_TO_NATIVE',
NATIVE_TO_ERC_V1: 'NATIVE_TO_ERC_V1',
ARBITRARY_MESSAGE: 'ARBITRARY_MESSAGE', ARBITRARY_MESSAGE: 'ARBITRARY_MESSAGE',
AMB_ERC_TO_ERC: 'AMB_ERC_TO_ERC', AMB_ERC_TO_ERC: 'AMB_ERC_TO_ERC'
STAKE_AMB_ERC_TO_ERC: 'STAKE_AMB_ERC_TO_ERC'
}
const ERC_TYPES = {
ERC20: 'ERC20',
ERC677: 'ERC677'
}
const FEE_MANAGER_MODE = {
ONE_DIRECTION: 'ONE_DIRECTION',
BOTH_DIRECTIONS: 'BOTH_DIRECTIONS',
ONE_DIRECTION_STAKE: 'ONE_DIRECTION_STAKE',
UNDEFINED: 'UNDEFINED'
} }
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
module.exports = { module.exports = {
BRIDGE_MODES, BRIDGE_MODES,
ERC_TYPES,
FEE_MANAGER_MODE,
ZERO_ADDRESS ZERO_ADDRESS
} }

@ -9,7 +9,7 @@
}, },
"dependencies": { "dependencies": {
"gas-price-oracle": "^0.1.5", "gas-price-oracle": "^0.1.5",
"web3-utils": "1.0.0-beta.34" "web3-utils": "^1.3.0"
}, },
"devDependencies": { "devDependencies": {
"bn-chai": "^1.0.1", "bn-chai": "^1.0.1",

@ -1,12 +1,8 @@
const { expect } = require('chai') const { expect } = require('chai')
const { BRIDGE_MODES, ERC_TYPES } = require('../constants') const { BRIDGE_MODES } = require('../constants')
describe('constants', () => { describe('constants', () => {
it('should contain correct number of bridge types', () => { it('should contain correct number of bridge types', () => {
expect(Object.keys(BRIDGE_MODES).length).to.be.equal(7) expect(Object.keys(BRIDGE_MODES).length).to.be.equal(3)
})
it('should contain correct number of erc types', () => {
expect(Object.keys(ERC_TYPES).length).to.be.equal(2)
}) })
}) })

@ -1,159 +0,0 @@
const { expect } = require('chai')
const { getTokenType, ERC_TYPES } = require('..')
describe('getTokenType', () => {
it('should return ERC677 if bridgeContract is equal to bridgeAddress', async () => {
// Given
const bridgeAddress = '0xCecBE80Ed3548dE11D7d2D922a36576eA40C4c26'
const contract = {
methods: {
bridgeContract: () => {
return {
call: () => Promise.resolve(bridgeAddress)
}
}
}
}
// When
const type = await getTokenType(contract, bridgeAddress)
// Then
expect(type).to.equal(ERC_TYPES.ERC677)
})
it('should return ERC20 if bridgeContract is not equal to bridgeAddress', async () => {
// Given
const bridgeAddress = '0xCecBE80Ed3548dE11D7d2D922a36576eA40C4c26'
const contract = {
methods: {
bridgeContract: () => {
return {
call: () => Promise.resolve('0xBFCb120F7B1de491262CA4D9D8Eba70438b6896E')
}
}
}
}
// When
const type = await getTokenType(contract, bridgeAddress)
// Then
expect(type).to.equal(ERC_TYPES.ERC20)
})
it('should return ERC20 if bridgeContract is not present', async () => {
// Given
const bridgeAddress = '0xCecBE80Ed3548dE11D7d2D922a36576eA40C4c26'
const contract = {
methods: {
bridgeContract: () => {
return {
call: () => Promise.reject()
}
}
}
}
// When
const type = await getTokenType(contract, bridgeAddress)
// Then
expect(type).to.equal(ERC_TYPES.ERC20)
})
it('should return ERC20 if bridgeContract and isBridge are not present', async () => {
// Given
const bridgeAddress = '0xCecBE80Ed3548dE11D7d2D922a36576eA40C4c26'
const contract = {
methods: {
bridgeContract: () => {
return {
call: () => Promise.reject()
}
},
isBridge: () => {
return {
call: () => Promise.reject()
}
}
}
}
// When
const type = await getTokenType(contract, bridgeAddress)
// Then
expect(type).to.equal(ERC_TYPES.ERC20)
})
it('should return ERC677 if isBridge returns true', async () => {
// Given
const bridgeAddress = '0xCecBE80Ed3548dE11D7d2D922a36576eA40C4c26'
const contract = {
methods: {
bridgeContract: () => {
return {
call: () => Promise.reject()
}
},
isBridge: () => {
return {
call: () => Promise.resolve(true)
}
}
}
}
// When
const type = await getTokenType(contract, bridgeAddress)
// Then
expect(type).to.equal(ERC_TYPES.ERC677)
})
it('should return ERC677 if isBridge returns true and bridgeContract not present', async () => {
// Given
const bridgeAddress = '0xCecBE80Ed3548dE11D7d2D922a36576eA40C4c26'
const contract = {
methods: {
isBridge: () => {
return {
call: () => Promise.resolve(true)
}
}
}
}
// When
const type = await getTokenType(contract, bridgeAddress)
// Then
expect(type).to.equal(ERC_TYPES.ERC677)
})
it('should return ERC20 if isBridge returns false', async () => {
// Given
const bridgeAddress = '0xCecBE80Ed3548dE11D7d2D922a36576eA40C4c26'
const contract = {
methods: {
bridgeContract: () => {
return {
call: () => Promise.reject()
}
},
isBridge: () => {
return {
call: () => Promise.resolve(false)
}
}
}
}
// When
const type = await getTokenType(contract, bridgeAddress)
// Then
expect(type).to.equal(ERC_TYPES.ERC20)
})
})

@ -1,22 +1,16 @@
const { toWei, toBN, BN } = require('web3-utils') const { toWei, toBN, BN } = require('web3-utils')
const { GasPriceOracle } = require('gas-price-oracle') const { GasPriceOracle } = require('gas-price-oracle')
const { BRIDGE_MODES, FEE_MANAGER_MODE, ERC_TYPES } = require('./constants') const { BRIDGE_MODES } = require('./constants')
const { REWARDABLE_VALIDATORS_ABI } = require('./abis') const { REWARDABLE_VALIDATORS_ABI } = require('./abis')
const gasPriceOracle = new GasPriceOracle() const gasPriceOracle = new GasPriceOracle()
function decodeBridgeMode(bridgeModeHash) { function decodeBridgeMode(bridgeModeHash) {
switch (bridgeModeHash) { switch (bridgeModeHash) {
case '0x92a8d7fe':
return BRIDGE_MODES.NATIVE_TO_ERC
case '0xba4690f5':
return BRIDGE_MODES.ERC_TO_ERC
case '0x18762d46': case '0x18762d46':
return BRIDGE_MODES.ERC_TO_NATIVE return BRIDGE_MODES.ERC_TO_NATIVE
case '0x2544fbb9': case '0x2544fbb9':
return BRIDGE_MODES.ARBITRARY_MESSAGE return BRIDGE_MODES.ARBITRARY_MESSAGE
case '0x16ea01e9':
return BRIDGE_MODES.STAKE_AMB_ERC_TO_ERC
case '0x76595b56': case '0x76595b56':
return BRIDGE_MODES.AMB_ERC_TO_ERC return BRIDGE_MODES.AMB_ERC_TO_ERC
default: default:
@ -24,80 +18,9 @@ function decodeBridgeMode(bridgeModeHash) {
} }
} }
const decodeFeeManagerMode = managerModeHash => {
switch (managerModeHash) {
case '0xf2aed8f7':
return FEE_MANAGER_MODE.ONE_DIRECTION
case '0xd7de965f':
return FEE_MANAGER_MODE.BOTH_DIRECTIONS
default:
throw new Error(`Unrecognized fee manager mode hash: '${managerModeHash}'`)
}
}
async function getBridgeMode(contract) { async function getBridgeMode(contract) {
try {
const bridgeModeHash = await contract.methods.getBridgeMode().call() const bridgeModeHash = await contract.methods.getBridgeMode().call()
return decodeBridgeMode(bridgeModeHash) return decodeBridgeMode(bridgeModeHash)
} catch (e) {
return BRIDGE_MODES.NATIVE_TO_ERC_V1
}
}
const getTokenType = async (bridgeTokenContract, bridgeAddress) => {
try {
const resultBridgeAddress = await bridgeTokenContract.methods.bridgeContract().call()
if (resultBridgeAddress === bridgeAddress) {
return ERC_TYPES.ERC677
} else {
return ERC_TYPES.ERC20
}
} catch (e) {
try {
const isBridge = await bridgeTokenContract.methods.isBridge(bridgeAddress).call()
if (isBridge) {
return ERC_TYPES.ERC677
} else {
return ERC_TYPES.ERC20
}
} catch (e) {
return ERC_TYPES.ERC20
}
}
}
const isErcToErcMode = bridgeMode => {
return (
bridgeMode === BRIDGE_MODES.ERC_TO_ERC ||
bridgeMode === BRIDGE_MODES.AMB_ERC_TO_ERC ||
bridgeMode === BRIDGE_MODES.STAKE_AMB_ERC_TO_ERC
)
}
const isMediatorMode = bridgeMode => {
return bridgeMode === BRIDGE_MODES.AMB_ERC_TO_ERC || bridgeMode === BRIDGE_MODES.STAKE_AMB_ERC_TO_ERC
}
const getUnit = bridgeMode => {
let unitHome = null
let unitForeign = null
if (bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC) {
unitHome = 'Native coins'
unitForeign = 'Tokens'
} else if (bridgeMode === BRIDGE_MODES.ERC_TO_ERC) {
unitHome = 'Tokens'
unitForeign = 'Tokens'
} else if (bridgeMode === BRIDGE_MODES.ERC_TO_NATIVE) {
unitHome = 'Native coins'
unitForeign = 'Tokens'
} else if (bridgeMode === BRIDGE_MODES.STAKE_AMB_ERC_TO_ERC) {
unitHome = 'Tokens'
unitForeign = 'Tokens'
} else {
throw new Error(`Unrecognized bridge mode: ${bridgeMode}`)
}
return { unitHome, unitForeign }
} }
const parseValidatorEvent = event => { const parseValidatorEvent = event => {
@ -306,10 +229,7 @@ const gasPriceFromContract = async (bridgeContract, options = {}) => {
module.exports = { module.exports = {
decodeBridgeMode, decodeBridgeMode,
decodeFeeManagerMode,
getBridgeMode, getBridgeMode,
getTokenType,
getUnit,
parseValidatorEvent, parseValidatorEvent,
processValidatorsEvents, processValidatorsEvents,
getValidatorList, getValidatorList,
@ -318,7 +238,5 @@ module.exports = {
normalizeGasPrice, normalizeGasPrice,
gasPriceFromSupplier, gasPriceFromSupplier,
gasPriceFromContract, gasPriceFromContract,
gasPriceWithinLimits, gasPriceWithinLimits
isErcToErcMode,
isMediatorMode
} }

@ -1,191 +0,0 @@
const homeV1Abi = [
{
constant: true,
inputs: [],
name: 'validatorContract',
outputs: [
{
name: '',
type: 'address'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
anonymous: false,
inputs: [
{
indexed: false,
name: 'recipient',
type: 'address'
},
{
indexed: false,
name: 'value',
type: 'uint256'
}
],
name: 'Deposit',
type: 'event'
},
{
anonymous: false,
inputs: [
{
indexed: false,
name: 'recipient',
type: 'address'
},
{
indexed: false,
name: 'value',
type: 'uint256'
},
{
indexed: false,
name: 'transactionHash',
type: 'bytes32'
}
],
name: 'Withdraw',
type: 'event'
},
{
constant: true,
inputs: [],
name: 'deployedAtBlock',
outputs: [
{
name: '',
type: 'uint256'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
constant: true,
inputs: [],
name: 'requiredBlockConfirmations',
outputs: [
{
name: '',
type: 'uint256'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
}
]
const foreignViAbi = [
{
constant: true,
inputs: [],
name: 'validatorContract',
outputs: [
{
name: '',
type: 'address'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
anonymous: false,
inputs: [
{
indexed: false,
name: 'recipient',
type: 'address'
},
{
indexed: false,
name: 'value',
type: 'uint256'
},
{
indexed: false,
name: 'transactionHash',
type: 'bytes32'
}
],
name: 'Deposit',
type: 'event'
},
{
anonymous: false,
inputs: [
{
indexed: false,
name: 'recipient',
type: 'address'
},
{
indexed: false,
name: 'value',
type: 'uint256'
},
{
indexed: false,
name: 'homeGasPrice',
type: 'uint256'
}
],
name: 'Withdraw',
type: 'event'
},
{
constant: true,
inputs: [],
name: 'deployedAtBlock',
outputs: [
{
name: '',
type: 'uint256'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
constant: true,
inputs: [],
name: 'erc677token',
outputs: [
{
name: '',
type: 'address'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
constant: true,
inputs: [],
name: 'requiredBlockConfirmations',
outputs: [
{
name: '',
type: 'uint256'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
}
]
module.exports = {
HOME_V1_ABI: homeV1Abi,
FOREIGN_V1_ABI: foreignViAbi
}

@ -1 +1 @@
Subproject commit c9377114f7bcf04cd12a30d9eca0a63362dcaedc Subproject commit 004d466a3d593e6304e52c74e6c3e801b6a33b32

@ -9,15 +9,17 @@
- oracle_net_db_bridge_request - oracle_net_db_bridge_request
- oracle_net_db_bridge_collected - oracle_net_db_bridge_collected
- oracle_net_db_bridge_affirmation - oracle_net_db_bridge_affirmation
- oracle_net_db_bridge_information
- oracle_net_db_bridge_transfer - oracle_net_db_bridge_transfer
- oracle_net_db_bridge_senderhome - oracle_net_db_bridge_senderhome
- oracle_net_db_bridge_senderforeign - oracle_net_db_bridge_senderforeign
- oracle_net_db_bridge_shutdown
- oracle_net_rabbit_bridge_request - oracle_net_rabbit_bridge_request
- oracle_net_rabbit_bridge_collected - oracle_net_rabbit_bridge_collected
- oracle_net_rabbit_bridge_affirmation - oracle_net_rabbit_bridge_affirmation
- oracle_net_rabbit_bridge_information
- oracle_net_rabbit_bridge_transfer - oracle_net_rabbit_bridge_transfer
- oracle_net_rabbit_bridge_senderhome - oracle_net_rabbit_bridge_senderhome
- oracle_net_rabbit_bridge_senderforeign - oracle_net_rabbit_bridge_senderforeign
- oracle_net_rabbit_bridge_convert_to_chai_worker
delegate_to: 127.0.0.1 delegate_to: 127.0.0.1
become: false become: false

@ -1,14 +0,0 @@
# Molecule managed
{% if item.registry is defined %}
FROM {{ item.registry.url }}/{{ item.image }}
{% else %}
FROM {{ item.image }}
{% endif %}
RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates && apt-get clean; \
elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install python sudo python-devel python*-dnf bash && dnf clean all; \
elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl bash && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml && zypper clean -a; \
elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates; \
elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates && xbps-remove -O; fi

@ -1,38 +0,0 @@
---
driver:
name: docker
platforms:
- name: oracle-erc-to-erc-host
groups:
- ultimate
- erc-to-erc
children:
- oracle
image: ubuntu:16.04
privileged: true
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock
provisioner:
name: ansible
playbooks:
prepare: ../prepare.yml
converge: ../ultimate-commons/converge.yml
inventory:
host_vars:
oracle-erc-to-erc-host:
ORACLE_VALIDATOR_ADDRESS: "0xaaB52d66283F7A1D5978bcFcB55721ACB467384b"
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9"
verifier:
name: testinfra
lint:
name: flake8
scenario:
name: ultimate-erc-to-erc
test_sequence:
- cleanup
- destroy
- syntax
- create
- prepare
- converge

@ -1,14 +0,0 @@
# Molecule managed
{% if item.registry is defined %}
FROM {{ item.registry.url }}/{{ item.image }}
{% else %}
FROM {{ item.image }}
{% endif %}
RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates && apt-get clean; \
elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install python sudo python-devel python*-dnf bash && dnf clean all; \
elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl bash && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml && zypper clean -a; \
elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates; \
elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates && xbps-remove -O; fi

@ -1,38 +0,0 @@
---
driver:
name: docker
platforms:
- name: oracle-native-to-erc-host
groups:
- ultimate
- native-to-erc
children:
- oracle
image: ubuntu:16.04
privileged: true
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock
provisioner:
name: ansible
playbooks:
prepare: ../prepare.yml
converge: ../ultimate-commons/converge.yml
inventory:
host_vars:
oracle-native-to-erc-host:
ORACLE_VALIDATOR_ADDRESS: "0xaaB52d66283F7A1D5978bcFcB55721ACB467384b"
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9"
verifier:
name: testinfra
lint:
name: flake8
scenario:
name: ultimate-native-to-erc
test_sequence:
- cleanup
- destroy
- syntax
- create
- prepare
- converge

@ -1,5 +1,5 @@
--- ---
ORACLE_BRIDGE_MODE: "ARBITRARY_MESSAGE" ORACLE_BRIDGE_MODE: "ARBITRARY_MESSAGE"
COMMON_HOME_BRIDGE_ADDRESS: "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0" COMMON_HOME_BRIDGE_ADDRESS: "0x8397be90BCF57b0B71219f555Fe121b22e5a994C"
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0" COMMON_FOREIGN_BRIDGE_ADDRESS: "0x1feB40aD9420b186F019A717c37f5546165d411E"
MONITOR_PORT: 3013 MONITOR_PORT: 3013

@ -1,5 +0,0 @@
---
ORACLE_BRIDGE_MODE: "ERC_TO_ERC"
COMMON_HOME_BRIDGE_ADDRESS: "0x1feB40aD9420b186F019A717c37f5546165d411E"
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x4a58D6d8D416a5fBCAcf3dC52eb8bE8948E25127"
MONITOR_PORT: 3011

@ -1,5 +1,5 @@
--- ---
ORACLE_BRIDGE_MODE: "ERC_TO_NATIVE" ORACLE_BRIDGE_MODE: "ERC_TO_NATIVE"
COMMON_HOME_BRIDGE_ADDRESS: "0x488Af810997eD1730cB3a3918cD83b3216E6eAda" COMMON_HOME_BRIDGE_ADDRESS: "0x5118AC62AE912Dd5B51EEfF7338c4fcb0248Ba8c"
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x488Af810997eD1730cB3a3918cD83b3216E6eAda" COMMON_FOREIGN_BRIDGE_ADDRESS: "0x32198D570fffC7033641F8A9094FFDCaAEF42624"
MONITOR_PORT: 3012 MONITOR_PORT: 3012

@ -1,6 +1,6 @@
--- ---
## General settings ## General settings
ORACLE_BRIDGE_MODE: "NATIVE_TO_ERC" ORACLE_BRIDGE_MODE: "ARBITRARY_MESSAGE"
ORACLE_LOG_LEVEL: debug ORACLE_LOG_LEVEL: debug
## Home contract ## Home contract

@ -1,5 +0,0 @@
---
ORACLE_BRIDGE_MODE: "NATIVE_TO_ERC"
COMMON_HOME_BRIDGE_ADDRESS: "0x32198D570fffC7033641F8A9094FFDCaAEF42624"
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x2B6871b9B02F73fa24F4864322CdC78604207769"
MONITOR_PORT: 3010

@ -1,37 +0,0 @@
---
## General settings
ORACLE_BRIDGE_MODE: "NATIVE_TO_ERC"
## Home contract
COMMON_HOME_RPC_URL: "https://www.ethercluster.com/etc"
COMMON_HOME_BRIDGE_ADDRESS: "0x073081832B4Ecdce79d4D6753565c85Ba4b3BeA9"
ORACLE_HOME_RPC_POLLING_INTERVAL: 7000
## Foreign contract
COMMON_FOREIGN_RPC_URL: "https://mainnet.infura.io/"
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x0cB781EE62F815bdD9CD4c2210aE8600d43e7040"
ORACLE_FOREIGN_RPC_POLLING_INTERVAL: 7000
## Home Gasprice
COMMON_HOME_GAS_PRICE_SUPPLIER_URL: "https://gasprice-etc.poa.network/"
COMMON_HOME_GAS_PRICE_SPEED_TYPE: "standard"
COMMON_HOME_GAS_PRICE_FALLBACK: 15000000000 # in wei
ORACLE_HOME_GAS_PRICE_UPDATE_INTERVAL: 600000
COMMON_HOME_GAS_PRICE_FACTOR: 1
## Foreign Gasprice
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL: "https://gasprice.poa.network/"
COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE: "standard"
COMMON_FOREIGN_GAS_PRICE_FALLBACK: 10000000000 # in wei
ORACLE_FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000
COMMON_FOREIGN_GAS_PRICE_FACTOR: 1
## Monitor
MONITOR_BRIDGE_NAME: "wetc"
MONITOR_PORT: 3003
MONITOR_CACHE_EVENTS: "true"
MONITOR_HOME_START_BLOCK: 7703292
MONITOR_FOREIGN_START_BLOCK: 7412459
MONITOR_VALIDATOR_HOME_TX_LIMIT: 300000
MONITOR_VALIDATOR_FOREIGN_TX_LIMIT: 300000
MONITOR_TX_NUMBER_THRESHOLD: 100

@ -3,7 +3,7 @@
with_items: with_items:
- docker-compose - docker-compose
- docker-compose-transfer - docker-compose-transfer
- docker-compose-erc-native - docker-compose-amb
loop_control: loop_control:
loop_var: file loop_var: file

@ -38,14 +38,14 @@
set_fact: set_fact:
FOREIGN_ERC_TYPE: "{{ (ERCTYPE.stdout).foreignERC | default('') }}" FOREIGN_ERC_TYPE: "{{ (ERCTYPE.stdout).foreignERC | default('') }}"
- name: Extend docker compose file
set_fact: composefileoverride="-f docker-compose-transfer.yml"
when: ORACLE_BRIDGE_MODE == "ERC_TO_ERC" and FOREIGN_ERC_TYPE != "ERC677"
- name: Extend docker compose file for erc to native - name: Extend docker compose file for erc to native
set_fact: composefileoverride="-f docker-compose-erc-native.yml" set_fact: composefileoverride="-f docker-compose-transfer.yml"
when: ORACLE_BRIDGE_MODE == "ERC_TO_NATIVE" when: ORACLE_BRIDGE_MODE == "ERC_TO_NATIVE"
- name: Extend docker compose file for amb
set_fact: composefileoverride="-f docker-compose-amb.yml"
when: ORACLE_BRIDGE_MODE == "ARBITRARY_MESSAGE"
- name: Install .key config - name: Install .key config
template: template:
src: key.j2 src: key.j2

@ -20,4 +20,4 @@
with_items: with_items:
- docker-compose.yml - docker-compose.yml
- docker-compose-transfer.yml - docker-compose-transfer.yml
- docker-compose-erc-native.yml - docker-compose-amb.yml

@ -26,9 +26,7 @@ Shut down and cleans up containers, networks, services, running scripts:
| oracle-validator-3 | Launches Oracle containers for third validator | | oracle-validator-3 | Launches Oracle containers for third validator |
| blocks | Auto mines blocks | | blocks | Auto mines blocks |
| monitor | Launches Monitor containers | | monitor | Launches Monitor containers |
| native-to-erc | Creates infrastructure for ultimate e2e testing, for native-to-erc type of bridge |
| erc-to-native | Creates infrastructure for ultimate e2e testing, for erc-to-native type of bridge | | erc-to-native | Creates infrastructure for ultimate e2e testing, for erc-to-native type of bridge |
| erc-to-erc | Creates infrastructure for ultimate e2e testing, for erc-to-erc type of bridge |
| amb | Creates infrastructure for ultimate e2e testing, for arbitrary message type of bridge | | amb | Creates infrastructure for ultimate e2e testing, for arbitrary message type of bridge |
#### Ultimate e2e testing #### Ultimate e2e testing

@ -4,7 +4,7 @@ Documentation regarding the Ultimate end-to-end tests.
## Overview ## Overview
The ultimate e2e test scenario covers native-to-erc type of bridge. The ultimate e2e test scenario covers erc-to-native and amb types of bridges.
It runs the e2e tests on components deployed using the deployment playbooks. It runs the e2e tests on components deployed using the deployment playbooks.
@ -16,14 +16,14 @@ Run the Parity nodes, deploy the bridge contracts, deploy Oracle using the deplo
```bash ```bash
./e2e-commons/up.sh deploy blocks ./e2e-commons/up.sh deploy blocks
./deployment-e2e/molecule.sh ultimate-native-to-erc ./deployment-e2e/molecule.sh ultimate-erc-to-native
``` ```
### 2. Run the E2E tests ### 2. Run the E2E tests
```bash ```bash
cd e2e-commons cd e2e-commons
docker-compose run -e ULTIMATE=true e2e yarn workspace oracle-e2e run native-to-erc docker-compose run -e ULTIMATE=true e2e yarn workspace oracle-e2e run erc-to-native
``` ```
## Diagram ## Diagram

@ -1,2 +1,2 @@
0xc9e38bfdB9c635F0796ad83CC8705dc379F41c04 0xc9e38bfdB9c635F0796ad83CC8705dc379F41c04
0x6f359aC418a5f7538F7755A33C9c7dDf38785524 0xF9698Eb93702dfdd0e2d802088d4c21822a8A977

@ -5,9 +5,11 @@ set -e # exit when any command fails
docker-compose build e2e docker-compose build e2e
while [ "$1" != "" ]; do while [ "$1" != "" ]; do
if [ "$1" == "oracle" ]; then if [ "$1" == "oracle" ]; then
docker-compose build oracle docker-compose build oracle-amb
elif [ "$1" == "alm-e2e" ]; then
docker-compose build oracle-amb
elif [ "$1" == "monitor" ]; then elif [ "$1" == "monitor" ]; then
docker-compose build monitor docker-compose build monitor-amb
elif [ "$1" == "alm" ]; then elif [ "$1" == "alm" ]; then
docker-compose build alm docker-compose build alm
fi fi

@ -1,5 +1,5 @@
COMMON_HOME_BRIDGE_ADDRESS=0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0 COMMON_HOME_BRIDGE_ADDRESS=0x8397be90BCF57b0B71219f555Fe121b22e5a994C
COMMON_FOREIGN_BRIDGE_ADDRESS=0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0 COMMON_FOREIGN_BRIDGE_ADDRESS=0x1feB40aD9420b186F019A717c37f5546165d411E
COMMON_HOME_RPC_URL=http://localhost:8541 COMMON_HOME_RPC_URL=http://localhost:8541
COMMON_FOREIGN_RPC_URL=http://localhost:8542 COMMON_FOREIGN_RPC_URL=http://localhost:8542

@ -1,7 +1,7 @@
COMMON_HOME_RPC_URL=http://parity1:8545 COMMON_HOME_RPC_URL=http://parity1:8545
COMMON_FOREIGN_RPC_URL=http://parity2:8545 COMMON_FOREIGN_RPC_URL=http://parity2:8545
COMMON_HOME_BRIDGE_ADDRESS=0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0 COMMON_HOME_BRIDGE_ADDRESS=0x8397be90BCF57b0B71219f555Fe121b22e5a994C
COMMON_FOREIGN_BRIDGE_ADDRESS=0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0 COMMON_FOREIGN_BRIDGE_ADDRESS=0x1feB40aD9420b186F019A717c37f5546165d411E
MONITOR_HOME_START_BLOCK=0 MONITOR_HOME_START_BLOCK=0
MONITOR_FOREIGN_START_BLOCK=0 MONITOR_FOREIGN_START_BLOCK=0
MONITOR_VALIDATOR_HOME_TX_LIMIT=300000 MONITOR_VALIDATOR_HOME_TX_LIMIT=300000

@ -1,7 +1,7 @@
COMMON_HOME_RPC_URL=http://parity1:8545 COMMON_HOME_RPC_URL=http://parity1:8545
COMMON_FOREIGN_RPC_URL=http://parity2:8545 COMMON_FOREIGN_RPC_URL=http://parity2:8545
COMMON_HOME_BRIDGE_ADDRESS=0x488Af810997eD1730cB3a3918cD83b3216E6eAda COMMON_HOME_BRIDGE_ADDRESS=0x5118AC62AE912Dd5B51EEfF7338c4fcb0248Ba8c
COMMON_FOREIGN_BRIDGE_ADDRESS=0x488Af810997eD1730cB3a3918cD83b3216E6eAda COMMON_FOREIGN_BRIDGE_ADDRESS=0x32198D570fffC7033641F8A9094FFDCaAEF42624
MONITOR_HOME_START_BLOCK=0 MONITOR_HOME_START_BLOCK=0
MONITOR_FOREIGN_START_BLOCK=0 MONITOR_FOREIGN_START_BLOCK=0
MONITOR_VALIDATOR_HOME_TX_LIMIT=300000 MONITOR_VALIDATOR_HOME_TX_LIMIT=300000

@ -1,20 +0,0 @@
COMMON_HOME_RPC_URL=http://parity1:8545
COMMON_FOREIGN_RPC_URL=http://parity2:8545
COMMON_HOME_BRIDGE_ADDRESS=0x1feB40aD9420b186F019A717c37f5546165d411E
COMMON_FOREIGN_BRIDGE_ADDRESS=0x4a58D6d8D416a5fBCAcf3dC52eb8bE8948E25127
MONITOR_HOME_START_BLOCK=0
MONITOR_FOREIGN_START_BLOCK=0
MONITOR_VALIDATOR_HOME_TX_LIMIT=300000
COMMON_HOME_GAS_PRICE_SUPPLIER_URL=https://gasprice.poa.network/
COMMON_HOME_GAS_PRICE_SPEED_TYPE=standard
COMMON_HOME_GAS_PRICE_FALLBACK=1000000000
COMMON_HOME_GAS_PRICE_FACTOR=1
MONITOR_VALIDATOR_FOREIGN_TX_LIMIT=300000
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL=https://gasprice.poa.network/
COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE=standard
COMMON_FOREIGN_GAS_PRICE_FALLBACK=1000000000
COMMON_FOREIGN_GAS_PRICE_FACTOR=1
MONITOR_TX_NUMBER_THRESHOLD=100
MONITOR_PORT=3011
MONITOR_BRIDGE_NAME=bridge
MONITOR_CACHE_EVENTS=false

@ -1,20 +0,0 @@
COMMON_HOME_RPC_URL=http://parity1:8545
COMMON_FOREIGN_RPC_URL=http://parity2:8545
COMMON_HOME_BRIDGE_ADDRESS=0x32198D570fffC7033641F8A9094FFDCaAEF42624
COMMON_FOREIGN_BRIDGE_ADDRESS=0x2B6871b9B02F73fa24F4864322CdC78604207769
MONITOR_HOME_START_BLOCK=0
MONITOR_FOREIGN_START_BLOCK=0
MONITOR_VALIDATOR_HOME_TX_LIMIT=300000
COMMON_HOME_GAS_PRICE_SUPPLIER_URL=https://gasprice.poa.network/
COMMON_HOME_GAS_PRICE_SPEED_TYPE=standard
COMMON_HOME_GAS_PRICE_FALLBACK=1000000000
COMMON_HOME_GAS_PRICE_FACTOR=1
MONITOR_VALIDATOR_FOREIGN_TX_LIMIT=300000
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL=https://gasprice.poa.network/
COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE=standard
COMMON_FOREIGN_GAS_PRICE_FALLBACK=1000000000
COMMON_FOREIGN_GAS_PRICE_FACTOR=1
MONITOR_TX_NUMBER_THRESHOLD=100
MONITOR_PORT=3010
MONITOR_BRIDGE_NAME=bridge
MONITOR_CACHE_EVENTS=false

@ -4,8 +4,8 @@ ORACLE_QUEUE_URL=amqp://rabbit
ORACLE_REDIS_URL=redis://redis ORACLE_REDIS_URL=redis://redis
COMMON_HOME_RPC_URL=http://parity1:8545 COMMON_HOME_RPC_URL=http://parity1:8545
COMMON_FOREIGN_RPC_URL=http://parity2:8545 COMMON_FOREIGN_RPC_URL=http://parity2:8545
COMMON_HOME_BRIDGE_ADDRESS=0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0 COMMON_HOME_BRIDGE_ADDRESS=0x8397be90BCF57b0B71219f555Fe121b22e5a994C
COMMON_FOREIGN_BRIDGE_ADDRESS=0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0 COMMON_FOREIGN_BRIDGE_ADDRESS=0x1feB40aD9420b186F019A717c37f5546165d411E
ORACLE_VALIDATOR_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b ORACLE_VALIDATOR_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9 ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9
COMMON_HOME_GAS_PRICE_SUPPLIER_URL=https://gasprice.poa.network/ COMMON_HOME_GAS_PRICE_SUPPLIER_URL=https://gasprice.poa.network/
@ -24,3 +24,4 @@ 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 ORACLE_HOME_TO_FOREIGN_BLOCK_LIST=/mono/oracle/access-lists/block_list.txt
ORACLE_FOREIGN_ARCHIVE_RPC_URL=http://parity2:8545

@ -4,8 +4,8 @@ ORACLE_QUEUE_URL=amqp://rabbit
ORACLE_REDIS_URL=redis://redis ORACLE_REDIS_URL=redis://redis
COMMON_HOME_RPC_URL=http://parity1:8545 COMMON_HOME_RPC_URL=http://parity1:8545
COMMON_FOREIGN_RPC_URL=http://parity2:8545 COMMON_FOREIGN_RPC_URL=http://parity2:8545
COMMON_HOME_BRIDGE_ADDRESS=0x488Af810997eD1730cB3a3918cD83b3216E6eAda COMMON_HOME_BRIDGE_ADDRESS=0x5118AC62AE912Dd5B51EEfF7338c4fcb0248Ba8c
COMMON_FOREIGN_BRIDGE_ADDRESS=0x488Af810997eD1730cB3a3918cD83b3216E6eAda COMMON_FOREIGN_BRIDGE_ADDRESS=0x32198D570fffC7033641F8A9094FFDCaAEF42624
ORACLE_VALIDATOR_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b ORACLE_VALIDATOR_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9 ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9
COMMON_HOME_GAS_PRICE_SUPPLIER_URL=https://gasprice.poa.network/ COMMON_HOME_GAS_PRICE_SUPPLIER_URL=https://gasprice.poa.network/

@ -1,25 +0,0 @@
ORACLE_BRIDGE_MODE=ERC_TO_ERC
ORACLE_QUEUE_URL=amqp://rabbit
ORACLE_REDIS_URL=redis://redis
COMMON_HOME_RPC_URL=http://parity1:8545
COMMON_FOREIGN_RPC_URL=http://parity2:8545
COMMON_HOME_BRIDGE_ADDRESS=0x1feB40aD9420b186F019A717c37f5546165d411E
COMMON_FOREIGN_BRIDGE_ADDRESS=0x4a58D6d8D416a5fBCAcf3dC52eb8bE8948E25127
ORACLE_VALIDATOR_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9
COMMON_HOME_GAS_PRICE_SUPPLIER_URL=https://gasprice.poa.network/
COMMON_HOME_GAS_PRICE_SPEED_TYPE=standard
COMMON_HOME_GAS_PRICE_FALLBACK=1
ORACLE_HOME_GAS_PRICE_UPDATE_INTERVAL=600000
COMMON_HOME_GAS_PRICE_FACTOR=1
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL=https://gasprice.poa.network/
COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE=standard
COMMON_FOREIGN_GAS_PRICE_FALLBACK=1
ORACLE_FOREIGN_GAS_PRICE_UPDATE_INTERVAL=600000
COMMON_FOREIGN_GAS_PRICE_FACTOR=0.1
ORACLE_HOME_RPC_POLLING_INTERVAL=500
ORACLE_FOREIGN_RPC_POLLING_INTERVAL=500
ORACLE_ALLOW_HTTP_FOR_RPC=yes
ORACLE_HOME_START_BLOCK=1
ORACLE_FOREIGN_START_BLOCK=1

@ -1,25 +0,0 @@
ORACLE_BRIDGE_MODE=NATIVE_TO_ERC
ORACLE_QUEUE_URL=amqp://rabbit
ORACLE_REDIS_URL=redis://redis
COMMON_HOME_RPC_URL=http://parity1:8545
COMMON_FOREIGN_RPC_URL=http://parity2:8545
COMMON_HOME_BRIDGE_ADDRESS=0x32198D570fffC7033641F8A9094FFDCaAEF42624
COMMON_FOREIGN_BRIDGE_ADDRESS=0x2B6871b9B02F73fa24F4864322CdC78604207769
ORACLE_VALIDATOR_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9
COMMON_HOME_GAS_PRICE_SUPPLIER_URL=https://gasprice.poa.network/
COMMON_HOME_GAS_PRICE_SPEED_TYPE=standard
COMMON_HOME_GAS_PRICE_FALLBACK=1
ORACLE_HOME_GAS_PRICE_UPDATE_INTERVAL=600000
COMMON_HOME_GAS_PRICE_FACTOR=1
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL=https://gasprice.poa.network/
COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE=standard
COMMON_FOREIGN_GAS_PRICE_FALLBACK=1
ORACLE_FOREIGN_GAS_PRICE_UPDATE_INTERVAL=600000
COMMON_FOREIGN_GAS_PRICE_FACTOR=0.1
ORACLE_HOME_RPC_POLLING_INTERVAL=500
ORACLE_FOREIGN_RPC_POLLING_INTERVAL=500
ORACLE_ALLOW_HTTP_FOR_RPC=yes
ORACLE_HOME_START_BLOCK=1
ORACLE_FOREIGN_START_BLOCK=1

@ -35,32 +35,18 @@
"address": "0xB4579fd5AfEaB60B03Db3F408AAdD315035943f7", "address": "0xB4579fd5AfEaB60B03Db3F408AAdD315035943f7",
"privateKey": "0xd6143d390d8b28c33601bb0fe29392fb1c35c24ccfe8722c09c2bdd6ada2699f" "privateKey": "0xd6143d390d8b28c33601bb0fe29392fb1c35c24ccfe8722c09c2bdd6ada2699f"
}, },
"nativeToErcBridge": {
"home": "0x32198D570fffC7033641F8A9094FFDCaAEF42624",
"foreign": "0x2B6871b9B02F73fa24F4864322CdC78604207769",
"foreignToken": "0xdbeE25CbE97e4A5CC6c499875774dc7067E9426B",
"monitor": "http://monitor:3010/bridge"
},
"ercToErcBridge": {
"home": "0x1feB40aD9420b186F019A717c37f5546165d411E",
"foreign": "0x4a58D6d8D416a5fBCAcf3dC52eb8bE8948E25127",
"homeToken": "0x792455a6bCb62Ed4C4362D323E0590654CA4765c",
"foreignToken": "0x3C665A31199694Bf723fD08844AD290207B5797f",
"monitor": "http://monitor-erc20:3011/bridge"
},
"ercToNativeBridge": { "ercToNativeBridge": {
"home": "0x488Af810997eD1730cB3a3918cD83b3216E6eAda", "home": "0x5118AC62AE912Dd5B51EEfF7338c4fcb0248Ba8c",
"foreign": "0x488Af810997eD1730cB3a3918cD83b3216E6eAda", "foreign": "0x32198D570fffC7033641F8A9094FFDCaAEF42624",
"foreignToken": "0x7cc4b1851c35959d34e635a470f6b5c43ba3c9c9", "foreignToken": "0x7cc4b1851c35959d34e635a470f6b5c43ba3c9c9",
"chaiToken": "0x06af07097c9eeb7fd685c692751d5c66db49c215",
"monitor": "http://monitor-erc20-native:3012/bridge" "monitor": "http://monitor-erc20-native:3012/bridge"
}, },
"amb": { "amb": {
"home": "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0", "home": "0x8397be90BCF57b0B71219f555Fe121b22e5a994C",
"foreign": "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0", "foreign": "0x1feB40aD9420b186F019A717c37f5546165d411E",
"homeBox": "0x6C4EaAb8756d53Bf599FFe2347FAFF1123D6C8A1", "homeBox": "0xb008E9076fCbDB2C3AF84225Bc07Eb35B2bE5ECD",
"foreignBox": "0x6C4EaAb8756d53Bf599FFe2347FAFF1123D6C8A1", "foreignBox": "0x4a58D6d8D416a5fBCAcf3dC52eb8bE8948E25127",
"blockedHomeBox": "0x6f359aC418a5f7538F7755A33C9c7dDf38785524", "blockedHomeBox": "0xF9698Eb93702dfdd0e2d802088d4c21822a8A977",
"monitor": "http://monitor-amb:3013/bridge" "monitor": "http://monitor-amb:3013/bridge"
}, },
"homeRPC": { "homeRPC": {

@ -9,7 +9,7 @@ HOME_RPC_URL=http://parity1:8545
HOME_BRIDGE_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b HOME_BRIDGE_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
HOME_VALIDATORS_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b HOME_VALIDATORS_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
HOME_UPGRADEABLE_ADMIN=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b HOME_UPGRADEABLE_ADMIN=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
HOME_MAX_AMOUNT_PER_TX=8000000 HOME_MAX_AMOUNT_PER_TX=2000000
HOME_REQUIRED_BLOCK_CONFIRMATIONS=1 HOME_REQUIRED_BLOCK_CONFIRMATIONS=1
HOME_GAS_PRICE=1000000000 HOME_GAS_PRICE=1000000000
@ -17,7 +17,7 @@ FOREIGN_RPC_URL=http://parity2:8545
FOREIGN_BRIDGE_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b FOREIGN_BRIDGE_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
FOREIGN_VALIDATORS_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b FOREIGN_VALIDATORS_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
FOREIGN_UPGRADEABLE_ADMIN=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b FOREIGN_UPGRADEABLE_ADMIN=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
FOREIGN_MAX_AMOUNT_PER_TX=8000000 FOREIGN_MAX_AMOUNT_PER_TX=2000000
FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS=1 FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS=1
FOREIGN_GAS_PRICE=10000000000 FOREIGN_GAS_PRICE=10000000000

@ -1,40 +0,0 @@
BRIDGE_MODE=ERC_TO_ERC
DEPLOYMENT_ACCOUNT_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9
HOME_DEPLOYMENT_GAS_PRICE=10000000000
FOREIGN_DEPLOYMENT_GAS_PRICE=10000000000
GET_RECEIPT_INTERVAL_IN_MILLISECONDS=50
DEPLOYMENT_GAS_LIMIT_EXTRA=0.2
DEPLOY_REWARDABLE_TOKEN=false
BRIDGEABLE_TOKEN_NAME="Your New Bridged Token"
BRIDGEABLE_TOKEN_SYMBOL="TEST"
BRIDGEABLE_TOKEN_DECIMALS="18"
HOME_RPC_URL=http://parity1:8545
HOME_BRIDGE_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
HOME_VALIDATORS_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
HOME_UPGRADEABLE_ADMIN=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
HOME_DAILY_LIMIT=30000000000000000000000000
HOME_MAX_AMOUNT_PER_TX=1500000000000000000000000
HOME_MIN_AMOUNT_PER_TX=10000000000000000
HOME_REQUIRED_BLOCK_CONFIRMATIONS=1
HOME_GAS_PRICE=1000000000
HOME_REWARDABLE=false
FOREIGN_RPC_URL=http://parity2:8545
FOREIGN_BRIDGE_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
FOREIGN_VALIDATORS_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
FOREIGN_UPGRADEABLE_ADMIN=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
FOREIGN_DAILY_LIMIT=15000000000000000000000000
FOREIGN_MAX_AMOUNT_PER_TX=750000000000000000000000
FOREIGN_MIN_AMOUNT_PER_TX=10000000000000000
FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS=1
FOREIGN_GAS_PRICE=10000000000
FOREIGN_REWARDABLE=false
ERC20_TOKEN_ADDRESS=0x3C665A31199694Bf723fD08844AD290207B5797f
REQUIRED_NUMBER_OF_VALIDATORS=1
VALIDATORS="0xaaB52d66283F7A1D5978bcFcB55721ACB467384b 0xdCC784657C78054aa61FbcFFd2605F32374816A4 0xDcef88209a20D52165230104B245803C3269454d"
BLOCK_REWARD_ADDRESS=0x0000000000000000000000000000000000000000
DPOS_STAKING_ADDRESS=0x0000000000000000000000000000000000000000
ERC20_EXTENDED_BY_ERC677=false

@ -31,7 +31,7 @@ FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS=1
FOREIGN_GAS_PRICE=10000000000 FOREIGN_GAS_PRICE=10000000000
FOREIGN_REWARDABLE=false FOREIGN_REWARDABLE=false
BLOCK_REWARD_ADDRESS=0xF9698Eb93702dfdd0e2d802088d4c21822a8A977 BLOCK_REWARD_ADDRESS=0xdbeE25CbE97e4A5CC6c499875774dc7067E9426B
ERC20_TOKEN_ADDRESS=0x7cc4b1851c35959d34e635a470f6b5c43ba3c9c9 ERC20_TOKEN_ADDRESS=0x7cc4b1851c35959d34e635a470f6b5c43ba3c9c9
REQUIRED_NUMBER_OF_VALIDATORS=1 REQUIRED_NUMBER_OF_VALIDATORS=1

@ -1,38 +0,0 @@
BRIDGE_MODE=NATIVE_TO_ERC
DEPLOYMENT_ACCOUNT_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
DEPLOYMENT_ACCOUNT_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9
HOME_DEPLOYMENT_GAS_PRICE=10000000000
FOREIGN_DEPLOYMENT_GAS_PRICE=10000000000
GET_RECEIPT_INTERVAL_IN_MILLISECONDS=50
DEPLOYMENT_GAS_LIMIT_EXTRA=0.2
DEPLOY_REWARDABLE_TOKEN=false
BRIDGEABLE_TOKEN_NAME="Your New Bridged Token"
BRIDGEABLE_TOKEN_SYMBOL="TEST"
BRIDGEABLE_TOKEN_DECIMALS="18"
HOME_RPC_URL=http://parity1:8545
HOME_BRIDGE_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
HOME_VALIDATORS_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
HOME_UPGRADEABLE_ADMIN=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
HOME_DAILY_LIMIT=30000000000000000000000000
HOME_MAX_AMOUNT_PER_TX=1500000000000000000000000
HOME_MIN_AMOUNT_PER_TX=10000000000000000
HOME_REQUIRED_BLOCK_CONFIRMATIONS=1
HOME_GAS_PRICE=1000000000
HOME_REWARDABLE=false
FOREIGN_RPC_URL=http://parity2:8545
FOREIGN_BRIDGE_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
FOREIGN_VALIDATORS_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
FOREIGN_UPGRADEABLE_ADMIN=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
FOREIGN_DAILY_LIMIT=15000000000000000000000000
FOREIGN_MAX_AMOUNT_PER_TX=750000000000000000000000
FOREIGN_MIN_AMOUNT_PER_TX=10000000000000000
FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS=1
FOREIGN_GAS_PRICE=10000000000
FOREIGN_REWARDABLE=false
REQUIRED_NUMBER_OF_VALIDATORS=1
VALIDATORS="0xaaB52d66283F7A1D5978bcFcB55721ACB467384b 0xdCC784657C78054aa61FbcFFd2605F32374816A4 0xDcef88209a20D52165230104B245803C3269454d"
BLOCK_REWARD_ADDRESS=0x0000000000000000000000000000000000000000

@ -27,25 +27,6 @@ services:
image: "rabbitmq:3-management" image: "rabbitmq:3-management"
networks: networks:
- ultimate - ultimate
oracle:
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-oracle:${ORACLE_TAG:-local}
build:
context: ..
dockerfile: oracle/Dockerfile
env_file: ../e2e-commons/components-envs/oracle.env
environment:
- NODE_ENV=production
command: "true"
networks:
- ultimate
oracle-erc20:
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-oracle:${ORACLE_TAG:-local}
env_file: ../e2e-commons/components-envs/oracle-erc20.env
environment:
- NODE_ENV=production
command: "true"
networks:
- ultimate
oracle-erc20-native: oracle-erc20-native:
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-oracle:${ORACLE_TAG:-local} image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-oracle:${ORACLE_TAG:-local}
env_file: ../e2e-commons/components-envs/oracle-erc20-native.env env_file: ../e2e-commons/components-envs/oracle-erc20-native.env
@ -59,6 +40,9 @@ services:
- ultimate - ultimate
oracle-amb: oracle-amb:
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-oracle:${ORACLE_TAG:-local} image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-oracle:${ORACLE_TAG:-local}
build:
context: ..
dockerfile: oracle/Dockerfile
env_file: ../e2e-commons/components-envs/oracle-amb.env env_file: ../e2e-commons/components-envs/oracle-amb.env
environment: environment:
- NODE_ENV=production - NODE_ENV=production
@ -78,25 +62,6 @@ services:
command: "true" command: "true"
networks: networks:
- ultimate - ultimate
monitor:
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-monitor:${MONITOR_TAG:-local}
build:
context: ..
dockerfile: monitor/Dockerfile
env_file: ../e2e-commons/components-envs/monitor.env
entrypoint: yarn check-and-start
ports:
- "3010:3010"
networks:
- ultimate
monitor-erc20:
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-monitor:${MONITOR_TAG:-local}
env_file: ../e2e-commons/components-envs/monitor-erc20.env
entrypoint: yarn check-and-start
ports:
- "3011:3011"
networks:
- ultimate
monitor-erc20-native: monitor-erc20-native:
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-monitor:${MONITOR_TAG:-local} image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-monitor:${MONITOR_TAG:-local}
env_file: ../e2e-commons/components-envs/monitor-erc20-native.env env_file: ../e2e-commons/components-envs/monitor-erc20-native.env
@ -107,6 +72,9 @@ services:
- ultimate - ultimate
monitor-amb: monitor-amb:
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-monitor:${MONITOR_TAG:-local} image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-monitor:${MONITOR_TAG:-local}
build:
context: ..
dockerfile: monitor/Dockerfile
env_file: ../e2e-commons/components-envs/monitor-amb.env env_file: ../e2e-commons/components-envs/monitor-amb.env
entrypoint: yarn check-and-start entrypoint: yarn check-and-start
ports: ports:

@ -5,6 +5,7 @@ if [ $CI ]; then exit $rc; fi
ps | grep node | grep -v grep | grep -v yarn | awk '{print "kill " $1}' | /bin/bash ps | grep node | grep -v grep | grep -v yarn | awk '{print "kill " $1}' | /bin/bash
docker-compose down docker-compose down
docker-compose -p validator1 down
docker-compose -p validator2 down docker-compose -p validator2 down
docker-compose -p validator3 down docker-compose -p validator3 down
docker network rm ultimate || true docker network rm ultimate || true

@ -5,9 +5,11 @@ set -e # exit when any command fails
docker-compose pull e2e docker-compose pull e2e
while [ "$1" != "" ]; do while [ "$1" != "" ]; do
if [ "$1" == "oracle" ]; then if [ "$1" == "oracle" ]; then
docker-compose pull oracle docker-compose pull oracle-amb
elif [ "$1" == "alm-e2e" ]; then
docker-compose pull oracle-amb
elif [ "$1" == "monitor" ]; then elif [ "$1" == "monitor" ]; then
docker-compose pull monitor docker-compose pull monitor-amb
elif [ "$1" == "alm" ]; then elif [ "$1" == "alm" ]; then
docker-compose pull alm docker-compose pull alm
fi fi

@ -9,26 +9,13 @@ ENVS_PATH="../contracts-envs"
# mock bridge validators contract with the one with deterministic isValidatorDuty # mock bridge validators contract with the one with deterministic isValidatorDuty
mv "$CONTRACTS_PATH/build/contracts/BridgeValidatorsDeterministic.json" "$CONTRACTS_PATH/build/contracts/BridgeValidators.json" mv "$CONTRACTS_PATH/build/contracts/BridgeValidatorsDeterministic.json" "$CONTRACTS_PATH/build/contracts/BridgeValidators.json"
echo -e "\n\n############ Deploying native-to-erc ############\n"
cp "$ENVS_PATH/native-to-erc.env" "$DEPLOY_PATH/.env"
cd "$DEPLOY_PATH"
node deploy.js
cd - > /dev/null
echo -e "\n\n############ Deploying erc20 and erc-to-erc ############\n"
node deployERC20.js
cp "$ENVS_PATH/erc-to-erc.env" "$DEPLOY_PATH/.env"
cd "$DEPLOY_PATH"
node deploy.js
cd - > /dev/null
echo -e "\n\n############ Deploying block reward ############\n" echo -e "\n\n############ Deploying block reward ############\n"
cp "$ENVS_PATH/erc-to-native.env" "$DEPLOY_PATH/.env"
cd "$DEPLOY_PATH" cd "$DEPLOY_PATH"
node src/utils/deployBlockReward.js node src/utils/deployBlockReward.js
cd - > /dev/null cd - > /dev/null
echo -e "\n\n############ Deploying erc-to-native ############\n" echo -e "\n\n############ Deploying erc-to-native ############\n"
cp "$ENVS_PATH/erc-to-native.env" "$DEPLOY_PATH/.env"
cd "$DEPLOY_PATH" cd "$DEPLOY_PATH"
node deploy.js node deploy.js
cd - > /dev/null cd - > /dev/null

@ -1,43 +0,0 @@
const path = require('path')
const { user } = require('../constants.json')
const contractsPath = '../../contracts'
require('dotenv').config({
path: path.join(__dirname, contractsPath, '/deploy/.env')
})
const { deployContract, sendRawTxHome, privateKeyToAddress } = require(`${contractsPath}/deploy/src/deploymentUtils`)
const { web3Home, deploymentPrivateKey } = require(`${contractsPath}/deploy/src/web3`)
const ERC677BridgeTokenRewardable = require(`${contractsPath}/build/contracts/ERC677BridgeTokenRewardable.json`)
const { DEPLOYMENT_ACCOUNT_PRIVATE_KEY } = process.env
const DEPLOYMENT_ACCOUNT_ADDRESS = privateKeyToAddress(DEPLOYMENT_ACCOUNT_PRIVATE_KEY)
async function deployBridgeTokenRewardable() {
try {
let homeNonce = await web3Home.eth.getTransactionCount(DEPLOYMENT_ACCOUNT_ADDRESS)
console.log('\n[Home] Deploying ERC677BridgeTokenRewardable Test token')
const stakeToken = await deployContract(ERC677BridgeTokenRewardable, ['STAKE', 'STAKE', '18', '77'], {
from: DEPLOYMENT_ACCOUNT_ADDRESS,
network: 'home',
nonce: homeNonce
})
homeNonce++
console.log('[Home] Stake Token: ', stakeToken.options.address)
const mintData = await stakeToken.methods
.mint(user.address, '500000000000000000000')
.encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS })
await sendRawTxHome({
data: mintData,
nonce: homeNonce,
to: stakeToken.options.address,
privateKey: deploymentPrivateKey,
url: process.env.HOME_RPC_URL
})
} catch (e) {
console.log(e)
throw e
}
}
deployBridgeTokenRewardable()

@ -1,51 +0,0 @@
/* eslint import/no-unresolved: 0 node/no-missing-require: 0 */
const path = require('path')
const {user} = require('../constants.json')
const contractsPath = '../../contracts';
require('dotenv').config({
path: path.join(__dirname, contractsPath, '/deploy/.env')
})
const {
deployContract,
sendRawTxForeign,
privateKeyToAddress
} = require(`${contractsPath}/deploy/src/deploymentUtils`)
const {
web3Foreign,
deploymentPrivateKey
} = require(`${contractsPath}/deploy/src/web3`)
const POA20 = require(`${contractsPath}/build/contracts/ERC677BridgeToken.json`)
const { DEPLOYMENT_ACCOUNT_PRIVATE_KEY } = process.env
const DEPLOYMENT_ACCOUNT_ADDRESS = privateKeyToAddress(DEPLOYMENT_ACCOUNT_PRIVATE_KEY)
async function deployErc20() {
try {
let foreignNonce = await web3Foreign.eth.getTransactionCount(DEPLOYMENT_ACCOUNT_ADDRESS)
console.log('\n[Foreign] Deploying POA20 Test token')
const poa20foreign = await deployContract(POA20, ['POA ERC20 Test', 'POA20', 18], {
from: DEPLOYMENT_ACCOUNT_ADDRESS,
network: 'foreign',
nonce: foreignNonce
})
foreignNonce++
console.log('[Foreign] POA20 Test: ', poa20foreign.options.address)
const mintData = await poa20foreign.methods
.mint(user.address, '500000000000000000000')
.encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS })
await sendRawTxForeign({
data: mintData,
nonce: foreignNonce,
to: poa20foreign.options.address,
privateKey: deploymentPrivateKey,
url: process.env.FOREIGN_RPC_URL
})
} catch (e) {
console.log(e)
throw e;
}
}
deployErc20()

@ -1,43 +0,0 @@
const path = require('path')
const { user } = require('../constants.json')
const contractsPath = '../../contracts'
require('dotenv').config({
path: path.join(__dirname, contractsPath, '/deploy/.env')
})
const { deployContract, sendRawTxForeign, privateKeyToAddress } = require(`${contractsPath}/deploy/src/deploymentUtils`)
const { web3Foreign, deploymentPrivateKey } = require(`${contractsPath}/deploy/src/web3`)
const ERC677MultiBridgeToken = require(`${contractsPath}/build/contracts/ERC677MultiBridgeToken.json`)
const { DEPLOYMENT_ACCOUNT_PRIVATE_KEY } = process.env
const DEPLOYMENT_ACCOUNT_ADDRESS = privateKeyToAddress(DEPLOYMENT_ACCOUNT_PRIVATE_KEY)
async function deployMultiBridgeToken() {
try {
let foreignNonce = await web3Foreign.eth.getTransactionCount(DEPLOYMENT_ACCOUNT_ADDRESS)
console.log('\n[Foreign] Deploying ERC677MultiBridgeToken Test token')
const stakeToken = await deployContract(ERC677MultiBridgeToken, ['STAKE', 'STAKE', '18', '42'], {
from: DEPLOYMENT_ACCOUNT_ADDRESS,
network: 'foreign',
nonce: foreignNonce
})
foreignNonce++
console.log('[Foreign] Stake Token: ', stakeToken.options.address)
const mintData = await stakeToken.methods
.mint(user.address, '500000000000000000000')
.encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS })
await sendRawTxForeign({
data: mintData,
nonce: foreignNonce,
to: stakeToken.options.address,
privateKey: deploymentPrivateKey,
url: process.env.FOREIGN_RPC_URL
})
} catch (e) {
console.log(e)
throw e
}
}
deployMultiBridgeToken()

@ -15,64 +15,42 @@ docker network create --driver bridge ultimate || true
docker-compose up -d parity1 parity2 e2e docker-compose up -d parity1 parity2 e2e
startValidator () { startValidator () {
docker-compose $1 run -d --name $4 redis db_env="-e ORACLE_QUEUE_URL=amqp://$4 -e ORACLE_REDIS_URL=redis://$3"
docker-compose $1 run -d --name $5 rabbit
if [[ -z "$MODE" || "$MODE" == native-to-erc ]]; then docker-compose $1 run -d --name $3 redis
docker-compose $1 run $2 $3 -d oracle yarn watcher:signature-request docker-compose $1 run -d --name $4 rabbit
docker-compose $1 run $2 $3 -d oracle yarn watcher:collected-signatures
docker-compose $1 run $2 $3 -d oracle yarn watcher:affirmation-request
fi
if [[ -z "$MODE" || "$MODE" == erc-to-erc ]]; then
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:signature-request
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:collected-signatures
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:affirmation-request
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:transfer
fi
if [[ -z "$MODE" || "$MODE" == erc-to-native ]]; then if [[ -z "$MODE" || "$MODE" == erc-to-native ]]; then
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:signature-request docker-compose $1 run $2 $db_env -d oracle-erc20-native yarn watcher:signature-request
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:collected-signatures docker-compose $1 run $2 $db_env -d oracle-erc20-native yarn watcher:collected-signatures
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:affirmation-request docker-compose $1 run $2 $db_env -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 $db_env -d oracle-erc20-native yarn watcher:transfer
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn worker:convert-to-chai
fi fi
if [[ -z "$MODE" || "$MODE" == amb ]]; then if [[ -z "$MODE" || "$MODE" == amb ]]; then
docker-compose $1 run $2 $3 -d oracle-amb yarn watcher:signature-request docker-compose $1 run $2 $db_env -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 $db_env -d oracle-amb yarn watcher:collected-signatures
docker-compose $1 run $2 $3 -d oracle-amb yarn watcher:affirmation-request docker-compose $1 run $2 $db_env -d oracle-amb yarn watcher:affirmation-request
docker-compose $1 run $2 $db_env -d oracle-amb yarn watcher:information-request
fi fi
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn sender:home
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn sender:foreign
docker-compose $1 run $2 $3 -d oracle yarn manager:shutdown
}
startAMBValidator () { docker-compose $1 run $2 $db_env -d oracle-amb yarn sender:home
docker-compose $1 run -d --name $4 redis docker-compose $1 run $2 $db_env -d oracle-amb yarn sender:foreign
docker-compose $1 run -d --name $5 rabbit docker-compose $1 run $2 $db_env -d oracle-amb yarn manager:shutdown
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
docker-compose $1 run $2 $3 -d oracle-amb yarn sender:home
docker-compose $1 run $2 $3 -d oracle-amb yarn sender:foreign
docker-compose $1 run $2 $3 -d oracle-amb yarn manager:shutdown
} }
while [ "$1" != "" ]; do while [ "$1" != "" ]; do
if [ "$1" == "oracle" ]; then if [ "$1" == "oracle" ]; then
startValidator "" "" "" "redis" "rabbit" startValidator "-p validator1" "" redis rabbit
fi fi
if [ "$1" == "oracle-validator-2" ]; then if [ "$1" == "oracle-validator-2" ]; then
oracle2name="-p validator2"
oracle2Values="-e ORACLE_VALIDATOR_ADDRESS=0xdCC784657C78054aa61FbcFFd2605F32374816A4 -e ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=5a5c3645d0f04e9eb4f27f94ed4c244a225587405b8838e7456f7781ce3a9513" oracle2Values="-e ORACLE_VALIDATOR_ADDRESS=0xdCC784657C78054aa61FbcFFd2605F32374816A4 -e ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=5a5c3645d0f04e9eb4f27f94ed4c244a225587405b8838e7456f7781ce3a9513"
oracle2comp="-e ORACLE_QUEUE_URL=amqp://rabbit2 -e ORACLE_REDIS_URL=redis://redis2" startValidator "-p validator2" "$oracle2Values" redis2 rabbit2
startValidator "$oracle2name" "$oracle2Values" "$oracle2comp" "redis2" "rabbit2"
fi fi
if [ "$1" == "oracle-validator-3" ]; then if [ "$1" == "oracle-validator-3" ]; then
oracle3name="-p validator3"
oracle3Values="-e ORACLE_VALIDATOR_ADDRESS=0xDcef88209a20D52165230104B245803C3269454d -e ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=f877f62a1c19f852cff1d29f0fb1ecac18821c0080d4cc0520c60c098293dca1" oracle3Values="-e ORACLE_VALIDATOR_ADDRESS=0xDcef88209a20D52165230104B245803C3269454d -e ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=f877f62a1c19f852cff1d29f0fb1ecac18821c0080d4cc0520c60c098293dca1"
oracle3comp="-e ORACLE_QUEUE_URL=amqp://rabbit3 -e ORACLE_REDIS_URL=redis://redis3" startValidator "-p validator3" "$oracle3Values" redis3 rabbit3
startValidator "$oracle3name" "$oracle3Values" "$oracle3comp" "redis3" "rabbit3"
fi fi
if [ "$1" == "alm" ]; then if [ "$1" == "alm" ]; then
@ -94,33 +72,25 @@ while [ "$1" != "" ]; do
amb) amb)
docker-compose up -d monitor-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) erc-to-native)
docker-compose up -d monitor-erc20-native docker-compose up -d monitor-erc20-native
;; ;;
*) *)
docker-compose up -d monitor monitor-erc20 monitor-erc20-native monitor-amb docker-compose up -d monitor-erc20-native monitor-amb
;; ;;
esac esac
fi fi
if [ "$1" == "alm-e2e" ]; then if [ "$1" == "alm-e2e" ]; then
startAMBValidator "" "" "" "redis" "rabbit" MODE=amb
startValidator "-p validator1" "" redis rabbit
oracle2name="-p validator2"
oracle2Values="-e ORACLE_VALIDATOR_ADDRESS=0xdCC784657C78054aa61FbcFFd2605F32374816A4 -e ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=5a5c3645d0f04e9eb4f27f94ed4c244a225587405b8838e7456f7781ce3a9513" oracle2Values="-e ORACLE_VALIDATOR_ADDRESS=0xdCC784657C78054aa61FbcFFd2605F32374816A4 -e ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=5a5c3645d0f04e9eb4f27f94ed4c244a225587405b8838e7456f7781ce3a9513"
oracle2comp="-e ORACLE_QUEUE_URL=amqp://rabbit2 -e ORACLE_REDIS_URL=redis://redis2" startValidator "-p validator2" "$oracle2Values" redis2 rabbit2
startAMBValidator "$oracle2name" "$oracle2Values" "$oracle2comp" "redis2" "rabbit2"
oracle3name="-p validator3"
oracle3Values="-e ORACLE_VALIDATOR_ADDRESS=0xDcef88209a20D52165230104B245803C3269454d -e ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=f877f62a1c19f852cff1d29f0fb1ecac18821c0080d4cc0520c60c098293dca1" oracle3Values="-e ORACLE_VALIDATOR_ADDRESS=0xDcef88209a20D52165230104B245803C3269454d -e ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=f877f62a1c19f852cff1d29f0fb1ecac18821c0080d4cc0520c60c098293dca1"
oracle3comp="-e ORACLE_QUEUE_URL=amqp://rabbit3 -e ORACLE_REDIS_URL=redis://redis3" startValidator "-p validator3" "$oracle3Values" redis3 rabbit3
startAMBValidator "$oracle3name" "$oracle3Values" "$oracle3comp" "redis3" "rabbit3"
fi fi
shift # Shift all the parameters down by one shift # Shift all the parameters down by one

@ -14,7 +14,7 @@
"axios": "0.19.0" "axios": "0.19.0"
}, },
"engines": { "engines": {
"node": ">= 10.18" "node": ">= 12.22"
}, },
"devDependencies": {} "devDependencies": {}
} }

@ -1,15 +1,9 @@
while true; do while true; do
docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor yarn check-all
pid1=$!
docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20 yarn check-all
pid2=$!
docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20-native yarn check-all docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20-native yarn check-all
pid3=$! pid1=$!
docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-amb yarn check-all docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-amb yarn check-all
pid4=$! pid2=$!
wait $pid1 wait $pid1
wait $pid2 wait $pid2
wait $pid3
wait $pid4
done done

@ -5,12 +5,6 @@ case "$mode" in
amb) amb)
script=./test/amb.js script=./test/amb.js
;; ;;
native-to-erc)
script=./test/nativeToErc.js
;;
erc-to-erc)
script=./test/ercToErc.js
;;
erc-to-native) erc-to-native)
script=./test/ercToNative.js script=./test/ercToNative.js
;; ;;

@ -1,12 +1,8 @@
const assert = require('assert') const assert = require('assert')
const axios = require('axios') const axios = require('axios')
const { nativeToErcBridge, ercToErcBridge, ercToNativeBridge, validator } = require('../../e2e-commons/constants.json') const { ercToNativeBridge, validator } = require('../../e2e-commons/constants.json')
const types = [ const types = [{ description: 'ERC TO NATIVE', baseUrl: ercToNativeBridge.monitor }]
{ description: 'NATIVE TO ERC', baseUrl: nativeToErcBridge.monitor },
{ description: 'ERC TO ERC', baseUrl: ercToErcBridge.monitor },
{ description: 'ERC TO NATIVE', baseUrl: ercToNativeBridge.monitor }
]
types.forEach(type => { types.forEach(type => {
describe(type.description, () => { describe(type.description, () => {

@ -1,43 +0,0 @@
const assert = require('assert')
const axios = require('axios')
const { ercToErcBridge, user, foreignRPC, validator } = require('../../e2e-commons/constants.json')
const { waitUntil, sendTokens, addValidator } = require('../utils')
const baseUrl = ercToErcBridge.monitor
describe('ERC TO ERC', () => {
let data
before(async () => {
;({ data } = await axios.get(`${baseUrl}`))
})
it('balance', () => assert(parseInt(data.foreign.erc20Balance, 10) >= 0))
it('should contain totalSupply', () => assert(data.home.totalSupply === '0'))
})
describe('ERC TO ERC with changing state of contracts', () => {
let data
before(async () => {
assert((await axios.get(`${baseUrl}`)).data.balanceDiff === 0)
assert((await axios.get(`${baseUrl}/validators`)).data.validatorsMatch === true)
})
it('should change balanceDiff', async () => {
await sendTokens(foreignRPC.URL, user, ercToErcBridge.foreignToken, ercToErcBridge.foreign)
await waitUntil(async () => {
;({ data } = await axios.get(`${baseUrl}`))
return data.balanceDiff !== 0
})
})
it('should change validatorsMatch', async () => {
await addValidator(foreignRPC.URL, validator, ercToErcBridge.foreign)
await waitUntil(async () => {
;({ data } = await axios.get(`${baseUrl}/validators`))
return data.validatorsMatch === false
})
})
})

@ -1,14 +1,7 @@
const assert = require('assert') const assert = require('assert')
const axios = require('axios') const axios = require('axios')
const { ercToNativeBridge, user, foreignRPC, validator } = require('../../e2e-commons/constants.json') const { ercToNativeBridge, user, foreignRPC, validator } = require('../../e2e-commons/constants.json')
const { const { waitUntil, sendTokens, addValidator } = require('../utils')
waitUntil,
sendTokens,
addValidator,
initializeChaiToken,
convertDaiToChai,
setMinDaiTokenBalance
} = require('../utils')
const baseUrl = ercToNativeBridge.monitor const baseUrl = ercToNativeBridge.monitor
@ -52,58 +45,4 @@ describe('ERC TO NATIVE with changing state of contracts', () => {
return data.validatorsMatch === false return data.validatorsMatch === false
}) })
}) })
it('should consider chai token balance', async function() {
this.timeout(120000)
await initializeChaiToken(foreignRPC.URL, ercToNativeBridge.foreign)
await sendTokens(foreignRPC.URL, user, ercToNativeBridge.foreignToken, ercToNativeBridge.foreign)
await waitUntil(async () => {
;({ data } = await axios.get(`${baseUrl}`))
if (!data.foreign) {
return false
}
const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
return (
data.balanceDiff === 0.02 &&
erc20Balance === '0.02' &&
investedErc20Balance === '0' &&
accumulatedInterest === '0.001' // value of dsrBalance() is initially defined in genesis block as 0.001
)
})
await setMinDaiTokenBalance(foreignRPC.URL, ercToNativeBridge.foreign, '0.01')
await convertDaiToChai(foreignRPC.URL, ercToNativeBridge.foreign)
await waitUntil(async () => {
;({ data } = await axios.get(`${baseUrl}`))
if (!data.foreign) {
return false
}
const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
return (
data.balanceDiff === 0.02 &&
erc20Balance === '0.01' &&
investedErc20Balance === '0.01' &&
accumulatedInterest === '0.001'
)
})
await setMinDaiTokenBalance(foreignRPC.URL, ercToNativeBridge.foreign, '0.005')
await convertDaiToChai(foreignRPC.URL, ercToNativeBridge.foreign)
await waitUntil(async () => {
;({ data } = await axios.get(`${baseUrl}`))
if (!data.foreign) {
return false
}
const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign
return (
data.balanceDiff === 0.02 &&
erc20Balance === '0.005' &&
investedErc20Balance === '0.015' &&
accumulatedInterest === '0.001'
)
})
})
}) })

@ -1,43 +0,0 @@
const assert = require('assert')
const axios = require('axios')
const { nativeToErcBridge, user, homeRPC, foreignRPC, validator } = require('../../e2e-commons/constants.json')
const { waitUntil, sendEther, addValidator } = require('../utils')
const baseUrl = nativeToErcBridge.monitor
describe('NATIVE TO ERC', () => {
let data
before(async () => {
;({ data } = await axios.get(`${baseUrl}`))
})
it('balance', () => assert(parseInt(data.home.balance, 10) >= 0))
it('should contain totalSupply', () => assert(data.foreign.totalSupply === '0'))
})
describe('NATIVE TO ERC with changing state of contracts', () => {
let data
before(async () => {
assert((await axios.get(`${baseUrl}`)).data.balanceDiff === 0)
assert((await axios.get(`${baseUrl}/validators`)).data.validatorsMatch === true)
})
it('should change balanceDiff', async () => {
await sendEther(homeRPC.URL, user, nativeToErcBridge.home)
await waitUntil(async () => {
;({ data } = await axios.get(`${baseUrl}`))
return data.balanceDiff !== 0
})
})
it('should change validatorsMatch', async () => {
await addValidator(foreignRPC.URL, validator, nativeToErcBridge.foreign)
await waitUntil(async () => {
;({ data } = await axios.get(`${baseUrl}/validators`))
return data.validatorsMatch === false
})
})
})

@ -1,12 +1,5 @@
const Web3 = require('web3') const Web3 = require('web3')
const { const { ERC20_ABI, BRIDGE_VALIDATORS_ABI, FOREIGN_ERC_TO_NATIVE_ABI, BOX_ABI } = require('../commons')
ERC677_BRIDGE_TOKEN_ABI,
BRIDGE_VALIDATORS_ABI,
FOREIGN_NATIVE_TO_ERC_ABI,
FOREIGN_ERC_TO_NATIVE_ABI,
BOX_ABI
} = require('../commons')
const { validator } = require('../e2e-commons/constants')
const waitUntil = async (predicate, step = 100, timeout = 60000) => { const waitUntil = async (predicate, step = 100, timeout = 60000) => {
const stopTime = Date.now() + timeout const stopTime = Date.now() + timeout
@ -36,7 +29,7 @@ const sendEther = async (rpcUrl, account, to) => {
const sendTokens = async (rpcUrl, account, tokenAddress, recipientAddress) => { const sendTokens = async (rpcUrl, account, tokenAddress, recipientAddress) => {
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 erc20Token = new web3.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, tokenAddress) const erc20Token = new web3.eth.Contract(ERC20_ABI, tokenAddress)
await erc20Token.methods.transfer(recipientAddress, web3.utils.toWei('0.01')).send({ await erc20Token.methods.transfer(recipientAddress, web3.utils.toWei('0.01')).send({
from: account.address, from: account.address,
@ -62,7 +55,7 @@ const sendAMBMessage = async (rpcUrl, account, boxAddress, bridgeAddress, boxOth
const addValidator = async (rpcUrl, account, bridgeAddress) => { const addValidator = async (rpcUrl, account, bridgeAddress) => {
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 bridgeContract = new web3.eth.Contract(FOREIGN_NATIVE_TO_ERC_ABI, bridgeAddress) const bridgeContract = new web3.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, bridgeAddress)
const foreignValidatorsAddress = await bridgeContract.methods.validatorContract().call() const foreignValidatorsAddress = await bridgeContract.methods.validatorContract().call()
const foreignBridgeValidators = new web3.eth.Contract(BRIDGE_VALIDATORS_ABI, foreignValidatorsAddress) const foreignBridgeValidators = new web3.eth.Contract(BRIDGE_VALIDATORS_ABI, foreignValidatorsAddress)
await foreignBridgeValidators.methods.addValidator('0xE71FBa5db00172bb0C93d649362B006300000935').send({ await foreignBridgeValidators.methods.addValidator('0xE71FBa5db00172bb0C93d649362B006300000935').send({
@ -71,46 +64,10 @@ const addValidator = async (rpcUrl, account, bridgeAddress) => {
}) })
} }
const initializeChaiToken = async (rpcUrl, bridgeAddress) => {
const web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl))
web3.eth.accounts.wallet.add(validator.privateKey)
const bridgeContract = new web3.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, bridgeAddress)
await bridgeContract.methods.initializeChaiToken().send({
from: validator.address,
gas: '1000000'
})
}
const setMinDaiTokenBalance = async (rpcUrl, bridgeAddress, limit) => {
const web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl))
web3.eth.accounts.wallet.add(validator.privateKey)
const bridgeContract = new web3.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, bridgeAddress)
await bridgeContract.methods.setMinDaiTokenBalance(web3.utils.toWei(limit)).send({
from: validator.address,
gas: '1000000'
})
}
const convertDaiToChai = async (rpcUrl, bridgeAddress) => {
const web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl))
web3.eth.accounts.wallet.add(validator.privateKey)
const bridgeContract = new web3.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, bridgeAddress)
await bridgeContract.methods.convertDaiToChai().send({
from: validator.address,
gas: '1000000'
})
}
module.exports = { module.exports = {
waitUntil, waitUntil,
sendEther, sendEther,
sendTokens, sendTokens,
addValidator, addValidator,
sendAMBMessage, sendAMBMessage
initializeChaiToken,
setMinDaiTokenBalance,
convertDaiToChai
} }

@ -6,12 +6,6 @@ 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"
if [[ -z "$MODE" || "$MODE" == native-to-erc ]]; then
(docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor /bin/bash -c "$command") || rc=1
fi
if [[ -z "$MODE" || "$MODE" == erc-to-erc ]]; then
(docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20 /bin/bash -c "$command") || rc=1
fi
if [[ -z "$MODE" || "$MODE" == erc-to-native ]]; then 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 (docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20-native /bin/bash -c "$command") || rc=1
fi fi

@ -1,4 +1,4 @@
FROM node:10 as contracts FROM node:12 as contracts
WORKDIR /mono WORKDIR /mono
@ -11,7 +11,7 @@ COPY ./contracts/truffle-config.js ./
COPY ./contracts/contracts ./contracts COPY ./contracts/contracts ./contracts
RUN npm run compile RUN npm run compile
FROM node:10 FROM node:12
WORKDIR /mono WORKDIR /mono
COPY package.json . COPY package.json .

@ -12,12 +12,12 @@ const { web3Home } = require('./utils/web3')
const { COMMON_HOME_BRIDGE_ADDRESS, MONITOR_BRIDGE_NAME } = process.env const { COMMON_HOME_BRIDGE_ADDRESS, MONITOR_BRIDGE_NAME } = process.env
const { HOME_ERC_TO_ERC_ABI } = require('../commons') const { HOME_ERC_TO_NATIVE_ABI } = require('../commons')
async function checkWorker() { async function checkWorker() {
try { try {
createDir(`/responses/${MONITOR_BRIDGE_NAME}`) createDir(`/responses/${MONITOR_BRIDGE_NAME}`)
const homeBridge = new web3Home.eth.Contract(HOME_ERC_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS) const homeBridge = new web3Home.eth.Contract(HOME_ERC_TO_NATIVE_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()') logger.debug('calling getEventsInfo()')

@ -1,6 +1,5 @@
require('dotenv').config() require('dotenv').config()
const logger = require('./logger')('checkWorker3') const logger = require('./logger')('checkWorker3')
const stuckTransfers = require('./stuckTransfers')
const detectMediators = require('./detectMediators') const detectMediators = require('./detectMediators')
const detectFailures = require('./detectFailures') const detectFailures = require('./detectFailures')
const { writeFile, createDir } = require('./utils/file') const { writeFile, createDir } = require('./utils/file')
@ -8,22 +7,13 @@ const { web3Home } = require('./utils/web3')
const { saveCache } = require('./utils/web3Cache') const { saveCache } = require('./utils/web3Cache')
const { MONITOR_BRIDGE_NAME, COMMON_HOME_BRIDGE_ADDRESS } = 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_ERC_TO_NATIVE_ABI, BRIDGE_MODES } = require('../commons')
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_ERC_TO_NATIVE_ABI, COMMON_HOME_BRIDGE_ADDRESS)
const bridgeMode = await getBridgeMode(homeBridge) const bridgeMode = await getBridgeMode(homeBridge)
if (bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC_V1) { if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) {
createDir(`/responses/${MONITOR_BRIDGE_NAME}`)
logger.debug('calling stuckTransfers()')
const transfers = await stuckTransfers()
if (!transfers) throw new Error('transfers is empty: ' + JSON.stringify(transfers))
transfers.ok = transfers.total.length === 0
transfers.health = true
writeFile(`/responses/${MONITOR_BRIDGE_NAME}/stuckTransfers.json`, transfers)
logger.debug('Done')
} else if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) {
createDir(`/responses/${MONITOR_BRIDGE_NAME}`) createDir(`/responses/${MONITOR_BRIDGE_NAME}`)
logger.debug('calling detectMediators()') logger.debug('calling detectMediators()')

@ -12,23 +12,13 @@ const {
COMMON_FOREIGN_BRIDGE_ADDRESS COMMON_FOREIGN_BRIDGE_ADDRESS
} = process.env } = process.env
const { const { ERC20_ABI, BLOCK_REWARD_ABI, HOME_ERC_TO_NATIVE_ABI, FOREIGN_ERC_TO_NATIVE_ABI } = require('../commons')
ERC20_ABI,
ERC677_ABI,
BLOCK_REWARD_ABI,
HOME_ERC_TO_ERC_ABI,
HOME_ERC_TO_NATIVE_ABI,
FOREIGN_ERC_TO_ERC_ABI,
FOREIGN_ERC_TO_NATIVE_ABI,
FOREIGN_NATIVE_TO_ERC_ABI
} = require('../commons')
async function main(bridgeMode, eventsInfo) { async function main(bridgeMode, eventsInfo) {
const { const {
homeBlockNumber, homeBlockNumber,
foreignBlockNumber, foreignBlockNumber,
homeToForeignConfirmations, homeToForeignConfirmations,
foreignToHomeConfirmations,
homeDelayedBlockNumber, homeDelayedBlockNumber,
foreignDelayedBlockNumber foreignDelayedBlockNumber
} = eventsInfo } = eventsInfo
@ -44,14 +34,6 @@ async function main(bridgeMode, eventsInfo) {
0, 0,
...homeToForeignConfirmations.filter(e => e.blockNumber > foreignDelayedBlockNumber).map(e => e.value) ...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)
)
const blockRanges = { const blockRanges = {
startBlockHome: MONITOR_HOME_START_BLOCK, startBlockHome: MONITOR_HOME_START_BLOCK,
@ -60,59 +42,7 @@ async function main(bridgeMode, eventsInfo) {
endBlockForeign: foreignBlockNumber endBlockForeign: foreignBlockNumber
} }
if (bridgeMode === BRIDGE_MODES.ERC_TO_ERC) { if (bridgeMode === BRIDGE_MODES.ERC_TO_NATIVE) {
const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
const erc20Address = await foreignBridge.methods.erc20token().call()
const erc20Contract = new web3Foreign.eth.Contract(ERC20_ABI, erc20Address)
logger.debug('calling erc20Contract.methods.balanceOf')
const foreignErc20Balance = await erc20Contract.methods
.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS)
.call({}, foreignDelayedBlockNumber)
const homeBridge = new web3Home.eth.Contract(HOME_ERC_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
logger.debug('calling homeBridge.methods.erc677token')
const tokenAddress = await homeBridge.methods.erc677token().call()
const tokenContract = new web3Home.eth.Contract(ERC677_ABI, tokenAddress)
logger.debug('calling tokenContract.methods.totalSupply()')
const totalSupply = await tokenContract.methods.totalSupply().call({}, homeDelayedBlockNumber)
const foreignBalanceBN = new BN(foreignErc20Balance).plus(lateForeignConfirmationsTotalValue)
const foreignTotalSupplyBN = new BN(totalSupply).plus(lateHomeConfirmationsTotalValue)
const diff = foreignBalanceBN.minus(foreignTotalSupplyBN).toString(10)
logger.debug('Done')
return {
home: {
totalSupply: Web3Utils.fromWei(totalSupply)
},
foreign: {
erc20Balance: Web3Utils.fromWei(foreignErc20Balance)
},
balanceDiff: Number(Web3Utils.fromWei(diff)),
...blockRanges,
lastChecked: Math.floor(Date.now() / 1000)
}
} else if (bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC || bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC_V1) {
logger.debug('calling web3Home.eth.getBalance')
const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_NATIVE_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
const erc20Address = await foreignBridge.methods.erc677token().call()
const homeBalance = await web3Home.eth.getBalance(COMMON_HOME_BRIDGE_ADDRESS, homeDelayedBlockNumber)
const tokenContract = new web3Foreign.eth.Contract(ERC20_ABI, erc20Address)
logger.debug('calling tokenContract.methods.totalSupply()')
const totalSupply = await tokenContract.methods.totalSupply().call({}, foreignDelayedBlockNumber)
const homeBalanceBN = new BN(homeBalance).plus(lateHomeConfirmationsTotalValue)
const foreignTotalSupplyBN = new BN(totalSupply).plus(lateForeignConfirmationsTotalValue)
const diff = homeBalanceBN.minus(foreignTotalSupplyBN).toString(10)
logger.debug('Done')
return {
home: {
balance: Web3Utils.fromWei(homeBalance)
},
foreign: {
totalSupply: Web3Utils.fromWei(totalSupply)
},
balanceDiff: Number(Web3Utils.fromWei(diff)),
...blockRanges,
lastChecked: Math.floor(Date.now() / 1000)
}
} else if (bridgeMode === BRIDGE_MODES.ERC_TO_NATIVE) {
const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS) const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_NATIVE_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)

@ -22,7 +22,7 @@
"web3": "^1.3.0" "web3": "^1.3.0"
}, },
"engines": { "engines": {
"node": ">= 10.18" "node": ">= 12.22"
}, },
"devDependencies": { "devDependencies": {
"chai": "^4.2.0" "chai": "^4.2.0"

@ -39,7 +39,7 @@ async function getPrometheusMetrics(bridgeName) {
const { home, foreign, ...commonBalances } = balancesFile const { home, foreign, ...commonBalances } = balancesFile
const balanceMetrics = { const balanceMetrics = {
// ERC_TO_ERC or ERC_TO_NATIVE mode // ERC_TO_NATIVE mode
balances_home_value: home.totalSupply, balances_home_value: home.totalSupply,
balances_home_txs_deposit: home.deposits, balances_home_txs_deposit: home.deposits,
balances_home_txs_withdrawal: home.withdrawals, balances_home_txs_withdrawal: home.withdrawals,

@ -1,105 +0,0 @@
require('dotenv').config()
const logger = require('./logger')('stuckTransfers.js')
const { FOREIGN_V1_ABI } = require('../commons/abis')
const { web3Foreign, getForeignBlockNumber } = require('./utils/web3')
const { getPastEvents } = require('./utils/web3Cache')
const { COMMON_FOREIGN_BRIDGE_ADDRESS } = process.env
const MONITOR_FOREIGN_START_BLOCK = Number(process.env.MONITOR_FOREIGN_START_BLOCK) || 0
const ABITransferWithoutData = [
{
anonymous: false,
inputs: [
{
indexed: true,
name: 'from',
type: 'address'
},
{
indexed: true,
name: 'to',
type: 'address'
},
{
indexed: false,
name: 'value',
type: 'uint256'
}
],
name: 'Transfer',
type: 'event'
}
]
const ABIWithData = [
{
anonymous: false,
inputs: [
{
indexed: true,
name: 'from',
type: 'address'
},
{
indexed: true,
name: 'to',
type: 'address'
},
{
indexed: false,
name: 'value',
type: 'uint256'
},
{
indexed: false,
name: 'data',
type: 'bytes'
}
],
name: 'Transfer',
type: 'event'
}
]
function transferWithoutCallback(transfersNormal) {
const txHashes = new Set()
transfersNormal.forEach(transfer => txHashes.add(transfer.transactionHash))
return withData => !txHashes.has(withData.transactionHash)
}
async function main() {
const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_V1_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
logger.debug('calling foreignBridge.methods.erc677token')
const erc20Address = await foreignBridge.methods.erc677token().call()
const tokenContract = new web3Foreign.eth.Contract(ABITransferWithoutData, erc20Address)
const tokenContractWithData = new web3Foreign.eth.Contract(ABIWithData, erc20Address)
logger.debug('getting last block number')
const foreignBlockNumber = await getForeignBlockNumber()
const foreignConfirmations = await foreignBridge.methods.requiredBlockConfirmations().call()
const foreignDelayedBlockNumber = foreignBlockNumber - foreignConfirmations
logger.debug('calling tokenContract.getPastEvents Transfer')
const options = {
event: 'Transfer',
options: {
filter: {
to: COMMON_FOREIGN_BRIDGE_ADDRESS
}
},
fromBlock: MONITOR_FOREIGN_START_BLOCK,
toBlock: foreignBlockNumber,
chain: 'foreign',
safeToBlock: foreignDelayedBlockNumber
}
const transfersNormal = await getPastEvents(tokenContract, options)
logger.debug('calling tokenContractWithData.getPastEvents Transfer')
const transfersWithData = await getPastEvents(tokenContractWithData, options)
const stuckTransfers = transfersNormal.filter(transferWithoutCallback(transfersWithData))
logger.debug('Done')
return {
stuckTransfers,
total: stuckTransfers.length,
lastChecked: Math.floor(Date.now() / 1000)
}
}
module.exports = main

@ -2,13 +2,10 @@ require('dotenv').config()
const logger = require('../logger')('eventsUtils') const logger = require('../logger')('eventsUtils')
const { const {
BRIDGE_MODES, BRIDGE_MODES,
ERC_TYPES,
getBridgeABIs, getBridgeABIs,
getBridgeMode, getBridgeMode,
HOME_ERC_TO_ERC_ABI, HOME_ERC_TO_NATIVE_ABI,
ERC20_ABI, ERC20_ABI,
ERC677_BRIDGE_TOKEN_ABI,
getTokenType,
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
@ -34,24 +31,18 @@ async function main(mode) {
} }
} }
const homeErcBridge = new web3Home.eth.Contract(HOME_ERC_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS) const homeErcBridge = new web3Home.eth.Contract(HOME_ERC_TO_NATIVE_ABI, COMMON_HOME_BRIDGE_ADDRESS)
const bridgeMode = mode || (await getBridgeMode(homeErcBridge)) const bridgeMode = mode || (await getBridgeMode(homeErcBridge))
const { HOME_ABI, FOREIGN_ABI } = getBridgeABIs(bridgeMode) const { HOME_ABI, FOREIGN_ABI } = getBridgeABIs(bridgeMode)
const homeBridge = new web3Home.eth.Contract(HOME_ABI, COMMON_HOME_BRIDGE_ADDRESS) const homeBridge = new web3Home.eth.Contract(HOME_ABI, COMMON_HOME_BRIDGE_ADDRESS)
const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS) const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
const v1Bridge = bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC_V1 let isExternalErc20 = false
let isExternalErc20
let erc20Contract let erc20Contract
let erc20Address let erc20Address
let normalizeEvent = normalizeEventInformation let normalizeEvent = normalizeEventInformation
if (bridgeMode !== BRIDGE_MODES.ARBITRARY_MESSAGE) { if (bridgeMode !== BRIDGE_MODES.ARBITRARY_MESSAGE) {
const erc20MethodName = bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC || v1Bridge ? 'erc677token' : 'erc20token' erc20Address = await foreignBridge.methods.erc20token().call()
erc20Address = await foreignBridge.methods[erc20MethodName]().call() isExternalErc20 = true
const tokenType = await getTokenType(
new web3Foreign.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, erc20Address),
COMMON_FOREIGN_BRIDGE_ADDRESS
)
isExternalErc20 = tokenType === ERC_TYPES.ERC20
erc20Contract = new web3Foreign.eth.Contract(ERC20_ABI, erc20Address) erc20Contract = new web3Foreign.eth.Contract(ERC20_ABI, erc20Address)
} else { } else {
normalizeEvent = e => e normalizeEvent = e => e
@ -104,7 +95,7 @@ async function main(mode) {
logger.debug("calling homeBridge.getPastEvents('UserRequestForSignature')") logger.debug("calling homeBridge.getPastEvents('UserRequestForSignature')")
const homeToForeignRequestsNew = (await getPastEvents(homeBridge, { const homeToForeignRequestsNew = (await getPastEvents(homeBridge, {
event: v1Bridge ? 'Deposit' : 'UserRequestForSignature', event: 'UserRequestForSignature',
fromBlock: homeMigrationBlock, fromBlock: homeMigrationBlock,
toBlock: homeDelayedBlockNumber, toBlock: homeDelayedBlockNumber,
chain: 'home' chain: 'home'
@ -113,7 +104,7 @@ async function main(mode) {
logger.debug("calling foreignBridge.getPastEvents('RelayedMessage')") logger.debug("calling foreignBridge.getPastEvents('RelayedMessage')")
const homeToForeignConfirmations = (await getPastEvents(foreignBridge, { const homeToForeignConfirmations = (await getPastEvents(foreignBridge, {
event: v1Bridge ? 'Deposit' : 'RelayedMessage', event: 'RelayedMessage',
fromBlock: MONITOR_FOREIGN_START_BLOCK, fromBlock: MONITOR_FOREIGN_START_BLOCK,
toBlock: foreignBlockNumber, toBlock: foreignBlockNumber,
chain: 'foreign', chain: 'foreign',
@ -122,7 +113,7 @@ async function main(mode) {
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: 'AffirmationCompleted',
fromBlock: MONITOR_HOME_START_BLOCK, fromBlock: MONITOR_HOME_START_BLOCK,
toBlock: homeBlockNumber, toBlock: homeBlockNumber,
chain: 'home', chain: 'home',
@ -131,7 +122,7 @@ async function main(mode) {
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: 'UserRequestForAffirmation',
fromBlock: foreignMigrationBlock, fromBlock: foreignMigrationBlock,
toBlock: foreignDelayedBlockNumber, toBlock: foreignDelayedBlockNumber,
chain: 'foreign' chain: 'foreign'

@ -4,11 +4,9 @@
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"start": "mocha", "start": "mocha --exit",
"lint": "eslint . --ignore-path ../.eslintignore", "lint": "eslint . --ignore-path ../.eslintignore",
"amb": "mocha test/amb.js", "amb": "mocha test/amb.js",
"native-to-erc": "mocha test/nativeToErc.js",
"erc-to-erc": "mocha test/ercToErc.js",
"erc-to-native": "mocha test/ercToNative.js", "erc-to-native": "mocha test/ercToNative.js",
"alm": "mocha test/amb.js" "alm": "mocha test/amb.js"
}, },
@ -21,11 +19,11 @@
"promise-retry": "^1.1.1", "promise-retry": "^1.1.1",
"shelljs": "^0.8.2", "shelljs": "^0.8.2",
"tree-kill": "^1.2.0", "tree-kill": "^1.2.0",
"web3": "1.0.0-beta.34", "web3": "^1.3.0",
"websocket": "^1.0.28" "websocket": "^1.0.28"
}, },
"engines": { "engines": {
"node": ">= 10.18" "node": ">= 12.22"
}, },
"devDependencies": {} "devDependencies": {}
} }

@ -5,12 +5,6 @@ case "$mode" in
amb) amb)
script=./test/amb.js script=./test/amb.js
;; ;;
native-to-erc)
script=./test/nativeToErc.js
;;
erc-to-erc)
script=./test/ercToErc.js
;;
erc-to-native) erc-to-native)
script=./test/ercToNative.js script=./test/ercToNative.js
;; ;;

@ -10,23 +10,47 @@ const { toBN } = Web3.utils
const homeWeb3 = new Web3(new Web3.providers.HttpProvider(homeRPC.URL)) const homeWeb3 = new Web3(new Web3.providers.HttpProvider(homeRPC.URL))
const foreignWeb3 = new Web3(new Web3.providers.HttpProvider(foreignRPC.URL)) const foreignWeb3 = new Web3(new Web3.providers.HttpProvider(foreignRPC.URL))
const COMMON_HOME_BRIDGE_ADDRESS = amb.home
const COMMON_FOREIGN_BRIDGE_ADDRESS = amb.foreign
homeWeb3.eth.accounts.wallet.add(user.privateKey) homeWeb3.eth.accounts.wallet.add(user.privateKey)
homeWeb3.eth.accounts.wallet.add(validator.privateKey) homeWeb3.eth.accounts.wallet.add(validator.privateKey)
foreignWeb3.eth.accounts.wallet.add(user.privateKey) 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 opts = {
const blockHomeBox = new homeWeb3.eth.Contract(BOX_ABI, amb.blockedHomeBox) from: user.address,
const foreignBox = new foreignWeb3.eth.Contract(BOX_ABI, amb.foreignBox) gas: 400000,
const homeBridge = new homeWeb3.eth.Contract(HOME_AMB_ABI, COMMON_HOME_BRIDGE_ADDRESS) gasPrice: '1'
const foreignBridge = new foreignWeb3.eth.Contract(FOREIGN_AMB_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS) }
const homeBox = new homeWeb3.eth.Contract(BOX_ABI, amb.homeBox, opts)
const blockHomeBox = new homeWeb3.eth.Contract(BOX_ABI, amb.blockedHomeBox, opts)
const foreignBox = new foreignWeb3.eth.Contract(BOX_ABI, amb.foreignBox, opts)
const homeBridge = new homeWeb3.eth.Contract(HOME_AMB_ABI, amb.home, opts)
const foreignBridge = new foreignWeb3.eth.Contract(FOREIGN_AMB_ABI, amb.foreign, opts)
describe('arbitrary message bridging', () => { describe('arbitrary message bridging', () => {
let requiredSignatures = 1 let requiredSignatures = 1
before(async () => { before(async () => {
const allowedMethods = [
'eth_call(address,bytes)',
'eth_call(address,bytes,uint256)',
'eth_call(address,address,uint256,bytes)',
'eth_blockNumber()',
'eth_getBlockByNumber()',
'eth_getBlockByNumber(uint256)',
'eth_getBlockByHash(bytes32)',
'eth_getBalance(address)',
'eth_getBalance(address,uint256)',
'eth_getTransactionCount(address)',
'eth_getTransactionCount(address,uint256)',
'eth_getTransactionByHash(bytes32)',
'eth_getTransactionReceipt(bytes32)',
'eth_getStorageAt(address,bytes32)',
'eth_getStorageAt(address,bytes32,uint256)'
]
for (const method of allowedMethods) {
const selector = homeWeb3.utils.soliditySha3(method)
await homeBridge.methods.enableAsyncRequestSelector(selector, true).send({ from: validator.address })
}
// 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') {
return return
@ -66,10 +90,7 @@ describe('arbitrary message bridging', () => {
await homeBox.methods await homeBox.methods
.setValueOnOtherNetwork(newValue, amb.home, amb.foreignBox) .setValueOnOtherNetwork(newValue, amb.home, amb.foreignBox)
.send({ .send()
from: user.address,
gas: '400000'
})
.catch(e => { .catch(e => {
console.error(e) console.error(e)
}) })
@ -98,10 +119,7 @@ describe('arbitrary message bridging', () => {
await blockHomeBox.methods await blockHomeBox.methods
.setValueOnOtherNetwork(newValue, amb.home, amb.foreignBox) .setValueOnOtherNetwork(newValue, amb.home, amb.foreignBox)
.send({ .send()
from: user.address,
gas: '400000'
})
.catch(e => { .catch(e => {
console.error(e) console.error(e)
}) })
@ -137,10 +155,7 @@ describe('arbitrary message bridging', () => {
await homeBox.methods await homeBox.methods
.setValueOnOtherNetworkUsingManualLane(newValue, amb.home, amb.foreignBox) .setValueOnOtherNetworkUsingManualLane(newValue, amb.home, amb.foreignBox)
.send({ .send()
from: user.address,
gas: '400000'
})
.catch(e => { .catch(e => {
console.error(e) console.error(e)
}) })
@ -173,10 +188,7 @@ describe('arbitrary message bridging', () => {
await foreignBox.methods await foreignBox.methods
.setValueOnOtherNetwork(newValue, amb.foreign, amb.homeBox) .setValueOnOtherNetwork(newValue, amb.foreign, amb.homeBox)
.send({ .send()
from: user.address,
gas: '400000'
})
.catch(e => { .catch(e => {
console.error(e) console.error(e)
}) })
@ -191,4 +203,363 @@ describe('arbitrary message bridging', () => {
}) })
}) })
}) })
describe('Home to Foreign Async Call', () => {
async function makeAsyncCall(selector, data) {
const prevMessageId = await homeBox.methods.messageId().call()
await homeBox.methods
.makeAsyncCall(amb.home, selector, data)
.send()
.catch(e => {
console.error(e)
})
// check that value changed and balance decreased
await uniformRetry(async retry => {
const messageId = await homeBox.methods.messageId().call()
if (messageId === prevMessageId) {
retry()
}
})
}
it('should make async eth_call', async () => {
const foreignValue = await foreignBox.methods.value().call()
const selector = homeWeb3.utils.soliditySha3('eth_call(address,bytes)')
const data = homeWeb3.eth.abi.encodeParameters(
['address', 'bytes'],
[amb.foreignBox, foreignBox.methods.value().encodeABI()]
)
await makeAsyncCall(selector, data)
assert(await homeBox.methods.status().call(), 'status is false')
assert.strictEqual(
await homeBox.methods.data().call(),
homeWeb3.eth.abi.encodeParameters(['bytes'], [homeWeb3.eth.abi.encodeParameter('uint256', foreignValue)]),
'returned data is incorrect'
)
})
it('should make async eth_call with 4 arguments', async () => {
const foreignValue = await foreignBox.methods.value().call()
const selector = homeWeb3.utils.soliditySha3('eth_call(address,address,uint256,bytes)')
const data1 = homeWeb3.eth.abi.encodeParameters(
['address', 'address', 'uint256', 'bytes'],
[amb.foreignBox, user.address, '100000', foreignBox.methods.value().encodeABI()]
)
await makeAsyncCall(selector, data1)
assert(await homeBox.methods.status().call(), 'status is false')
assert.strictEqual(
await homeBox.methods.data().call(),
homeWeb3.eth.abi.encodeParameters(['bytes'], [homeWeb3.eth.abi.encodeParameter('uint256', foreignValue)]),
'returned data is incorrect'
)
const data2 = homeWeb3.eth.abi.encodeParameters(
['address', 'address', 'uint256', 'bytes'],
[amb.foreignBox, user.address, '1000', foreignBox.methods.value().encodeABI()]
)
await makeAsyncCall(selector, data2)
assert(!(await homeBox.methods.status().call()), 'status is true')
assert.strictEqual(await homeBox.methods.data().call(), null, 'returned data is incorrect')
const data3 = homeWeb3.eth.abi.encodeParameters(
['address', 'address', 'uint256', 'bytes'],
[amb.foreignBox, user.address, '21300', foreignBox.methods.value().encodeABI()]
)
await makeAsyncCall(selector, data3)
assert(!(await homeBox.methods.status().call()), 'status is true')
assert.strictEqual(await homeBox.methods.data().call(), null, 'returned data is incorrect')
})
it('should make async eth_call for specific block', async () => {
const foreignValue = await foreignBox.methods.value().call()
const blockNumber = await foreignWeb3.eth.getBlockNumber()
const selector = homeWeb3.utils.soliditySha3('eth_call(address,bytes,uint256)')
const data1 = homeWeb3.eth.abi.encodeParameters(
['address', 'bytes', 'uint256'],
[amb.foreignBox, foreignBox.methods.value().encodeABI(), 60]
)
const data2 = homeWeb3.eth.abi.encodeParameters(
['address', 'bytes', 'uint256'],
[amb.foreignBox, foreignBox.methods.value().encodeABI(), blockNumber - 2]
)
const data3 = homeWeb3.eth.abi.encodeParameters(
['address', 'bytes', 'uint256'],
[amb.foreignBox, foreignBox.methods.value().encodeABI(), blockNumber + 20]
)
await makeAsyncCall(selector, data1)
assert(await homeBox.methods.status().call(), 'status is false')
assert.strictEqual(
await homeBox.methods.data().call(),
homeWeb3.eth.abi.encodeParameters(['bytes'], [homeWeb3.eth.abi.encodeParameter('uint256', 0)]),
'returned data is incorrect'
)
await makeAsyncCall(selector, data2)
assert(await homeBox.methods.status().call(), 'status is false')
assert.strictEqual(
await homeBox.methods.data().call(),
homeWeb3.eth.abi.encodeParameters(['bytes'], [homeWeb3.eth.abi.encodeParameter('uint256', foreignValue)]),
'returned data is incorrect'
)
await makeAsyncCall(selector, data3)
assert(!(await homeBox.methods.status().call()), 'status is true')
})
it('should make async eth_blockNumber', async () => {
const selector = homeWeb3.utils.soliditySha3('eth_blockNumber()')
await makeAsyncCall(selector, '0x')
assert(await homeBox.methods.status().call(), 'status is false')
assert.strictEqual((await homeBox.methods.data().call()).length, 66, 'invalid block number')
})
it('should make async eth_getBlockByNumber', async () => {
const blockNumber = ((await foreignWeb3.eth.getBlockNumber()) - 5).toString()
const selector = homeWeb3.utils.soliditySha3('eth_getBlockByNumber(uint256)')
await makeAsyncCall(selector, homeWeb3.eth.abi.encodeParameter('uint256', blockNumber))
assert(await homeBox.methods.status().call(), 'status is false')
const data = await homeBox.methods.data().call()
assert.strictEqual(data.length, 2 + 64 * 3)
const { 0: number, 1: hash, 2: miner } = homeWeb3.eth.abi.decodeParameters(
['uint256', 'bytes32', 'address'],
data
)
const block = await foreignWeb3.eth.getBlock(blockNumber)
assert.strictEqual(number, blockNumber, 'wrong block number returned')
assert.strictEqual(hash, block.hash, 'wrong block hash returned')
assert.strictEqual(miner, block.miner, 'wrong block miner returned')
})
it('should make async eth_getBlockByNumber and return latest block', async () => {
const selector = homeWeb3.utils.soliditySha3('eth_getBlockByNumber()')
await makeAsyncCall(selector, '0x')
assert(await homeBox.methods.status().call(), 'status is false')
const data = await homeBox.methods.data().call()
assert.strictEqual(data.length, 2 + 64 * 3)
})
it('should make async eth_getBlockByHash', async () => {
const blockNumber = ((await foreignWeb3.eth.getBlockNumber()) - 5).toString()
const block = await foreignWeb3.eth.getBlock(blockNumber)
const selector = homeWeb3.utils.soliditySha3('eth_getBlockByHash(bytes32)')
await makeAsyncCall(selector, block.hash)
assert(await homeBox.methods.status().call(), 'status is false')
const data = await homeBox.methods.data().call()
assert.strictEqual(data.length, 2 + 64 * 3)
const { 0: number, 1: hash, 2: miner } = homeWeb3.eth.abi.decodeParameters(
['uint256', 'bytes32', 'address'],
data
)
assert.strictEqual(number, blockNumber, 'wrong block number returned')
assert.strictEqual(hash, block.hash, 'wrong block hash returned')
assert.strictEqual(miner, block.miner, 'wrong block miner returned')
})
it('should make async eth_getBalance', async () => {
const balance = await foreignWeb3.eth.getBalance(user.address)
const selector = homeWeb3.utils.soliditySha3('eth_getBalance(address)')
await makeAsyncCall(selector, homeWeb3.eth.abi.encodeParameter('address', user.address))
assert(await homeBox.methods.status().call(), 'status is false')
const data = await homeBox.methods.data().call()
assert.strictEqual(data.length, 2 + 64)
assert.strictEqual(homeWeb3.eth.abi.decodeParameter('uint256', data), balance, 'wrong user balance returned')
})
it('should make async eth_getBalance for specific block', async () => {
const balance = await foreignWeb3.eth.getBalance(user.address)
const { blockNumber } = await foreignWeb3.eth.sendTransaction({
to: user.address,
value: 1,
from: user.address,
gas: 21000
})
const selector = homeWeb3.utils.soliditySha3('eth_getBalance(address,uint256)')
const data1 = homeWeb3.eth.abi.encodeParameters(['address', 'uint256'], [user.address, blockNumber - 1])
const data2 = homeWeb3.eth.abi.encodeParameters(['address', 'uint256'], [user.address, blockNumber])
await makeAsyncCall(selector, data1)
assert(await homeBox.methods.status().call(), 'status is false')
let data = await homeBox.methods.data().call()
assert.strictEqual(data.length, 2 + 64)
assert.strictEqual(homeWeb3.eth.abi.decodeParameter('uint256', data), balance, 'wrong user balance returned')
await makeAsyncCall(selector, data2)
assert(await homeBox.methods.status().call(), 'status is false')
data = await homeBox.methods.data().call()
assert.strictEqual(data.length, 2 + 64)
assert.notStrictEqual(homeWeb3.eth.abi.decodeParameter('uint256', data), balance, 'wrong user balance returned')
})
it('should make async eth_getTransactionCount', async () => {
const nonce = (await foreignWeb3.eth.getTransactionCount(user.address)).toString()
const selector = homeWeb3.utils.soliditySha3('eth_getTransactionCount(address)')
await makeAsyncCall(selector, homeWeb3.eth.abi.encodeParameter('address', user.address))
assert(await homeBox.methods.status().call(), 'status is false')
const data = await homeBox.methods.data().call()
assert.strictEqual(data.length, 2 + 64)
assert.strictEqual(homeWeb3.eth.abi.decodeParameter('uint256', data), nonce, 'wrong user nonce returned')
})
it('should make async eth_getTransactionCount for specific block', async () => {
let nonce = (await foreignWeb3.eth.getTransactionCount(user.address)).toString()
const { blockNumber } = await foreignWeb3.eth.sendTransaction({
to: user.address,
value: 1,
from: user.address,
gas: 21000
})
const selector = homeWeb3.utils.soliditySha3('eth_getTransactionCount(address,uint256)')
const data1 = homeWeb3.eth.abi.encodeParameters(['address', 'uint256'], [user.address, blockNumber - 1])
const data2 = homeWeb3.eth.abi.encodeParameters(['address', 'uint256'], [user.address, blockNumber])
await makeAsyncCall(selector, data1)
assert(await homeBox.methods.status().call(), 'status is false')
let data = await homeBox.methods.data().call()
assert.strictEqual(data.length, 2 + 64)
assert.strictEqual(homeWeb3.eth.abi.decodeParameter('uint256', data), nonce, 'wrong user nonce returned')
await makeAsyncCall(selector, data2)
assert(await homeBox.methods.status().call(), 'status is false')
data = await homeBox.methods.data().call()
assert.strictEqual(data.length, 2 + 64)
nonce = (parseInt(nonce, 10) + 1).toString()
assert.strictEqual(homeWeb3.eth.abi.decodeParameter('uint256', data), nonce, 'wrong user nonce returned')
})
it('should make async eth_getTransactionByHash', async () => {
const txHash = '0x09dfb947dbd17e27bcc117773b6e133829f7cef9646199a93ef019c4f7c0fec6'
const tx = await foreignWeb3.eth.getTransaction(txHash)
const selector = homeWeb3.utils.soliditySha3('eth_getTransactionByHash(bytes32)')
await makeAsyncCall(selector, txHash)
assert(await homeBox.methods.status().call(), 'status is false')
const data = await homeBox.methods.data().call()
const dataTypes = [
'bytes32',
'uint256',
'address',
'address',
'uint256',
'uint256',
'uint256',
'uint256',
'bytes'
]
const values = homeWeb3.eth.abi.decodeParameters(dataTypes, data)
assert.strictEqual(values[0], txHash, 'wrong txHash returned')
assert.strictEqual(values[1], tx.blockNumber.toString(), 'wrong tx blockNumber returned')
assert.strictEqual(values[2], tx.from, 'wrong tx from returned')
assert.strictEqual(values[3], tx.to, 'wrong tx to returned')
assert.strictEqual(values[4], tx.value, 'wrong tx value returned')
assert.strictEqual(values[5], tx.nonce.toString(), 'wrong tx nonce returned')
assert.strictEqual(values[6], tx.gas.toString(), 'wrong tx gas returned')
assert.strictEqual(values[7], tx.gasPrice, 'wrong tx gasPrice returned')
assert.strictEqual(values[8], tx.input, 'wrong tx data returned')
})
it('should make async eth_getTransactionReceipt', async () => {
const txHash = '0x09dfb947dbd17e27bcc117773b6e133829f7cef9646199a93ef019c4f7c0fec6'
const receipt = await foreignWeb3.eth.getTransactionReceipt(txHash)
const selector = homeWeb3.utils.soliditySha3('eth_getTransactionReceipt(bytes32)')
await makeAsyncCall(selector, txHash)
assert(await homeBox.methods.status().call(), 'status is false')
const data = await homeBox.methods.data().call()
const dataTypes = ['bytes32', 'uint256', 'bool', '(address,bytes32[],bytes)[]']
const values = homeWeb3.eth.abi.decodeParameters(dataTypes, data)
assert.strictEqual(values[0], txHash, 'wrong txHash returned')
assert.strictEqual(values[1], receipt.blockNumber.toString(), 'wrong tx blockNumber returned')
assert.strictEqual(values[2], receipt.status, 'wrong tx status returned')
assert.strictEqual(values[3].length, 1, 'wrong logs length returned')
assert.strictEqual(values[3][0][0], receipt.logs[0].address, 'wrong log address returned')
assert.strictEqual(values[3][0][1].length, 2, 'wrong log topics length returned')
assert.strictEqual(values[3][0][1][0], receipt.logs[0].topics[0], 'wrong event signature returned')
assert.strictEqual(values[3][0][1][1], receipt.logs[0].topics[1], 'wrong message id returned')
assert.strictEqual(values[3][0][2], receipt.logs[0].data, 'wrong log data returned')
})
it('should make async eth_getStorageAt', async () => {
// slot for uintStorage[MAX_GAS_PER_TX]
const slot = '0x3d7fe2ee9790702383ef0118b516833ef2542132d3ca4ac6c77f62f1230fa610'
const value = await foreignWeb3.eth.getStorageAt(amb.foreign, slot)
const selector = homeWeb3.utils.soliditySha3('eth_getStorageAt(address,bytes32)')
await makeAsyncCall(selector, homeWeb3.eth.abi.encodeParameters(['address', 'bytes32'], [amb.foreign, slot]))
assert(await homeBox.methods.status().call(), 'status is false')
const data = await homeBox.methods.data().call()
assert.strictEqual(data, value, 'wrong storage value returned')
})
it('should make async eth_getStorageAt for specific block', async () => {
// slot for uintStorage[MAX_GAS_PER_TX]
const slot = '0x3d7fe2ee9790702383ef0118b516833ef2542132d3ca4ac6c77f62f1230fa610'
const value = await foreignWeb3.eth.getStorageAt(amb.foreign, slot)
const blockNumber = await foreignWeb3.eth.getBlockNumber()
const selector = homeWeb3.utils.soliditySha3('eth_getStorageAt(address,bytes32,uint256)')
const data1 = homeWeb3.eth.abi.encodeParameters(
['address', 'bytes32', 'uint256'],
[amb.foreign, slot, blockNumber]
)
const data2 = homeWeb3.eth.abi.encodeParameters(['address', 'bytes32', 'uint256'], [amb.foreign, slot, 1])
await makeAsyncCall(selector, data1)
assert(await homeBox.methods.status().call(), 'status is false')
let data = await homeBox.methods.data().call()
assert.strictEqual(data, value, 'wrong storage value returned')
await makeAsyncCall(selector, data2)
assert(await homeBox.methods.status().call(), 'status is false')
data = await homeBox.methods.data().call()
assert.strictEqual(
data,
'0x0000000000000000000000000000000000000000000000000000000000000000',
'wrong storage value returned'
)
})
})
}) })

@ -1,142 +0,0 @@
const Web3 = require('web3')
const assert = require('assert')
const { user, secondUser, ercToErcBridge, homeRPC, foreignRPC, validator } = require('../../e2e-commons/constants.json')
const { ERC677_BRIDGE_TOKEN_ABI, FOREIGN_ERC_TO_NATIVE_ABI, HOME_ERC_TO_ERC_ABI } = require('../../commons')
const { uniformRetry } = require('../../e2e-commons/utils')
const { setRequiredSignatures } = require('./utils')
const homeWeb3 = new Web3(new Web3.providers.HttpProvider(homeRPC.URL))
const foreignWeb3 = new Web3(new Web3.providers.HttpProvider(foreignRPC.URL))
const COMMON_HOME_BRIDGE_ADDRESS = ercToErcBridge.home
const COMMON_FOREIGN_BRIDGE_ADDRESS = ercToErcBridge.foreign
const { toBN } = foreignWeb3.utils
homeWeb3.eth.accounts.wallet.add(user.privateKey)
homeWeb3.eth.accounts.wallet.add(validator.privateKey)
foreignWeb3.eth.accounts.wallet.add(user.privateKey)
foreignWeb3.eth.accounts.wallet.add(validator.privateKey)
const erc20Token = new foreignWeb3.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, ercToErcBridge.foreignToken)
const foreignBridge = new foreignWeb3.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
const erc677Token = new homeWeb3.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, ercToErcBridge.homeToken)
const homeBridge = new homeWeb3.eth.Contract(HOME_ERC_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
describe('erc to erc', () => {
before(async () => {
if (process.env.ULTIMATE === 'true') {
return
}
console.log('Calling setRequiredSignatures(2)')
// Set 2 required signatures for home bridge
await setRequiredSignatures({
bridgeContract: homeBridge,
web3: homeWeb3,
requiredSignatures: 2,
options: {
from: validator.address,
gas: '4000000'
}
})
// Set 2 required signatures for foreign bridge
await setRequiredSignatures({
bridgeContract: foreignBridge,
web3: foreignWeb3,
requiredSignatures: 2,
options: {
from: validator.address,
gas: '4000000'
}
})
})
it('should convert tokens in foreign to tokens in home', async () => {
const balance = await erc20Token.methods.balanceOf(user.address).call()
assert(!toBN(balance).isZero(), 'Account should have tokens')
const firstTransferValue = homeWeb3.utils.toWei('0.01')
// approve tokens to foreign bridge
await erc20Token.methods
.approve(COMMON_FOREIGN_BRIDGE_ADDRESS, firstTransferValue)
.send({
from: user.address,
gas: '1000000'
})
.catch(e => {
console.error(e)
})
// call bridge method to transfer tokens to a different recipient
await foreignBridge.methods
.relayTokens(secondUser.address, firstTransferValue)
.send({
from: user.address,
gas: '1000000'
})
.catch(e => {
console.error(e)
})
// check that balance increases
await uniformRetry(async retry => {
const balance = await erc677Token.methods.balanceOf(user.address).call()
const recipientBalance = await erc677Token.methods.balanceOf(secondUser.address).call()
assert(toBN(balance).isZero(), 'User balance should be the same')
if (toBN(recipientBalance).isZero()) {
retry()
}
})
const secondTransferValue = homeWeb3.utils.toWei('0.05')
// send tokens to foreign bridge
await erc20Token.methods
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, secondTransferValue)
.send({
from: user.address,
gas: '1000000'
})
.catch(e => {
console.error(e)
})
// check that balance increases
await uniformRetry(async retry => {
const balance = await erc677Token.methods.balanceOf(user.address).call()
if (toBN(balance).isZero()) {
retry()
} else {
assert(toBN(balance).eq(toBN(secondTransferValue)), 'User balance should be increased only by second transfer')
}
})
})
it('should convert tokens in home to tokens in foreign', async () => {
const originalBalance = await erc20Token.methods.balanceOf(user.address).call()
// check that account has tokens in home chain
const balance = await erc677Token.methods.balanceOf(user.address).call()
assert(!toBN(balance).isZero(), 'Account should have tokens')
// send transaction to home bridge
await erc677Token.methods
.transferAndCall(COMMON_HOME_BRIDGE_ADDRESS, homeWeb3.utils.toWei('0.01'), '0x')
.send({
from: user.address,
gas: '1000000'
})
.catch(e => {
console.error(e)
})
// check that balance increases
await uniformRetry(async retry => {
const balance = await erc20Token.methods.balanceOf(user.address).call()
if (toBN(balance).lte(toBN(originalBalance))) {
retry()
}
})
})
})

@ -1,6 +1,5 @@
const Web3 = require('web3') const Web3 = require('web3')
const assert = require('assert') const assert = require('assert')
const promiseRetry = require('promise-retry')
const { const {
user, user,
secondUser, secondUser,
@ -10,7 +9,7 @@ const {
homeRPC, homeRPC,
foreignRPC foreignRPC
} = require('../../e2e-commons/constants.json') } = require('../../e2e-commons/constants.json')
const { ERC677_BRIDGE_TOKEN_ABI, FOREIGN_ERC_TO_NATIVE_ABI, HOME_ERC_TO_NATIVE_ABI } = require('../../commons') const { ERC20_ABI, FOREIGN_ERC_TO_NATIVE_ABI, HOME_ERC_TO_NATIVE_ABI } = require('../../commons')
const { uniformRetry, sleep } = require('../../e2e-commons/utils') const { uniformRetry, sleep } = require('../../e2e-commons/utils')
const { setRequiredSignatures } = require('./utils') const { setRequiredSignatures } = require('./utils')
@ -28,7 +27,7 @@ homeWeb3.eth.accounts.wallet.add(validator.privateKey)
foreignWeb3.eth.accounts.wallet.add(user.privateKey) foreignWeb3.eth.accounts.wallet.add(user.privateKey)
foreignWeb3.eth.accounts.wallet.add(validator.privateKey) foreignWeb3.eth.accounts.wallet.add(validator.privateKey)
const erc20Token = new foreignWeb3.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, ercToNativeBridge.foreignToken) const erc20Token = new foreignWeb3.eth.Contract(ERC20_ABI, ercToNativeBridge.foreignToken)
const foreignBridge = new foreignWeb3.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS) const foreignBridge = new foreignWeb3.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
const homeBridge = new homeWeb3.eth.Contract(HOME_ERC_TO_NATIVE_ABI, COMMON_HOME_BRIDGE_ADDRESS) const homeBridge = new homeWeb3.eth.Contract(HOME_ERC_TO_NATIVE_ABI, COMMON_HOME_BRIDGE_ADDRESS)
@ -196,211 +195,4 @@ describe('erc to native', () => {
) )
}) })
} }
it('should not invest dai when chai token is disabled', async () => {
const bridgeDaiTokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
await foreignBridge.methods.setMinDaiTokenBalance(foreignWeb3.utils.toWei('2', 'ether')).send({
from: validator.address,
gas: '1000000'
}) // set min limit for automatic investment to 2*2 dai
const valueToTransfer = foreignWeb3.utils.toWei('5', 'ether')
// this transfer won't trigger a call to convert to chai
await erc20Token.methods.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, valueToTransfer).send({
from: user.address,
gas: '1000000'
})
await promiseRetry(async (retry, number) => {
if (number < 4) {
retry()
} else {
const updatedBridgeDaiTokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
assert(
toBN(bridgeDaiTokenBalance)
.add(toBN(valueToTransfer))
.eq(toBN(updatedBridgeDaiTokenBalance)),
'Dai tokens should not be when chai is disabled'
)
}
})
})
it('should invest dai after enough tokens are collected on bridge account', async () => {
await foreignBridge.methods.initializeChaiToken().send({
from: validator.address,
gas: '1000000'
}) // initialize chai token
await foreignBridge.methods.setMinDaiTokenBalance('0').send({
from: validator.address,
gas: '1000000'
}) // set investing limit to 0
await foreignBridge.methods.convertDaiToChai().send({
from: validator.address,
gas: '1000000'
}) // convert all existing dai tokens on bridge account to chai, in order to start from zero balance
await foreignBridge.methods.setMinDaiTokenBalance(foreignWeb3.utils.toWei('2', 'ether')).send({
from: validator.address,
gas: '1000000'
}) // set investing limit to 2 dai, automatically invest should happen after 4 dai
const valueToTransfer = foreignWeb3.utils.toWei('3', 'ether')
// this transfer won't trigger a call to convert to chai
await erc20Token.methods.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, valueToTransfer).send({
from: user.address,
gas: '1000000'
})
await promiseRetry(async (retry, number) => {
if (number < 4) {
retry()
} else {
const bridgeDaiTokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
assert(
valueToTransfer === bridgeDaiTokenBalance,
'Dai tokens should not be invested automatically before twice limit is reached'
)
}
})
// this transfer will trigger call to convert to chai
await erc20Token.methods.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, valueToTransfer).send({
from: user.address,
gas: '1000000'
})
await promiseRetry(async retry => {
const updatedBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
if (toBN(updatedBalance).gte(toBN(valueToTransfer).add(toBN(valueToTransfer)))) {
retry()
} else {
const updatedBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
assert(
toBN(updatedBalance).eq(toBN(foreignWeb3.utils.toWei('2', 'ether'))),
'Dai bridge balance should be equal to limit'
)
}
})
})
if (process.env.ULTIMATE !== 'true') {
describe('handling of chai swaps', async () => {
before(async () => {
// Next tests check validator nonces, this will force every validator to submit signature/affirmation
// Set 3 required signatures for home bridge
await setRequiredSignatures({
bridgeContract: homeBridge,
web3: homeWeb3,
requiredSignatures: 3,
options: {
from: validator.address,
gas: '4000000'
}
})
// Set 3 required signatures for foreign bridge
await setRequiredSignatures({
bridgeContract: foreignBridge,
web3: foreignWeb3,
requiredSignatures: 3,
options: {
from: validator.address,
gas: '4000000'
}
})
})
it('should not handle transfer event in paying interest', async () => {
await foreignBridge.methods.setInterestReceiver(user.address).send({
from: validator.address,
gas: '1000000'
})
const initialNonce = await homeWeb3.eth.getTransactionCount(validator.address)
await foreignBridge.methods.payInterest().send({
from: user.address,
gas: '1000000'
})
await promiseRetry(async (retry, number) => {
if (number < 6) {
retry()
} else {
const nonce = await homeWeb3.eth.getTransactionCount(validator.address)
assert(
nonce === initialNonce,
'Validator should not process transfer event originated during converting Chai => Dai'
)
}
})
})
it('should not handle chai withdrawal transfer event in executeSignatures as a regular transfer', async () => {
await foreignBridge.methods.setMinDaiTokenBalance('0').send({
from: validator.address,
gas: '1000000'
}) // set investing limit to 0
await foreignBridge.methods.convertDaiToChai().send({
from: validator.address,
gas: '1000000'
}) // convert all existing dai tokens on bridge account to chai, in order to start from zero balance
const initialNonce = await homeWeb3.eth.getTransactionCount(validator.address)
const originalBalance = await erc20Token.methods.balanceOf(user.address).call()
// send transaction to home bridge
await homeWeb3.eth.sendTransaction({
from: user.address,
to: COMMON_HOME_BRIDGE_ADDRESS,
gasPrice: '1',
gas: '1000000',
value: homeWeb3.utils.toWei('0.01')
})
// check that balance increases
await uniformRetry(async retry => {
const balance = await erc20Token.methods.balanceOf(user.address).call()
if (toBN(balance).lte(toBN(originalBalance))) {
retry()
}
})
await promiseRetry(async (retry, number) => {
if (number < 6) {
retry()
} else {
const nonce = await homeWeb3.eth.getTransactionCount(validator.address)
assert(
nonce === initialNonce + 1,
'Validator should not process transfer event originated during converting Chai => Dai'
)
}
})
})
after(async () => {
// Set 2 required signatures for home bridge
await setRequiredSignatures({
bridgeContract: homeBridge,
web3: homeWeb3,
requiredSignatures: 2,
options: {
from: validator.address,
gas: '4000000'
}
})
// Set 2 required signatures for foreign bridge
await setRequiredSignatures({
bridgeContract: foreignBridge,
web3: foreignWeb3,
requiredSignatures: 2,
options: {
from: validator.address,
gas: '4000000'
}
})
})
})
}
}) })

@ -1,212 +0,0 @@
const Web3 = require('web3')
const assert = require('assert')
const {
user,
validator,
secondValidator,
thirdValidator,
nativeToErcBridge,
secondUser,
thirdUser,
fourthUser,
homeRPC,
foreignRPC
} = require('../../e2e-commons/constants.json')
const { ERC677_BRIDGE_TOKEN_ABI, HOME_NATIVE_TO_ERC_ABI, FOREIGN_NATIVE_TO_ERC_ABI } = require('../../commons')
const { uniformRetry, sleep } = require('../../e2e-commons/utils')
const { setRequiredSignatures } = require('./utils')
const homeWeb3 = new Web3(new Web3.providers.HttpProvider(homeRPC.URL))
const foreignWeb3 = new Web3(new Web3.providers.HttpProvider(foreignRPC.URL))
const { toBN } = foreignWeb3.utils
const COMMON_HOME_BRIDGE_ADDRESS = nativeToErcBridge.home
const COMMON_FOREIGN_BRIDGE_ADDRESS = nativeToErcBridge.foreign
const validatorAddresses = [validator.address, secondValidator.address, thirdValidator.address]
homeWeb3.eth.accounts.wallet.add(user.privateKey)
homeWeb3.eth.accounts.wallet.add(validator.privateKey)
homeWeb3.eth.accounts.wallet.add(secondUser.privateKey)
homeWeb3.eth.accounts.wallet.add(secondValidator.privateKey)
homeWeb3.eth.accounts.wallet.add(thirdValidator.privateKey)
homeWeb3.eth.accounts.wallet.add(thirdUser.privateKey)
homeWeb3.eth.accounts.wallet.add(fourthUser.privateKey)
foreignWeb3.eth.accounts.wallet.add(user.privateKey)
foreignWeb3.eth.accounts.wallet.add(validator.privateKey)
foreignWeb3.eth.accounts.wallet.add(secondUser.privateKey)
foreignWeb3.eth.accounts.wallet.add(secondValidator.privateKey)
foreignWeb3.eth.accounts.wallet.add(thirdValidator.privateKey)
foreignWeb3.eth.accounts.wallet.add(thirdUser.privateKey)
foreignWeb3.eth.accounts.wallet.add(fourthUser.privateKey)
const token = new foreignWeb3.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, nativeToErcBridge.foreignToken)
const homeBridge = new homeWeb3.eth.Contract(HOME_NATIVE_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
const foreignBridge = new foreignWeb3.eth.Contract(FOREIGN_NATIVE_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
describe('native to erc', () => {
before(async () => {
if (process.env.ULTIMATE === 'true') {
return
}
console.log('Calling setRequiredSignatures(2)')
// Set 2 required signatures for home bridge
await setRequiredSignatures({
bridgeContract: homeBridge,
web3: homeWeb3,
requiredSignatures: 2,
options: {
from: validator.address,
gas: '4000000'
}
})
// Set 2 required signatures for foreign bridge
await setRequiredSignatures({
bridgeContract: foreignBridge,
web3: foreignWeb3,
requiredSignatures: 2,
options: {
from: validator.address,
gas: '4000000'
}
})
})
it('should convert eth in home to tokens in foreign', async () => {
// check that account has zero tokens in the foreign chain
const balance = await token.methods.balanceOf(user.address).call()
assert(toBN(balance).isZero(), 'Account should not have tokens yet')
// send transaction to home chain
await homeWeb3.eth.sendTransaction({
from: user.address,
to: COMMON_HOME_BRIDGE_ADDRESS,
gasPrice: '1',
gas: '50000',
value: '1000000000000000000'
})
// check that account has tokens in the foreign chain
await uniformRetry(async retry => {
const balance = await token.methods.balanceOf(user.address).call()
if (toBN(balance).isZero()) {
retry()
}
})
})
it('should convert tokens in foreign to eth in home', async () => {
const originalBalance = await homeWeb3.eth.getBalance(user.address)
// send tokens to foreign bridge
await token.methods
.transferAndCall(COMMON_FOREIGN_BRIDGE_ADDRESS, homeWeb3.utils.toWei('0.01'), '0x')
.send({
from: user.address,
gas: '1000000'
})
.catch(e => {
console.error(e)
})
// check that balance increases
await uniformRetry(async retry => {
const balance = await homeWeb3.eth.getBalance(user.address)
if (toBN(balance).lte(toBN(originalBalance))) {
retry()
}
})
})
it('should wait for funds if these are insufficient (Home)', async () => {
// check that account has zero tokens in the foreign chain
const originalBalance = toBN(await token.methods.balanceOf(user.address).call())
// empty validator funds
await sendAllBalance(homeWeb3, validator.address, secondUser.address)
await sendAllBalance(homeWeb3, secondValidator.address, thirdUser.address)
await sendAllBalance(homeWeb3, thirdValidator.address, fourthUser.address)
const nonces = await Promise.all(validatorAddresses.map(homeWeb3.eth.getTransactionCount))
// send transaction to home chain
await homeWeb3.eth.sendTransaction({
from: user.address,
to: COMMON_HOME_BRIDGE_ADDRESS,
gasPrice: '1',
gas: '50000',
value: '1000000000000000000'
})
// wait two seconds, no new blocks should have been generated
await sleep(2000)
const newNonces = await Promise.all(validatorAddresses.map(homeWeb3.eth.getTransactionCount))
const balance = toBN(await token.methods.balanceOf(user.address).call())
assert.deepStrictEqual(nonces, newNonces, "Shouldn't sent new tx")
assert(originalBalance.eq(balance), "Token balance shouldn't have changed")
// send funds back to validator
await sendAllBalance(homeWeb3, secondUser.address, validator.address)
await sendAllBalance(homeWeb3, thirdUser.address, secondValidator.address)
await sendAllBalance(homeWeb3, fourthUser.address, thirdValidator.address)
// check that token balance was incremented in foreign chain
await uniformRetry(async retry => {
const balance = toBN(await token.methods.balanceOf(user.address).call())
if (!balance.gt(originalBalance)) {
retry()
}
})
})
it('should wait for funds if these are insufficient (Foreign)', async () => {
// get original tokens balance
const originalBalance = toBN(await token.methods.balanceOf(user.address).call())
// empty foreign validator funds
await sendAllBalance(foreignWeb3, validator.address, secondUser.address)
await sendAllBalance(foreignWeb3, secondValidator.address, thirdUser.address)
await sendAllBalance(foreignWeb3, thirdValidator.address, fourthUser.address)
const nonces = await Promise.all(validatorAddresses.map(foreignWeb3.eth.getTransactionCount))
// send transaction to home chain
await homeWeb3.eth.sendTransaction({
from: user.address,
to: COMMON_HOME_BRIDGE_ADDRESS,
gasPrice: '1',
gas: '50000',
value: '1000000000000000000'
})
// tokens shouldn't be generated in the foreign chain because the validator doesn't have funds
await sleep(2000)
const newNonces = await Promise.all(validatorAddresses.map(foreignWeb3.eth.getTransactionCount))
assert.deepStrictEqual(nonces, newNonces, "Shouldn't sent new tx")
// send funds back to validator
await sendAllBalance(foreignWeb3, secondUser.address, validator.address)
await sendAllBalance(foreignWeb3, thirdUser.address, secondValidator.address)
await sendAllBalance(foreignWeb3, fourthUser.address, thirdValidator.address)
// check that account has tokens in the foreign chain
await uniformRetry(async retry => {
const balance = toBN(await token.methods.balanceOf(user.address).call())
if (balance.eq(originalBalance)) {
retry()
}
})
})
})
async function sendAllBalance(web3, from, to) {
const balance = await web3.eth.getBalance(from)
const value = toBN(balance).sub(toBN('21000'))
return web3.eth.sendTransaction({
from,
to,
value,
gas: '21000',
gasPrice: '1'
})
}

@ -6,6 +6,7 @@
], ],
"plugins": ["node"], "plugins": ["node"],
"rules": { "rules": {
"node/no-unpublished-require": "off" "node/no-unpublished-require": "off",
"global-require": "off"
} }
} }

@ -1,4 +1,4 @@
FROM node:10 as contracts FROM node:12 as contracts
WORKDIR /mono WORKDIR /mono
@ -11,7 +11,7 @@ COPY ./contracts/truffle-config.js ./
COPY ./contracts/contracts ./contracts COPY ./contracts/contracts ./contracts
RUN npm run compile RUN npm run compile
FROM node:10 FROM node:12
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y build-essential libc6-dev libc6-dev-i386 wget && \ apt-get install -y build-essential libc6-dev libc6-dev-i386 wget && \

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

@ -10,13 +10,9 @@ The Oracle is deployed on specified validator nodes (only nodes whose private ke
## Architecture ## Architecture
### Native-to-ERC20 and Arbitrary-Message ### ERC20-to-Native
![Native-to-ERC](Native-to-ERC.png) ![ERC-to-Native](ERC_TO_NATIVE.png)
### ERC20-to-ERC20 and ERC20-to-Native
![ERC-to-ERC](ERC-to-ERC.png)
### Watcher ### Watcher
A watcher listens for a certain event and creates proper jobs in the queue. These jobs contain the transaction data (without the nonce) and the transaction hash for the related event. The watcher runs on a given frequency, keeping track of the last processed block. A watcher listens for a certain event and creates proper jobs in the queue. These jobs contain the transaction data (without the nonce) and the transaction hash for the related event. The watcher runs on a given frequency, keeping track of the last processed block.
@ -27,8 +23,8 @@ There are three Watchers:
- **Signature Request Watcher**: Listens to `UserRequestForSignature` events on the Home network. - **Signature Request Watcher**: Listens to `UserRequestForSignature` events on the Home network.
- **Collected Signatures Watcher**: Listens to `CollectedSignatures` events on the Home network. - **Collected Signatures Watcher**: Listens to `CollectedSignatures` events on the Home network.
- **Affirmation Request Watcher**: Depends on the bridge mode. - **Affirmation Request Watcher**: Depends on the bridge mode.
- `Native-to-ERC20` and `Arbitrary-Message`: Listens to `UserRequestForAffirmation` raised by the bridge contract. - `Arbitrary-Message`: Listens to `UserRequestForAffirmation` raised by the bridge contract.
- `ERC20-to-ERC20` and `ERC20-to-Native`: Listens to `Transfer` events raised by the token contract. - `ERC20-to-Native`: Listens to `Transfer` events raised by the token contract.
### Sender ### Sender
A sender subscribes to the queue and keeps track of the nonce. It takes jobs from the queue, extracts transaction data, adds the proper nonce, and sends it to the network. A sender subscribes to the queue and keeps track of the nonce. It takes jobs from the queue, extracts transaction data, adds the proper nonce, and sends it to the network.
@ -59,32 +55,12 @@ For more information on the Redis/RabbitMQ requirements, see [#90](/../../issues
#### Output examples #### Output examples
`Native-to-ERC20` mode example: `ERC20-to-Native` mode example:
```json
{
"homeBridge": {
"address": "0xc60daff55ec5b5ce5c3d2105a77e287ff638c35e",
"deployedBlockNumber": 123321
},
"foreignBridge": {
"address": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be",
"deployedBlockNumber": 456654,
"erc677": {
"address": "0x41a29780309dc2582f080f6af89953be3435679a"
}
}
}
```
`ERC20-to-ERC20` mode example:
```json ```json
{ {
"homeBridge": { "homeBridge": {
"address": "0x765a0d90e5a5773deacbd94b2dc941cbb163bdab", "address": "0x765a0d90e5a5773deacbd94b2dc941cbb163bdab",
"deployedBlockNumber": 789987, "deployedBlockNumber": 789987
"erc677": {
"address": "0x269f57f5ae5421d084686f9e353f5b7ee6af54c2"
}
}, },
"foreignBridge": { "foreignBridge": {
"address": "0x7ae703ea88b0545eef1f0bf8f91d5276e39be2f7", "address": "0x7ae703ea88b0545eef1f0bf8f91d5276e39be2f7",
@ -221,20 +197,6 @@ See the [E2E README](../oracle-e2e/README.md) for instructions.
*Notice*: for docker-based installations do not forget to add `docker-compose exec bridge_affirmation` before the test commands listed below. *Notice*: for docker-based installations do not forget to add `docker-compose exec bridge_affirmation` before the test commands listed below.
### Native-to-ERC20 Mode Testing
When running the processes, the following commands can be used to test functionality.
- To send deposits to a home contract run `node scripts/native_to_erc20/sendHome.js <tx num>`, where `<tx num>` is how many tx will be sent out to deposit.
- To send withdrawals to a foreign contract run `node scripts/native_to_erc20/sendForeign.js <tx num>`, where `<tx num>` is how many tx will be sent out to withdraw.
### ERC20-to-ERC20 Mode Testing
- To deposit from a Foreign to a Home contract run `node scripts/erc20_to_erc20/sendForeign.js <tx num>`.
- To make withdrawal to Home from a Foreign contract run `node scripts/erc20_to_erc20/sendHome.js <tx num>`.
### ERC20-to-Native Mode Testing ### ERC20-to-Native Mode Testing
- To deposit from a Foreign to a Home contract run `node scripts/erc20_to_native/sendForeign.js <tx num>`. - To deposit from a Foreign to a Home contract run `node scripts/erc20_to_native/sendForeign.js <tx num>`.

@ -1,28 +1,10 @@
const baseConfig = require('./base.config') const baseConfig = require('./base.config')
const { ERC_TYPES } = require('../../commons')
const initialChecksJson = process.argv[3]
if (!initialChecksJson) {
throw new Error('initial check parameter was not provided.')
}
let initialChecks
try {
initialChecks = JSON.parse(initialChecksJson)
} catch (e) {
throw new Error('Error on decoding values from initial checks.')
}
if (baseConfig.id === 'erc-erc' && initialChecks.foreignERC === ERC_TYPES.ERC677) {
baseConfig.id = 'erc677-erc677'
}
const id = `${baseConfig.id}-affirmation-request` const id = `${baseConfig.id}-affirmation-request`
module.exports = { module.exports = {
...baseConfig.bridgeConfig, ...baseConfig,
...baseConfig.foreignConfig, main: baseConfig.foreign,
event: 'UserRequestForAffirmation', event: 'UserRequestForAffirmation',
queue: 'home-prioritized', queue: 'home-prioritized',
name: `watcher-${id}`, name: `watcher-${id}`,

@ -1,12 +1,7 @@
require('../env') require('../env')
const { toBN } = require('web3').utils
const { const {
BRIDGE_MODES, BRIDGE_MODES,
HOME_NATIVE_TO_ERC_ABI,
FOREIGN_NATIVE_TO_ERC_ABI,
HOME_ERC_TO_ERC_ABI,
FOREIGN_ERC_TO_ERC_ABI,
HOME_ERC_TO_NATIVE_ABI, HOME_ERC_TO_NATIVE_ABI,
FOREIGN_ERC_TO_NATIVE_ABI, FOREIGN_ERC_TO_NATIVE_ABI,
HOME_AMB_ABI, HOME_AMB_ABI,
@ -15,23 +10,26 @@ const {
const { web3Home, web3Foreign } = require('../src/services/web3') const { web3Home, web3Foreign } = require('../src/services/web3')
const { privateKeyToAddress } = require('../src/utils/utils') const { privateKeyToAddress } = require('../src/utils/utils')
const { ORACLE_VALIDATOR_ADDRESS, ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY } = process.env const {
ORACLE_BRIDGE_MODE,
ORACLE_VALIDATOR_ADDRESS,
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY,
ORACLE_MAX_PROCESSING_TIME,
COMMON_HOME_BRIDGE_ADDRESS,
COMMON_FOREIGN_BRIDGE_ADDRESS,
ORACLE_HOME_RPC_POLLING_INTERVAL,
ORACLE_FOREIGN_RPC_POLLING_INTERVAL,
ORACLE_HOME_START_BLOCK,
ORACLE_FOREIGN_START_BLOCK,
ORACLE_HOME_RPC_BLOCK_POLLING_LIMIT,
ORACLE_FOREIGN_RPC_BLOCK_POLLING_LIMIT
} = process.env
let homeAbi let homeAbi
let foreignAbi let foreignAbi
let id let id
switch (process.env.ORACLE_BRIDGE_MODE) { switch (ORACLE_BRIDGE_MODE) {
case BRIDGE_MODES.NATIVE_TO_ERC:
homeAbi = HOME_NATIVE_TO_ERC_ABI
foreignAbi = FOREIGN_NATIVE_TO_ERC_ABI
id = 'native-erc'
break
case BRIDGE_MODES.ERC_TO_ERC:
homeAbi = HOME_ERC_TO_ERC_ABI
foreignAbi = FOREIGN_ERC_TO_ERC_ABI
id = 'erc-erc'
break
case BRIDGE_MODES.ERC_TO_NATIVE: case BRIDGE_MODES.ERC_TO_NATIVE:
homeAbi = HOME_ERC_TO_NATIVE_ABI homeAbi = HOME_ERC_TO_NATIVE_ABI
foreignAbi = FOREIGN_ERC_TO_NATIVE_ABI foreignAbi = FOREIGN_ERC_TO_NATIVE_ABI
@ -44,7 +42,7 @@ switch (process.env.ORACLE_BRIDGE_MODE) {
break break
default: default:
if (process.env.NODE_ENV !== 'test') { if (process.env.NODE_ENV !== 'test') {
throw new Error(`Bridge Mode: ${process.env.ORACLE_BRIDGE_MODE} not supported.`) throw new Error(`Bridge Mode: ${ORACLE_BRIDGE_MODE} not supported.`)
} else { } else {
homeAbi = HOME_ERC_TO_NATIVE_ABI homeAbi = HOME_ERC_TO_NATIVE_ABI
foreignAbi = FOREIGN_ERC_TO_NATIVE_ABI foreignAbi = FOREIGN_ERC_TO_NATIVE_ABI
@ -52,56 +50,41 @@ switch (process.env.ORACLE_BRIDGE_MODE) {
} }
} }
let maxProcessingTime = null const homeContract = new web3Home.eth.Contract(homeAbi, COMMON_HOME_BRIDGE_ADDRESS)
if (String(process.env.ORACLE_MAX_PROCESSING_TIME) === '0') { const homeConfig = {
maxProcessingTime = 0 chain: 'home',
} else if (!process.env.ORACLE_MAX_PROCESSING_TIME) { bridgeAddress: COMMON_HOME_BRIDGE_ADDRESS,
maxProcessingTime = bridgeABI: homeAbi,
4 * Math.max(process.env.ORACLE_HOME_RPC_POLLING_INTERVAL, process.env.ORACLE_FOREIGN_RPC_POLLING_INTERVAL) pollingInterval: parseInt(ORACLE_HOME_RPC_POLLING_INTERVAL, 10),
} else { startBlock: parseInt(ORACLE_HOME_START_BLOCK, 10) || 0,
maxProcessingTime = Number(process.env.ORACLE_MAX_PROCESSING_TIME) blockPollingLimit: parseInt(ORACLE_HOME_RPC_BLOCK_POLLING_LIMIT, 10),
web3: web3Home,
bridgeContract: homeContract,
eventContract: homeContract
} }
const bridgeConfig = { const foreignContract = new web3Foreign.eth.Contract(foreignAbi, COMMON_FOREIGN_BRIDGE_ADDRESS)
homeBridgeAddress: process.env.COMMON_HOME_BRIDGE_ADDRESS, const foreignConfig = {
homeBridgeAbi: homeAbi, chain: 'foreign',
foreignBridgeAddress: process.env.COMMON_FOREIGN_BRIDGE_ADDRESS, bridgeAddress: COMMON_FOREIGN_BRIDGE_ADDRESS,
foreignBridgeAbi: foreignAbi, bridgeABI: foreignAbi,
pollingInterval: parseInt(ORACLE_FOREIGN_RPC_POLLING_INTERVAL, 10),
startBlock: parseInt(ORACLE_FOREIGN_START_BLOCK, 10) || 0,
blockPollingLimit: parseInt(ORACLE_FOREIGN_RPC_BLOCK_POLLING_LIMIT, 10),
web3: web3Foreign,
bridgeContract: foreignContract,
eventContract: foreignContract
}
const maxProcessingTime =
parseInt(ORACLE_MAX_PROCESSING_TIME, 10) || 4 * Math.max(homeConfig.pollingInterval, foreignConfig.pollingInterval)
module.exports = {
eventFilter: {}, eventFilter: {},
validatorAddress: ORACLE_VALIDATOR_ADDRESS || privateKeyToAddress(ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY), validatorAddress: ORACLE_VALIDATOR_ADDRESS || privateKeyToAddress(ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY),
maxProcessingTime, maxProcessingTime,
shutdownKey: 'oracle-shutdown' shutdownKey: 'oracle-shutdown',
} home: homeConfig,
foreign: foreignConfig,
const toBNOrNull = x => (x ? toBN(x) : null)
const homeConfig = {
chain: 'home',
eventContractAddress: process.env.COMMON_HOME_BRIDGE_ADDRESS,
eventAbi: homeAbi,
bridgeContractAddress: process.env.COMMON_HOME_BRIDGE_ADDRESS,
bridgeAbi: homeAbi,
pollingInterval: process.env.ORACLE_HOME_RPC_POLLING_INTERVAL,
startBlock: toBN(process.env.ORACLE_HOME_START_BLOCK || 0),
blockPollingLimit: toBNOrNull(process.env.ORACLE_HOME_RPC_BLOCK_POLLING_LIMIT),
web3: web3Home
}
const foreignConfig = {
chain: 'foreign',
eventContractAddress: process.env.COMMON_FOREIGN_BRIDGE_ADDRESS,
eventAbi: foreignAbi,
bridgeContractAddress: process.env.COMMON_FOREIGN_BRIDGE_ADDRESS,
bridgeAbi: foreignAbi,
pollingInterval: process.env.ORACLE_FOREIGN_RPC_POLLING_INTERVAL,
startBlock: toBN(process.env.ORACLE_FOREIGN_START_BLOCK || 0),
blockPollingLimit: toBNOrNull(process.env.ORACLE_FOREIGN_RPC_BLOCK_POLLING_LIMIT),
web3: web3Foreign
}
module.exports = {
bridgeConfig,
homeConfig,
foreignConfig,
id id
} }

@ -3,8 +3,8 @@ const baseConfig = require('./base.config')
const id = `${baseConfig.id}-collected-signatures` const id = `${baseConfig.id}-collected-signatures`
module.exports = { module.exports = {
...baseConfig.bridgeConfig, ...baseConfig,
...baseConfig.homeConfig, main: baseConfig.home,
event: 'CollectedSignatures', event: 'CollectedSignatures',
queue: 'foreign-prioritized', queue: 'foreign-prioritized',
name: `watcher-${id}`, name: `watcher-${id}`,

@ -1,20 +0,0 @@
const baseConfig = require('./base.config')
const { EXIT_CODES } = require('../src/utils/constants')
const id = `${baseConfig.id}-convert-to-chai`
const workerRequired = baseConfig.id === 'erc-native'
if (!workerRequired) {
console.error(`Convert to chai tokens worker not required for bridge mode ${process.env.ORACLE_BRIDGE_MODE}`)
process.exit(EXIT_CODES.WATCHER_NOT_REQUIRED)
}
module.exports = {
...baseConfig.bridgeConfig,
...baseConfig.foreignConfig,
workerQueue: 'convert-to-chai',
senderQueue: 'foreign-prioritized',
name: `worker-${id}`,
id
}

@ -6,7 +6,7 @@ const { web3Foreign, web3ForeignRedundant, web3ForeignFallback } = require('../s
const { ORACLE_FOREIGN_TX_RESEND_INTERVAL } = process.env const { ORACLE_FOREIGN_TX_RESEND_INTERVAL } = process.env
module.exports = { module.exports = {
...baseConfig.bridgeConfig, ...baseConfig,
queue: 'foreign-prioritized', queue: 'foreign-prioritized',
oldQueue: 'foreign', oldQueue: 'foreign',
id: 'foreign', id: 'foreign',

@ -6,7 +6,7 @@ const { web3Home, web3HomeRedundant, web3HomeFallback } = require('../src/servic
const { ORACLE_HOME_TX_RESEND_INTERVAL } = process.env const { ORACLE_HOME_TX_RESEND_INTERVAL } = process.env
module.exports = { module.exports = {
...baseConfig.bridgeConfig, ...baseConfig,
queue: 'home-prioritized', queue: 'home-prioritized',
oldQueue: 'home', oldQueue: 'home',
id: 'home', id: 'home',

@ -0,0 +1,14 @@
const baseConfig = require('./base.config')
const { web3ForeignArchive } = require('../src/services/web3')
const id = `${baseConfig.id}-information-request`
module.exports = {
...baseConfig,
web3ForeignArchive: web3ForeignArchive || baseConfig.foreign.web3,
main: baseConfig.home,
event: 'UserRequestForInformation',
queue: 'home-prioritized',
name: `watcher-${id}`,
id
}

@ -8,7 +8,7 @@ const {
} = process.env } = process.env
module.exports = { module.exports = {
...baseConfig.bridgeConfig, ...baseConfig,
id: 'shutdown-manager', id: 'shutdown-manager',
name: 'shutdown-manager', name: 'shutdown-manager',
pollingInterval: ORACLE_SHUTDOWN_SERVICE_POLLING_INTERVAL || 120000, pollingInterval: ORACLE_SHUTDOWN_SERVICE_POLLING_INTERVAL || 120000,
@ -16,5 +16,6 @@ module.exports = {
checksBeforeStop: 1, checksBeforeStop: 1,
shutdownServiceURL: ORACLE_SHUTDOWN_SERVICE_URL, shutdownServiceURL: ORACLE_SHUTDOWN_SERVICE_URL,
shutdownContractAddress: ORACLE_SHUTDOWN_CONTRACT_ADDRESS, shutdownContractAddress: ORACLE_SHUTDOWN_CONTRACT_ADDRESS,
shutdownMethod: (ORACLE_SHUTDOWN_CONTRACT_METHOD || 'isShutdown()').trim() shutdownMethod: (ORACLE_SHUTDOWN_CONTRACT_METHOD || 'isShutdown()').trim(),
requestTimeout: 2000
} }

@ -3,8 +3,8 @@ const baseConfig = require('./base.config')
const id = `${baseConfig.id}-signature-request` const id = `${baseConfig.id}-signature-request`
module.exports = { module.exports = {
...baseConfig.bridgeConfig, ...baseConfig,
...baseConfig.homeConfig, main: baseConfig.home,
event: 'UserRequestForSignature', event: 'UserRequestForSignature',
queue: 'home-prioritized', queue: 'home-prioritized',
name: `watcher-${id}`, name: `watcher-${id}`,

@ -1,5 +1,5 @@
const baseConfig = require('./base.config') const baseConfig = require('./base.config')
const { ERC20_ABI, ERC_TYPES } = require('../../commons') const { ERC20_ABI } = require('../../commons')
const { EXIT_CODES } = require('../src/utils/constants') const { EXIT_CODES } = require('../src/utils/constants')
const initialChecksJson = process.argv[3] const initialChecksJson = process.argv[3]
@ -15,34 +15,22 @@ try {
throw new Error('Error on decoding values from initial checks.') throw new Error('Error on decoding values from initial checks.')
} }
if (baseConfig.id === 'erc-erc' && initialChecks.foreignERC === ERC_TYPES.ERC677) {
baseConfig.id = 'erc677-erc677'
}
const id = `${baseConfig.id}-transfer` const id = `${baseConfig.id}-transfer`
const transferWatcherRequired = if (baseConfig.id !== 'erc-native') {
(baseConfig.id === 'erc-erc' && initialChecks.foreignERC === ERC_TYPES.ERC20) || baseConfig.id === 'erc-native'
if (!transferWatcherRequired) {
console.error(`Transfer watcher not required for bridge mode ${process.env.ORACLE_BRIDGE_MODE}`) console.error(`Transfer watcher not required for bridge mode ${process.env.ORACLE_BRIDGE_MODE}`)
process.exit(EXIT_CODES.WATCHER_NOT_REQUIRED) process.exit(EXIT_CODES.WATCHER_NOT_REQUIRED)
} }
const workerQueueConfig = {}
if (baseConfig.id === 'erc-native') {
workerQueueConfig.workerQueue = 'convert-to-chai'
}
module.exports = { module.exports = {
...baseConfig.bridgeConfig, ...baseConfig,
...baseConfig.foreignConfig, main: {
...baseConfig.foreign,
eventContract: new baseConfig.foreign.web3.eth.Contract(ERC20_ABI, initialChecks.bridgeableTokenAddress)
},
event: 'Transfer', event: 'Transfer',
eventContractAddress: initialChecks.bridgeableTokenAddress,
eventAbi: ERC20_ABI,
eventFilter: { to: process.env.COMMON_FOREIGN_BRIDGE_ADDRESS }, eventFilter: { to: process.env.COMMON_FOREIGN_BRIDGE_ADDRESS },
queue: 'home-prioritized', queue: 'home-prioritized',
...workerQueueConfig,
name: `watcher-${id}`, name: `watcher-${id}`,
id id
} }

@ -6,14 +6,13 @@ services:
file: docker-compose.yml file: docker-compose.yml
service: rabbit service: rabbit
networks: networks:
- net_rabbit_bridge_transfer - net_rabbit_bridge_information
- net_rabbit_bridge_convert_to_chai_worker
redis: redis:
extends: extends:
file: docker-compose.yml file: docker-compose.yml
service: redis service: redis
networks: networks:
- net_db_bridge_transfer - net_db_bridge_information
bridge_request: bridge_request:
extends: extends:
file: docker-compose.yml file: docker-compose.yml
@ -25,9 +24,6 @@ services:
extends: extends:
file: docker-compose.yml file: docker-compose.yml
service: bridge_collected service: bridge_collected
volumes:
- '~/bridge_data/access-lists/block_list.txt:/mono/oracle/access-lists/block_list.txt'
- '~/bridge_data/access-lists/allowance_list.txt:/mono/oracle/access-lists/allowance_list.txt'
networks: networks:
- net_db_bridge_request - net_db_bridge_request
- net_rabbit_bridge_request - net_rabbit_bridge_request
@ -38,7 +34,7 @@ services:
networks: networks:
- net_db_bridge_request - net_db_bridge_request
- net_rabbit_bridge_request - net_rabbit_bridge_request
bridge_transfer: bridge_information:
cpus: 0.1 cpus: 0.1
mem_limit: 500m mem_limit: 500m
image: poanetwork/tokenbridge-oracle:latest image: poanetwork/tokenbridge-oracle:latest
@ -47,22 +43,10 @@ services:
- NODE_ENV=production - NODE_ENV=production
- ORACLE_VALIDATOR_ADDRESS=${ORACLE_VALIDATOR_ADDRESS} - ORACLE_VALIDATOR_ADDRESS=${ORACLE_VALIDATOR_ADDRESS}
restart: unless-stopped restart: unless-stopped
entrypoint: yarn watcher:transfer entrypoint: yarn watcher:information-request
networks: networks:
- net_db_bridge_transfer - net_db_bridge_information
- net_rabbit_bridge_transfer - net_rabbit_bridge_information
bridge_convert_to_chai_worker:
cpus: 0.1
mem_limit: 500m
image: poanetwork/tokenbridge-oracle:latest
env_file: ./.env
environment:
- NODE_ENV=production
- ORACLE_VALIDATOR_ADDRESS=${ORACLE_VALIDATOR_ADDRESS}
restart: unless-stopped
entrypoint: yarn worker:convert-to-chai
networks:
- net_rabbit_bridge_convert_to_chai_worker
bridge_senderhome: bridge_senderhome:
extends: extends:
file: docker-compose.yml file: docker-compose.yml
@ -91,25 +75,23 @@ networks:
driver: bridge driver: bridge
net_db_bridge_affirmation: net_db_bridge_affirmation:
driver: bridge driver: bridge
net_db_bridge_transfer: net_db_bridge_information:
driver: bridge driver: bridge
net_db_bridge_senderhome: net_db_bridge_senderhome:
driver: bridge driver: bridge
net_db_bridge_senderforeign: net_db_bridge_senderforeign:
driver: bridge driver: bridge
net_db_bridge_shutdown:
driver: bridge
net_rabbit_bridge_request: net_rabbit_bridge_request:
driver: bridge driver: bridge
net_db_bridge_shutdown:
driver: bridge
net_rabbit_bridge_collected: net_rabbit_bridge_collected:
driver: bridge driver: bridge
net_rabbit_bridge_affirmation: net_rabbit_bridge_affirmation:
driver: bridge driver: bridge
net_rabbit_bridge_transfer: net_rabbit_bridge_information:
driver: bridge driver: bridge
net_rabbit_bridge_senderhome: net_rabbit_bridge_senderhome:
driver: bridge driver: bridge
net_rabbit_bridge_senderforeign: net_rabbit_bridge_senderforeign:
driver: bridge driver: bridge
net_rabbit_bridge_convert_to_chai_worker:
driver: bridge

@ -24,6 +24,9 @@ services:
extends: extends:
file: docker-compose.yml file: docker-compose.yml
service: bridge_collected service: bridge_collected
volumes:
- '~/bridge_data/access-lists/block_list.txt:/mono/oracle/access-lists/block_list.txt'
- '~/bridge_data/access-lists/allowance_list.txt:/mono/oracle/access-lists/allowance_list.txt'
networks: networks:
- net_db_bridge_request - net_db_bridge_request
- net_rabbit_bridge_request - net_rabbit_bridge_request

@ -8,8 +8,8 @@
"watcher:signature-request": "./scripts/start-worker.sh watcher signature-request-watcher", "watcher:signature-request": "./scripts/start-worker.sh watcher signature-request-watcher",
"watcher:collected-signatures": "./scripts/start-worker.sh watcher collected-signatures-watcher", "watcher:collected-signatures": "./scripts/start-worker.sh watcher collected-signatures-watcher",
"watcher:affirmation-request": "./scripts/start-worker.sh watcher affirmation-request-watcher", "watcher:affirmation-request": "./scripts/start-worker.sh watcher affirmation-request-watcher",
"watcher:information-request": "./scripts/start-worker.sh watcher information-request-watcher",
"watcher:transfer": "./scripts/start-worker.sh watcher transfer-watcher", "watcher:transfer": "./scripts/start-worker.sh watcher transfer-watcher",
"worker:convert-to-chai": "./scripts/start-worker.sh worker convert-to-chai-worker",
"sender:home": "./scripts/start-worker.sh sender home-sender", "sender:home": "./scripts/start-worker.sh sender home-sender",
"sender:foreign": "./scripts/start-worker.sh sender foreign-sender", "sender:foreign": "./scripts/start-worker.sh sender foreign-sender",
"confirm:transfer": "./scripts/start-worker.sh confirmRelay transfer-watcher", "confirm:transfer": "./scripts/start-worker.sh confirmRelay transfer-watcher",
@ -47,6 +47,6 @@
"sinon": "^6.1.0" "sinon": "^6.1.0"
}, },
"engines": { "engines": {
"node": ">= 10.18" "node": ">= 12.22"
} }
} }

@ -1,56 +0,0 @@
require('../../env')
const { toWei } = require('web3').utils
const { web3Foreign } = require('../../src/services/web3')
const { sendTx } = require('../../src/tx/sendTx')
const { ERC20_ABI } = require('../../../commons')
const {
USER_ADDRESS,
USER_ADDRESS_PRIVATE_KEY,
COMMON_FOREIGN_BRIDGE_ADDRESS,
FOREIGN_MIN_AMOUNT_PER_TX,
FOREIGN_TEST_TX_GAS_PRICE
} = process.env
const NUMBER_OF_DEPOSITS_TO_SEND = process.argv[2] || process.env.NUMBER_OF_DEPOSITS_TO_SEND || 1
const { FOREIGN_ERC_TO_ERC_ABI } = require('../../../commons')
async function main() {
const bridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
const bridgeableTokenAddress = await bridge.methods.erc20token().call()
const poa20 = new web3Foreign.eth.Contract(ERC20_ABI, bridgeableTokenAddress)
try {
const foreignChainId = await web3Foreign.eth.getChainId()
let nonce = await web3Foreign.eth.getTransactionCount(USER_ADDRESS)
let actualSent = 0
for (let i = 0; i < Number(NUMBER_OF_DEPOSITS_TO_SEND); i++) {
const gasLimit = await poa20.methods
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, toWei(FOREIGN_MIN_AMOUNT_PER_TX))
.estimateGas({ from: USER_ADDRESS })
const data = await poa20.methods
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, toWei(FOREIGN_MIN_AMOUNT_PER_TX))
.encodeABI({ from: USER_ADDRESS })
const txHash = await sendTx({
privateKey: USER_ADDRESS_PRIVATE_KEY,
data,
nonce,
gasPrice: FOREIGN_TEST_TX_GAS_PRICE,
amount: '0',
gasLimit,
to: bridgeableTokenAddress,
web3: web3Foreign,
chainId: foreignChainId
})
if (txHash !== undefined) {
nonce++
actualSent++
console.log(actualSent, ' # ', txHash)
}
}
} catch (e) {
console.log(e)
}
}
main()

@ -1,87 +0,0 @@
require('../../env')
const { toWei } = require('web3').utils
const { web3Home } = require('../../src/services/web3')
const { sendTx } = require('../../src/tx/sendTx')
const { isValidAmount } = require('../utils/utils')
const { HOME_ERC_TO_ERC_ABI } = require('../../../commons')
const {
USER_ADDRESS,
USER_ADDRESS_PRIVATE_KEY,
COMMON_HOME_BRIDGE_ADDRESS,
HOME_MIN_AMOUNT_PER_TX,
HOME_TEST_TX_GAS_PRICE
} = process.env
const NUMBER_OF_WITHDRAWALS_TO_SEND = process.argv[2] || process.env.NUMBER_OF_WITHDRAWALS_TO_SEND || 1
const BRIDGEABLE_TOKEN_ABI = [
{
constant: false,
inputs: [
{
name: '_to',
type: 'address'
},
{
name: '_value',
type: 'uint256'
},
{
name: '_data',
type: 'bytes'
}
],
name: 'transferAndCall',
outputs: [
{
name: '',
type: 'bool'
}
],
payable: false,
stateMutability: 'nonpayable',
type: 'function'
}
]
async function main() {
const bridge = new web3Home.eth.Contract(HOME_ERC_TO_ERC_ABI, COMMON_HOME_BRIDGE_ADDRESS)
const BRIDGEABLE_TOKEN_ADDRESS = await bridge.methods.erc677token().call()
const erc677 = new web3Home.eth.Contract(BRIDGEABLE_TOKEN_ABI, BRIDGEABLE_TOKEN_ADDRESS)
try {
await isValidAmount(HOME_MIN_AMOUNT_PER_TX, bridge)
const homeChainId = await web3Home.eth.getChainId()
let nonce = await web3Home.eth.getTransactionCount(USER_ADDRESS)
let actualSent = 0
for (let i = 0; i < Number(NUMBER_OF_WITHDRAWALS_TO_SEND); i++) {
const gasLimit = await erc677.methods
.transferAndCall(COMMON_HOME_BRIDGE_ADDRESS, toWei(HOME_MIN_AMOUNT_PER_TX), '0x')
.estimateGas({ from: USER_ADDRESS })
const data = await erc677.methods
.transferAndCall(COMMON_HOME_BRIDGE_ADDRESS, toWei(HOME_MIN_AMOUNT_PER_TX), '0x')
.encodeABI({ from: USER_ADDRESS })
const txHash = await sendTx({
privateKey: USER_ADDRESS_PRIVATE_KEY,
data,
nonce,
gasPrice: HOME_TEST_TX_GAS_PRICE,
amount: '0',
gasLimit,
to: BRIDGEABLE_TOKEN_ADDRESS,
web3: web3Home,
chainId: homeChainId
})
if (txHash !== undefined) {
nonce++
actualSent++
console.log(actualSent, ' # ', txHash)
}
}
} catch (e) {
console.log(e)
}
}
main()

@ -1,16 +1,10 @@
require('../env') require('../env')
const { BRIDGE_VALIDATORS_ABI } = require('../../commons') const { BRIDGE_VALIDATORS_ABI } = require('../../commons')
const { web3Home, web3Foreign } = require('../src/services/web3') const { home, foreign } = require('../config/base.config')
const { bridgeConfig } = require('../config/base.config')
const homeABI = bridgeConfig.homeBridgeAbi async function getStartBlock(bridgeContract, web3) {
const foreignABI = bridgeConfig.foreignBridgeAbi
async function getStartBlock(web3, bridgeAddress, bridgeAbi) {
try { try {
const bridgeContract = new web3.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()
@ -30,10 +24,8 @@ async function getStartBlock(web3, bridgeAddress, bridgeAbi) {
} }
async function main() { async function main() {
const { COMMON_HOME_BRIDGE_ADDRESS, COMMON_FOREIGN_BRIDGE_ADDRESS } = process.env const homeStartBlock = await getStartBlock(home.bridgeContract, home.web3)
const foreignStartBlock = await getStartBlock(foreign.bridgeContract, foreign.web3)
const homeStartBlock = await getStartBlock(web3Home, COMMON_HOME_BRIDGE_ADDRESS, homeABI)
const foreignStartBlock = await getStartBlock(web3Foreign, COMMON_FOREIGN_BRIDGE_ADDRESS, foreignABI)
const result = { const result = {
homeStartBlock, homeStartBlock,
foreignStartBlock foreignStartBlock

Some files were not shown because too many files have changed in this diff Show More