Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78564afabd | ||
|
|
70a2c30b4c | ||
|
|
06a9586148 | ||
|
|
7379fe4190 | ||
|
|
e59766c5df | ||
|
|
fdb18a1a17 | ||
|
|
4412046f66 | ||
|
|
0ff224ccd3 | ||
|
|
5cedacafe5 | ||
|
|
2e6179f974 | ||
|
|
4f5e3c47be | ||
|
|
4c06329153 | ||
|
|
d53452675e | ||
|
|
c92f80c484 | ||
|
|
5e95b5d8c5 | ||
|
|
6e1f57493a | ||
|
|
8ed6550635 | ||
|
|
c8eb0f1ed8 | ||
|
|
3e5e50c06e | ||
|
|
92e1b597c4 | ||
|
|
8b1a97e673 | ||
|
|
3cf184c391 | ||
|
|
8f72516374 | ||
|
|
98155e3075 | ||
|
|
0d724147bd | ||
|
|
3b959776f3 | ||
|
|
ffbca8b941 | ||
|
|
38f1bae8f5 |
39
.github/workflows/main.yml
vendored
39
.github/workflows/main.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
node-version: 12
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
node-version: 12
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
@@ -70,19 +70,19 @@ jobs:
|
||||
- name: Evaluate e2e docker images tags
|
||||
run: |
|
||||
git submodule status > submodule.status
|
||||
echo "E2E_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}" >> $GITHUB_ENV
|
||||
echo "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 "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
|
||||
- name: Rebuild and push updated images
|
||||
run: |
|
||||
function check_if_image_exists() {
|
||||
curl -fsSlL -H 'Authorization: bearer ${{ github.token }}' "https://${DOCKER_REGISTRY}/v2/${DOCKER_REPO}/tokenbridge-e2e-$1/manifests/$2" > /dev/null
|
||||
curl -fsSlL "https://${{ github.actor }}:${{ github.token }}@${DOCKER_REGISTRY}/v2/${DOCKER_REPO}/tokenbridge-e2e-$1/manifests/$2" > /dev/null
|
||||
}
|
||||
updated=()
|
||||
if ! check_if_image_exists e2e ${E2E_TAG}; then updated+=("e2e"); fi
|
||||
if ! check_if_image_exists oracle ${ORACLE_TAG}; then updated+=("oracle"); fi
|
||||
if ! check_if_image_exists monitor ${MONITOR_TAG}; then updated+=("monitor"); fi
|
||||
if ! check_if_image_exists oracle ${ORACLE_TAG}; then updated+=("oracle-amb"); 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 [ ${#updated[@]} -gt 0 ]; then
|
||||
echo "Updated services: ${updated[@]}"
|
||||
@@ -104,7 +104,7 @@ jobs:
|
||||
- name: Rebuild and push molecule runner e2e image
|
||||
run: |
|
||||
function check_if_image_exists() {
|
||||
curl -fsSlL -H 'Authorization: bearer ${{ github.token }}' "https://${DOCKER_REGISTRY}/v2/${DOCKER_REPO}/tokenbridge-e2e-$1/manifests/$2" > /dev/null
|
||||
curl -fsSlL "https://${{ github.actor }}:${{ github.token }}@${DOCKER_REGISTRY}/v2/${DOCKER_REPO}/tokenbridge-e2e-$1/manifests/$2" > /dev/null
|
||||
}
|
||||
if check_if_image_exists molecule_runner ${MOLECULE_RUNNER_TAG}; then
|
||||
echo "Image already exists"
|
||||
@@ -133,7 +133,7 @@ jobs:
|
||||
- name: Evaluate e2e docker images tags
|
||||
run: |
|
||||
git submodule status > submodule.status
|
||||
echo "E2E_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}" >> $GITHUB_ENV
|
||||
echo "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 "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
|
||||
@@ -149,6 +149,12 @@ jobs:
|
||||
run: docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }}
|
||||
- name: yarn run ${{ matrix.task }}
|
||||
run: ${{ !matrix.use-cache || steps.cache-repo.outputs.cache-hit }} && yarn run ${{ matrix.task }}
|
||||
- name: Upload logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: logs-${{ matrix.task }}
|
||||
path: e2e-commons/logs
|
||||
deployment:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
@@ -176,7 +182,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
task: [amb, erc-to-erc, erc-to-native, native-to-erc]
|
||||
task: [amb, erc-to-native]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
@@ -184,7 +190,7 @@ jobs:
|
||||
- name: Evaluate e2e docker images tags
|
||||
run: |
|
||||
git submodule status > submodule.status
|
||||
echo "E2E_TAG=${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}" >> $GITHUB_ENV
|
||||
echo "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 "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
|
||||
@@ -199,10 +205,10 @@ jobs:
|
||||
- name: Login to docker registry
|
||||
run: docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }}
|
||||
- name: Deploy contracts
|
||||
run: ${{ steps.cache-repo.outputs.cache-hit }} && e2e-commons/up.sh deploy blocks
|
||||
run: ${{ steps.cache-repo.outputs.cache-hit }} && e2e-commons/up.sh deploy generate-amb-tx blocks
|
||||
- name: Pull e2e oracle image
|
||||
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
|
||||
- name: Deploy oracle
|
||||
run: deployment-e2e/molecule.sh ultimate-${{ matrix.task }}
|
||||
@@ -210,3 +216,12 @@ jobs:
|
||||
run: sudo chown -R $USER:docker /var/run/docker.sock
|
||||
- name: Run oracle e2e tests
|
||||
run: docker-compose -f ./e2e-commons/docker-compose.yml run -e ULTIMATE=true e2e yarn workspace oracle-e2e run ${{ matrix.task }}
|
||||
- name: Save logs
|
||||
if: always()
|
||||
run: e2e-commons/down.sh
|
||||
- name: Upload logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: logs-ultimate-${{ matrix.task }}
|
||||
path: e2e-commons/logs
|
||||
|
||||
@@ -22,7 +22,7 @@ COMMON_FOREIGN_GAS_PRICE_FACTOR | A value that will multiply the gas price of th
|
||||
|
||||
name | description | value
|
||||
--- | --- | ---
|
||||
ORACLE_BRIDGE_MODE | The bridge mode. The bridge starts listening to a different set of events based on this parameter. | NATIVE_TO_ERC / ERC_TO_ERC / ERC_TO_NATIVE / 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_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
|
||||
@@ -47,10 +47,12 @@ 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_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_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_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_HOME_RPC_BLOCK_POLLING_LIMIT | Max length for the block range used in `eth_getLogs` requests for polling contract events for the Home chain. Infinite, if not provided. | `integer`
|
||||
ORACLE_JSONRPC_ERROR_CODES | Override default JSON rpc error codes that can trigger RPC fallback to the next URL from the list (or a retry in case of a single RPC URL). Default is `-32603,-32002,-32005`. Should be a comma-separated list of negative integers. | `string`
|
||||
|
||||
|
||||
## Monitor configuration
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:10 as contracts
|
||||
FROM node:12 as contracts
|
||||
|
||||
WORKDIR /mono
|
||||
|
||||
@@ -11,7 +11,7 @@ COPY ./contracts/truffle-config.js ./
|
||||
COPY ./contracts/contracts ./contracts
|
||||
RUN npm run compile
|
||||
|
||||
FROM node:10
|
||||
FROM node:12
|
||||
|
||||
WORKDIR /mono
|
||||
COPY package.json .
|
||||
@@ -19,6 +19,7 @@ COPY --from=contracts /mono/contracts/build ./contracts/build
|
||||
COPY commons/package.json ./commons/
|
||||
COPY oracle-e2e/package.json ./oracle-e2e/
|
||||
COPY monitor-e2e/package.json ./monitor-e2e/
|
||||
COPY oracle/src/utils/constants.js ./oracle/src/utils/constants.js
|
||||
|
||||
COPY yarn.lock .
|
||||
RUN NOYARNPOSTINSTALL=1 yarn install --frozen-lockfile --production
|
||||
|
||||
@@ -54,8 +54,6 @@ Additionally there are [Smart Contracts](https://github.com/poanetwork/tokenbrid
|
||||
|
||||
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] `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"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.18"
|
||||
"node": ">= 12.22"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
cd $(dirname $0)
|
||||
|
||||
../e2e-commons/up.sh deploy blocks alm alm-e2e
|
||||
../e2e-commons/up.sh deploy generate-amb-tx blocks alm alm-e2e
|
||||
|
||||
# run oracle amb e2e tests to generate transactions for alm
|
||||
docker-compose -f ../e2e-commons/docker-compose.yml run e2e yarn workspace oracle-e2e run alm
|
||||
|
||||
@@ -6,8 +6,8 @@ jest.setTimeout(60000)
|
||||
const statusText = 'Success'
|
||||
const statusSelector = 'label[data-id="status"]'
|
||||
|
||||
const homeToForeignTxURL = 'http://localhost:3004/77/0x58e7d63368335b9591d4dbb43889084f698fcee93ab7656fd7a39d8c66bc4b60'
|
||||
const foreignToHomeTxURL = 'http://localhost:3004/42/0x592bf28fc896419d2838f71cd0388775814b692688f1ecd5b1519081566b994a'
|
||||
const homeToForeignTxURL = 'http://localhost:3004/77/0x295efbe6ae98937ef35d939376c9bd752b4dc6f6899a9d5ddd6a57cea3d76c89'
|
||||
const foreignToHomeTxURL = 'http://localhost:3004/42/0x7262f7dbe6c30599edded2137fbbe93c271b37f5c54dd27f713f0cf510e3b4dd'
|
||||
|
||||
describe('ALM', () => {
|
||||
let browser
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:10 as contracts
|
||||
FROM node:12 as contracts
|
||||
|
||||
WORKDIR /mono
|
||||
|
||||
|
||||
@@ -123,6 +123,24 @@ const abi: AbiItem[] = [
|
||||
stateMutability: 'nonpayable',
|
||||
type: 'function'
|
||||
},
|
||||
{
|
||||
constant: false,
|
||||
inputs: [
|
||||
{
|
||||
name: '_data',
|
||||
type: 'bytes'
|
||||
},
|
||||
{
|
||||
name: '_signatures',
|
||||
type: 'bytes'
|
||||
}
|
||||
],
|
||||
name: 'safeExecuteSignaturesWithAutoGasLimit',
|
||||
outputs: [],
|
||||
payable: false,
|
||||
stateMutability: 'nonpayable',
|
||||
type: 'function'
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { formatTimestamp, formatTxHash, getExplorerTxUrl } from '../utils/networks'
|
||||
import { useWindowWidth } from '@react-hook/window-size'
|
||||
import { SEARCHING_TX, VALIDATOR_CONFIRMATION_STATUS, ALM_HOME_TO_FOREIGN_MANUAL_EXECUTION } from '../config/constants'
|
||||
@@ -9,6 +9,7 @@ import { GreyLabel, RedLabel, SuccessLabel } from './commons/Labels'
|
||||
import { ExplorerTxLink } from './commons/ExplorerTxLink'
|
||||
import { Thead, AgeTd, StatusTd } from './commons/Table'
|
||||
import { ManualExecutionButton } from './ManualExecutionButton'
|
||||
import { useStateProvider } from '../state/StateProvider'
|
||||
|
||||
const StyledExecutionConfirmation = styled.div`
|
||||
margin-top: 30px;
|
||||
@@ -33,6 +34,8 @@ export const ExecutionConfirmation = ({
|
||||
executionEventsFetched,
|
||||
setPendingExecution
|
||||
}: ExecutionConfirmationParams) => {
|
||||
const { foreign } = useStateProvider()
|
||||
const [safeExecutionAvailable, setSafeExecutionAvailable] = useState(false)
|
||||
const availableManualExecution =
|
||||
!isHome &&
|
||||
(executionData.status === VALIDATOR_CONFIRMATION_STATUS.WAITING ||
|
||||
@@ -48,6 +51,22 @@ export const ExecutionConfirmation = ({
|
||||
const formattedValidator =
|
||||
windowWidth < 850 && executionData.validator ? formatTxHash(executionData.validator) : executionData.validator
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
if (!availableManualExecution || !foreign.bridgeContract) return
|
||||
|
||||
const p = foreign.bridgeContract.methods.getBridgeInterfacesVersion().call()
|
||||
p.then(({ major, minor }: any) => {
|
||||
major = parseInt(major, 10)
|
||||
minor = parseInt(minor, 10)
|
||||
if (major < 5 || (major === 5 && minor < 7)) return
|
||||
|
||||
setSafeExecutionAvailable(true)
|
||||
})
|
||||
},
|
||||
[availableManualExecution, foreign.bridgeContract]
|
||||
)
|
||||
|
||||
const getExecutionStatusElement = (validatorStatus = '') => {
|
||||
switch (validatorStatus) {
|
||||
case VALIDATOR_CONFIRMATION_STATUS.SUCCESS:
|
||||
@@ -105,6 +124,7 @@ export const ExecutionConfirmation = ({
|
||||
{availableManualExecution && (
|
||||
<td>
|
||||
<ManualExecutionButton
|
||||
safeExecutionAvailable={safeExecutionAvailable}
|
||||
messageData={messageData}
|
||||
setExecutionData={setExecutionData}
|
||||
signatureCollected={signatureCollected as string[]}
|
||||
|
||||
@@ -15,16 +15,19 @@ import { signatureToVRS, packSignatures } from '../utils/signatures'
|
||||
import { getSuccessExecutionData } from '../utils/getFinalizationEvent'
|
||||
import { TransactionReceipt } from 'web3-eth'
|
||||
|
||||
const StyledButton = styled.button`
|
||||
const ActionButton = styled.button`
|
||||
color: var(--button-color);
|
||||
border-color: var(--font-color);
|
||||
margin-top: 10px;
|
||||
min-width: 120px;
|
||||
padding: 1rem;
|
||||
&:focus {
|
||||
outline: var(--button-color);
|
||||
}
|
||||
`
|
||||
|
||||
interface ManualExecutionButtonParams {
|
||||
safeExecutionAvailable: boolean
|
||||
messageData: string
|
||||
setExecutionData: Function
|
||||
signatureCollected: string[]
|
||||
@@ -32,6 +35,7 @@ interface ManualExecutionButtonParams {
|
||||
}
|
||||
|
||||
export const ManualExecutionButton = ({
|
||||
safeExecutionAvailable,
|
||||
messageData,
|
||||
setExecutionData,
|
||||
signatureCollected,
|
||||
@@ -40,6 +44,7 @@ export const ManualExecutionButton = ({
|
||||
const { foreign, setError } = useStateProvider()
|
||||
const { library, activate, account, active } = useWeb3React()
|
||||
const [manualExecution, setManualExecution] = useState(false)
|
||||
const [allowFailures, setAllowFailures] = useState(false)
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
@@ -72,7 +77,11 @@ export const ManualExecutionButton = ({
|
||||
const signatures = packSignatures(signatureCollected.map(signatureToVRS))
|
||||
const messageId = messageData.slice(0, 66)
|
||||
const bridge = foreign.bridgeContract
|
||||
const data = bridge.methods.executeSignatures(messageData, signatures).encodeABI()
|
||||
const executeMethod =
|
||||
safeExecutionAvailable && !allowFailures
|
||||
? bridge.methods.safeExecuteSignaturesWithAutoGasLimit
|
||||
: bridge.methods.executeSignatures
|
||||
const data = executeMethod(messageData, signatures).encodeABI()
|
||||
setManualExecution(false)
|
||||
|
||||
library.eth
|
||||
@@ -132,15 +141,35 @@ export const ManualExecutionButton = ({
|
||||
messageData,
|
||||
signatureCollected,
|
||||
setExecutionData,
|
||||
setPendingExecution
|
||||
setPendingExecution,
|
||||
safeExecutionAvailable,
|
||||
allowFailures
|
||||
]
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="is-center">
|
||||
<StyledButton className="button outline" onClick={() => setManualExecution(true)}>
|
||||
Execute
|
||||
</StyledButton>
|
||||
<div>
|
||||
<div className="is-center">
|
||||
<ActionButton className="button outline" onClick={() => setManualExecution(true)}>
|
||||
Execute
|
||||
</ActionButton>
|
||||
</div>
|
||||
{safeExecutionAvailable && (
|
||||
<div
|
||||
title="Allow executed message to fail and record its failure on-chain without reverting the whole transaction.
|
||||
Use fixed gas limit for execution."
|
||||
className="is-center"
|
||||
style={{ paddingTop: 10 }}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="allow-failures"
|
||||
checked={allowFailures}
|
||||
onChange={e => setAllowFailures(e.target.checked)}
|
||||
/>
|
||||
<label htmlFor="allow-failures">Unsafe mode</label>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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 FOREIGN_ERC_TO_NATIVE_ABI = require('../contracts/build/contracts/ForeignBridgeErcToNative').abi
|
||||
const FOREIGN_ERC_TO_NATIVE_ABI = require('../contracts/build/contracts/XDaiForeignBridge.json').abi
|
||||
const ERC20_ABI = require('../contracts/build/contracts/ERC20').abi
|
||||
const ERC677_ABI = require('../contracts/build/contracts/ERC677').abi
|
||||
const ERC677_BRIDGE_TOKEN_ABI = require('../contracts/build/contracts/ERC677BridgeToken').abi
|
||||
const BLOCK_REWARD_ABI = require('../contracts/build/contracts/BlockReward').abi
|
||||
const BLOCK_REWARD_ABI = require('../contracts/build/contracts/BlockRewardMock').abi
|
||||
const BRIDGE_VALIDATORS_ABI = require('../contracts/build/contracts/BridgeValidators').abi
|
||||
const REWARDABLE_VALIDATORS_ABI = require('../contracts/build/contracts/RewardableValidators').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 HOME_AMB_ERC_TO_ERC_ABI = require('../contracts/build/contracts/HomeAMBErc677ToErc677').abi
|
||||
const FOREIGN_AMB_ERC_TO_ERC_ABI = require('../contracts/build/contracts/ForeignAMBErc677ToErc677').abi
|
||||
const HOME_STAKE_ERC_TO_ERC_ABI = require('../contracts/build/contracts/HomeStakeTokenMediator').abi
|
||||
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 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 = [
|
||||
{
|
||||
anonymous: false,
|
||||
@@ -85,27 +45,15 @@ const OLD_AMB_USER_REQUEST_FOR_AFFIRMATION_ABI = [
|
||||
function getBridgeABIs(bridgeMode) {
|
||||
let HOME_ABI = null
|
||||
let FOREIGN_ABI = null
|
||||
if (bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC) {
|
||||
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) {
|
||||
if (bridgeMode === BRIDGE_MODES.ERC_TO_NATIVE) {
|
||||
HOME_ABI = HOME_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) {
|
||||
HOME_ABI = HOME_AMB_ABI
|
||||
FOREIGN_ABI = FOREIGN_AMB_ABI
|
||||
} else if (bridgeMode === BRIDGE_MODES.AMB_ERC_TO_ERC) {
|
||||
HOME_ABI = HOME_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 {
|
||||
throw new Error(`Unrecognized bridge mode: ${bridgeMode}`)
|
||||
}
|
||||
@@ -115,26 +63,15 @@ function getBridgeABIs(bridgeMode) {
|
||||
|
||||
module.exports = {
|
||||
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,
|
||||
FOREIGN_ERC_TO_NATIVE_ABI,
|
||||
ERC20_ABI,
|
||||
ERC677_ABI,
|
||||
ERC677_BRIDGE_TOKEN_ABI,
|
||||
BLOCK_REWARD_ABI,
|
||||
BRIDGE_VALIDATORS_ABI,
|
||||
REWARDABLE_VALIDATORS_ABI,
|
||||
HOME_V1_ABI,
|
||||
FOREIGN_V1_ABI,
|
||||
ERC20_BYTES32_ABI,
|
||||
HOME_AMB_ABI,
|
||||
FOREIGN_AMB_ABI,
|
||||
OLD_AMB_USER_REQUEST_FOR_AFFIRMATION_ABI,
|
||||
OLD_AMB_USER_REQUEST_FOR_SIGNATURE_ABI,
|
||||
BOX_ABI,
|
||||
HOME_STAKE_ERC_TO_ERC_ABI,
|
||||
FOREIGN_STAKE_ERC_TO_ERC_ABI
|
||||
BOX_ABI
|
||||
}
|
||||
|
||||
@@ -1,30 +1,12 @@
|
||||
const BRIDGE_MODES = {
|
||||
NATIVE_TO_ERC: 'NATIVE_TO_ERC',
|
||||
ERC_TO_ERC: 'ERC_TO_ERC',
|
||||
ERC_TO_NATIVE: 'ERC_TO_NATIVE',
|
||||
NATIVE_TO_ERC_V1: 'NATIVE_TO_ERC_V1',
|
||||
ARBITRARY_MESSAGE: 'ARBITRARY_MESSAGE',
|
||||
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'
|
||||
AMB_ERC_TO_ERC: 'AMB_ERC_TO_ERC'
|
||||
}
|
||||
|
||||
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
|
||||
|
||||
module.exports = {
|
||||
BRIDGE_MODES,
|
||||
ERC_TYPES,
|
||||
FEE_MANAGER_MODE,
|
||||
ZERO_ADDRESS
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
const { soliditySha3 } = require('web3-utils')
|
||||
|
||||
function strip0x(input) {
|
||||
return input.replace(/^0x/, '')
|
||||
}
|
||||
@@ -39,8 +41,35 @@ const normalizeAMBMessageEvent = e => {
|
||||
return parseAMBMessage(msgData)
|
||||
}
|
||||
|
||||
const ambInformationSignatures = [
|
||||
'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)'
|
||||
]
|
||||
const ambInformationSelectors = Object.fromEntries(ambInformationSignatures.map(sig => [soliditySha3(sig), sig]))
|
||||
const normalizeAMBInfoRequest = e => ({
|
||||
messageId: e.returnValues.messageId,
|
||||
sender: e.returnValues.sender,
|
||||
requestSelector: ambInformationSelectors[e.returnValues.requestSelector] || 'unknown',
|
||||
data: e.returnValues.data
|
||||
})
|
||||
|
||||
module.exports = {
|
||||
strip0x,
|
||||
parseAMBMessage,
|
||||
normalizeAMBMessageEvent
|
||||
normalizeAMBMessageEvent,
|
||||
ambInformationSignatures,
|
||||
normalizeAMBInfoRequest
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"gas-price-oracle": "^0.1.5",
|
||||
"web3-utils": "1.0.0-beta.34"
|
||||
"web3-utils": "^1.3.0",
|
||||
"node-fetch": "^2.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bn-chai": "^1.0.1",
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
const { expect } = require('chai')
|
||||
const { BRIDGE_MODES, ERC_TYPES } = require('../constants')
|
||||
const { BRIDGE_MODES } = require('../constants')
|
||||
|
||||
describe('constants', () => {
|
||||
it('should contain correct number of bridge types', () => {
|
||||
expect(Object.keys(BRIDGE_MODES).length).to.be.equal(7)
|
||||
})
|
||||
|
||||
it('should contain correct number of erc types', () => {
|
||||
expect(Object.keys(ERC_TYPES).length).to.be.equal(2)
|
||||
expect(Object.keys(BRIDGE_MODES).length).to.be.equal(3)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
104
commons/utils.js
104
commons/utils.js
@@ -1,22 +1,17 @@
|
||||
const { toWei, toBN, BN } = require('web3-utils')
|
||||
const { GasPriceOracle } = require('gas-price-oracle')
|
||||
const { BRIDGE_MODES, FEE_MANAGER_MODE, ERC_TYPES } = require('./constants')
|
||||
const fetch = require('node-fetch')
|
||||
const { BRIDGE_MODES } = require('./constants')
|
||||
const { REWARDABLE_VALIDATORS_ABI } = require('./abis')
|
||||
|
||||
const gasPriceOracle = new GasPriceOracle()
|
||||
|
||||
function decodeBridgeMode(bridgeModeHash) {
|
||||
switch (bridgeModeHash) {
|
||||
case '0x92a8d7fe':
|
||||
return BRIDGE_MODES.NATIVE_TO_ERC
|
||||
case '0xba4690f5':
|
||||
return BRIDGE_MODES.ERC_TO_ERC
|
||||
case '0x18762d46':
|
||||
return BRIDGE_MODES.ERC_TO_NATIVE
|
||||
case '0x2544fbb9':
|
||||
return BRIDGE_MODES.ARBITRARY_MESSAGE
|
||||
case '0x16ea01e9':
|
||||
return BRIDGE_MODES.STAKE_AMB_ERC_TO_ERC
|
||||
case '0x76595b56':
|
||||
return BRIDGE_MODES.AMB_ERC_TO_ERC
|
||||
default:
|
||||
@@ -24,80 +19,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) {
|
||||
try {
|
||||
const bridgeModeHash = await contract.methods.getBridgeMode().call()
|
||||
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 bridgeModeHash = await contract.methods.getBridgeMode().call()
|
||||
return decodeBridgeMode(bridgeModeHash)
|
||||
}
|
||||
|
||||
const parseValidatorEvent = event => {
|
||||
@@ -255,17 +179,16 @@ const normalizeGasPrice = (oracleGasPrice, factor, limits = null) => {
|
||||
return toBN(toWei(gasPrice.toFixed(2).toString(), 'gwei'))
|
||||
}
|
||||
|
||||
// fetchFn has to be supplied (instead of just url to oracle),
|
||||
// because this utility function is shared between Browser and Node,
|
||||
// we use built-in 'fetch' on browser side, and `node-fetch` package in Node.
|
||||
const gasPriceFromSupplier = async (fetchFn, options = {}) => {
|
||||
const gasPriceFromSupplier = async (url, options = {}) => {
|
||||
try {
|
||||
let json
|
||||
if (fetchFn) {
|
||||
const response = await fetchFn()
|
||||
if (url === 'gas-price-oracle') {
|
||||
json = await gasPriceOracle.fetchGasPricesOffChain()
|
||||
} else if (url) {
|
||||
const response = await fetch(url, { timeout: 2000 })
|
||||
json = await response.json()
|
||||
} else {
|
||||
json = await gasPriceOracle.fetchGasPricesOffChain()
|
||||
return null
|
||||
}
|
||||
const oracleGasPrice = json[options.speedType]
|
||||
|
||||
@@ -306,10 +229,7 @@ const gasPriceFromContract = async (bridgeContract, options = {}) => {
|
||||
|
||||
module.exports = {
|
||||
decodeBridgeMode,
|
||||
decodeFeeManagerMode,
|
||||
getBridgeMode,
|
||||
getTokenType,
|
||||
getUnit,
|
||||
parseValidatorEvent,
|
||||
processValidatorsEvents,
|
||||
getValidatorList,
|
||||
@@ -318,7 +238,5 @@ module.exports = {
|
||||
normalizeGasPrice,
|
||||
gasPriceFromSupplier,
|
||||
gasPriceFromContract,
|
||||
gasPriceWithinLimits,
|
||||
isErcToErcMode,
|
||||
isMediatorMode
|
||||
gasPriceWithinLimits
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
Submodule contracts updated: c9377114f7...908a481079
@@ -34,7 +34,7 @@ provisioner:
|
||||
inventory:
|
||||
host_vars:
|
||||
multiple-host:
|
||||
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9"
|
||||
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "6c48435bd464a53ed66ed62127c4dba8af75cf1a99a8ebe2680599948fbfbc6d"
|
||||
MONITOR_PORT: 3003
|
||||
syslog_server_port: "udp://127.0.0.1:514"
|
||||
verifier:
|
||||
|
||||
@@ -33,7 +33,7 @@ provisioner:
|
||||
inventory:
|
||||
host_vars:
|
||||
oracle-host:
|
||||
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9"
|
||||
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "6c48435bd464a53ed66ed62127c4dba8af75cf1a99a8ebe2680599948fbfbc6d"
|
||||
syslog_server_port: "udp://127.0.0.1:514"
|
||||
verifier:
|
||||
name: testinfra
|
||||
|
||||
@@ -9,15 +9,17 @@
|
||||
- oracle_net_db_bridge_request
|
||||
- oracle_net_db_bridge_collected
|
||||
- oracle_net_db_bridge_affirmation
|
||||
- oracle_net_db_bridge_information
|
||||
- oracle_net_db_bridge_transfer
|
||||
- oracle_net_db_bridge_senderhome
|
||||
- oracle_net_db_bridge_senderforeign
|
||||
- oracle_net_db_bridge_shutdown
|
||||
- oracle_net_rabbit_bridge_request
|
||||
- oracle_net_rabbit_bridge_collected
|
||||
- oracle_net_rabbit_bridge_affirmation
|
||||
- oracle_net_rabbit_bridge_information
|
||||
- oracle_net_rabbit_bridge_transfer
|
||||
- oracle_net_rabbit_bridge_senderhome
|
||||
- oracle_net_rabbit_bridge_senderforeign
|
||||
- oracle_net_rabbit_bridge_convert_to_chai_worker
|
||||
delegate_to: 127.0.0.1
|
||||
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"
|
||||
COMMON_HOME_BRIDGE_ADDRESS: "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0"
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0"
|
||||
COMMON_HOME_BRIDGE_ADDRESS: "0x8397be90BCF57b0B71219f555Fe121b22e5a994C"
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x1feB40aD9420b186F019A717c37f5546165d411E"
|
||||
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"
|
||||
COMMON_HOME_BRIDGE_ADDRESS: "0x488Af810997eD1730cB3a3918cD83b3216E6eAda"
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x488Af810997eD1730cB3a3918cD83b3216E6eAda"
|
||||
COMMON_HOME_BRIDGE_ADDRESS: "0x5118AC62AE912Dd5B51EEfF7338c4fcb0248Ba8c"
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x32198D570fffC7033641F8A9094FFDCaAEF42624"
|
||||
MONITOR_PORT: 3012
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
---
|
||||
## General settings
|
||||
ORACLE_BRIDGE_MODE: "NATIVE_TO_ERC"
|
||||
ORACLE_BRIDGE_MODE: "ARBITRARY_MESSAGE"
|
||||
ORACLE_LOG_LEVEL: debug
|
||||
|
||||
## Home contract
|
||||
COMMON_HOME_RPC_URL: "https://sokol.poa.network"
|
||||
COMMON_HOME_BRIDGE_ADDRESS: "0x98aFdE294f1C46aA0a27Cc4049ED337F879d8976"
|
||||
COMMON_HOME_BRIDGE_ADDRESS: "0x59ba90A588ce732AB33FD32Aab1b58c21400A0f6"
|
||||
ORACLE_HOME_RPC_POLLING_INTERVAL: 5000
|
||||
|
||||
## Foreign contract
|
||||
COMMON_FOREIGN_RPC_URL: "https://sokol.poa.network"
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x5a584f4C30B36f282848dAc9a2b20E7BEF481981"
|
||||
ORACLE_FOREIGN_RPC_POLLING_INTERVAL: 1000
|
||||
COMMON_FOREIGN_RPC_URL: "https://kovan.infura.io/v3/5d7bd94c50ed43fab1cb8e74f58678b0"
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS: "0xdA4a49a00F4fF4A5988b9AceE95f99e3b2c208b6"
|
||||
ORACLE_FOREIGN_RPC_POLLING_INTERVAL: 5000
|
||||
|
||||
## Home Gasprice
|
||||
COMMON_HOME_GAS_PRICE_SUPPLIER_URL: "https://gasprice.poa.network/"
|
||||
@@ -31,8 +31,8 @@ ORACLE_FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000
|
||||
MONITOR_BRIDGE_NAME: "bridge"
|
||||
MONITOR_PORT: 3003
|
||||
MONITOR_CACHE_EVENTS: "false"
|
||||
MONITOR_HOME_START_BLOCK: 0
|
||||
MONITOR_FOREIGN_START_BLOCK: 0
|
||||
MONITOR_HOME_START_BLOCK: 20821049
|
||||
MONITOR_FOREIGN_START_BLOCK: 24773297
|
||||
MONITOR_VALIDATOR_HOME_TX_LIMIT: 300000
|
||||
MONITOR_VALIDATOR_FOREIGN_TX_LIMIT: 300000
|
||||
MONITOR_TX_NUMBER_THRESHOLD: 100
|
||||
|
||||
@@ -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
|
||||
@@ -1,6 +1,6 @@
|
||||
/var/log/docker/*/docker.log {
|
||||
rotate 5
|
||||
size 1G
|
||||
size 100M
|
||||
compress
|
||||
missingok
|
||||
delaycompress
|
||||
@@ -8,7 +8,7 @@
|
||||
}
|
||||
/var/log/docker/*.log {
|
||||
rotate 5
|
||||
size 1G
|
||||
size 100M
|
||||
compress
|
||||
missingok
|
||||
delaycompress
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
with_items:
|
||||
- docker-compose
|
||||
- docker-compose-transfer
|
||||
- docker-compose-erc-native
|
||||
- docker-compose-amb
|
||||
loop_control:
|
||||
loop_var: file
|
||||
|
||||
- name: Set the local container logs configuration file
|
||||
- name: Set the oracle's containers local logs configuration file
|
||||
template:
|
||||
src: 31-oracle-docker.conf.j2
|
||||
dest: /etc/rsyslog.d/31-oracle-docker.conf
|
||||
@@ -15,6 +15,22 @@
|
||||
group: root
|
||||
mode: 0644
|
||||
|
||||
- name: Set the redis container local logs configuration file
|
||||
template:
|
||||
src: 32-redis-docker.conf.j2
|
||||
dest: /etc/rsyslog.d/32-redis-docker.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0644
|
||||
|
||||
- name: Set the rabbit MQ container local logs configuration file
|
||||
template:
|
||||
src: 33-rabbit-docker.conf.j2
|
||||
dest: /etc/rsyslog.d/33-rabbit-docker.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0644
|
||||
|
||||
- name: Set the log configuration file to send container logs to remote server
|
||||
template:
|
||||
src: 36-oracle-remote-logging.conf.j2
|
||||
|
||||
@@ -27,25 +27,14 @@
|
||||
set_fact:
|
||||
ORACLE_VALIDATOR_ADDRESS: "{{ VADDRESS.stdout }}"
|
||||
|
||||
- name: Get foreign erc type
|
||||
become_user: "{{ compose_service_user }}"
|
||||
shell: docker-compose run --rm --entrypoint "node scripts/initialChecks.js" bridge_affirmation
|
||||
args:
|
||||
chdir: "{{ bridge_path }}/oracle"
|
||||
register: ERCTYPE
|
||||
|
||||
- name: Set FOREIGN_ERC_TYPE variable
|
||||
set_fact:
|
||||
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
|
||||
set_fact: composefileoverride="-f docker-compose-erc-native.yml"
|
||||
set_fact: composefileoverride="-f docker-compose-transfer.yml"
|
||||
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
|
||||
template:
|
||||
src: key.j2
|
||||
|
||||
@@ -20,4 +20,4 @@
|
||||
with_items:
|
||||
- docker-compose.yml
|
||||
- docker-compose-transfer.yml
|
||||
- docker-compose-erc-native.yml
|
||||
- docker-compose-amb.yml
|
||||
|
||||
@@ -11,9 +11,16 @@ ORACLE_HOME_RPC_POLLING_INTERVAL={{ ORACLE_HOME_RPC_POLLING_INTERVAL }}
|
||||
|
||||
## Foreign contract
|
||||
COMMON_FOREIGN_RPC_URL={{ COMMON_FOREIGN_RPC_URL }}
|
||||
{% if ORACLE_FOREIGN_ARCHIVE_RPC_URL | default('') != '' %}
|
||||
ORACLE_FOREIGN_ARCHIVE_RPC_URL={{ ORACLE_FOREIGN_ARCHIVE_RPC_URL }}
|
||||
{% endif %}
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS={{ COMMON_FOREIGN_BRIDGE_ADDRESS }}
|
||||
ORACLE_FOREIGN_RPC_POLLING_INTERVAL={{ ORACLE_FOREIGN_RPC_POLLING_INTERVAL }}
|
||||
|
||||
{% if ORACLE_TX_REDUNDANCY | default('') != '' %}
|
||||
ORACLE_TX_REDUNDANCY={{ ORACLE_TX_REDUNDANCY }}
|
||||
{% endif %}
|
||||
|
||||
## Gasprice
|
||||
{% if COMMON_HOME_GAS_PRICE_SUPPLIER_URL | default('') != '' %}
|
||||
COMMON_HOME_GAS_PRICE_SUPPLIER_URL={{ COMMON_HOME_GAS_PRICE_SUPPLIER_URL }}
|
||||
@@ -47,8 +54,28 @@ COMMON_FOREIGN_GAS_PRICE_FACTOR={{ COMMON_FOREIGN_GAS_PRICE_FACTOR }}
|
||||
ORACLE_ALLOW_HTTP_FOR_RPC={{ "yes" if ORACLE_ALLOW_HTTP_FOR_RPC else "no" }}
|
||||
ORACLE_QUEUE_URL={{ ORACLE_QUEUE_URL }}
|
||||
ORACLE_REDIS_URL={{ ORACLE_REDIS_URL }}
|
||||
{% if ORACLE_TX_REDUNDANCY | default('') != '' %}
|
||||
ORACLE_TX_REDUNDANCY={{ ORACLE_TX_REDUNDANCY }}
|
||||
{% if ORACLE_FOREIGN_TX_RESEND_INTERVAL | default('') != '' %}
|
||||
ORACLE_FOREIGN_TX_RESEND_INTERVAL={{ ORACLE_FOREIGN_TX_RESEND_INTERVAL }}
|
||||
{% endif %}
|
||||
{% if ORACLE_HOME_TX_RESEND_INTERVAL | default('') != '' %}
|
||||
ORACLE_HOME_TX_RESEND_INTERVAL={{ ORACLE_HOME_TX_RESEND_INTERVAL }}
|
||||
{% endif %}
|
||||
|
||||
## Emergency shutdown configuration
|
||||
{% if ORACLE_SHUTDOWN_SERVICE_URL | default('') != '' %}
|
||||
ORACLE_SHUTDOWN_SERVICE_URL={{ ORACLE_SHUTDOWN_SERVICE_URL }}
|
||||
{% endif %}
|
||||
{% if ORACLE_SHUTDOWN_SERVICE_POLLING_INTERVAL | default('') != '' %}
|
||||
ORACLE_SHUTDOWN_SERVICE_POLLING_INTERVAL={{ ORACLE_SHUTDOWN_SERVICE_POLLING_INTERVAL }}
|
||||
{% endif %}
|
||||
{% if ORACLE_SIDE_RPC_URL | default('') != '' %}
|
||||
ORACLE_SIDE_RPC_URL={{ ORACLE_SIDE_RPC_URL }}
|
||||
{% endif %}
|
||||
{% if ORACLE_SHUTDOWN_CONTRACT_ADDRESS | default('') != '' %}
|
||||
ORACLE_SHUTDOWN_CONTRACT_ADDRESS={{ ORACLE_SHUTDOWN_CONTRACT_ADDRESS }}
|
||||
{% endif %}
|
||||
{% if ORACLE_SHUTDOWN_CONTRACT_METHOD | default('') != '' %}
|
||||
ORACLE_SHUTDOWN_CONTRACT_METHOD={{ ORACLE_SHUTDOWN_CONTRACT_METHOD }}
|
||||
{% endif %}
|
||||
|
||||
{% if ORACLE_HOME_START_BLOCK | default('') != '' %}
|
||||
|
||||
11
deployment/roles/oracle/templates/32-redis-docker.conf.j2
Normal file
11
deployment/roles/oracle/templates/32-redis-docker.conf.j2
Normal file
@@ -0,0 +1,11 @@
|
||||
$FileCreateMode 0644
|
||||
template(name="DockerLogFileName_Redis" type="list") {
|
||||
constant(value="/var/log/docker/")
|
||||
property(name="syslogtag" securepath="replace" regex.type="ERE" regex.submatch="1" regex.expression="oracle_(.*redis.*)\\/[a-zA-Z0-9]+\\[")
|
||||
constant(value="/docker.log")
|
||||
}
|
||||
|
||||
if $programname contains 'oracle' and $programname contains 'redis' then \
|
||||
?DockerLogFileName_Redis
|
||||
|
||||
$FileCreateMode 0600
|
||||
11
deployment/roles/oracle/templates/33-rabbit-docker.conf.j2
Normal file
11
deployment/roles/oracle/templates/33-rabbit-docker.conf.j2
Normal file
@@ -0,0 +1,11 @@
|
||||
$FileCreateMode 0644
|
||||
template(name="DockerLogFileName_Rabbit" type="list") {
|
||||
constant(value="/var/log/docker/")
|
||||
property(name="syslogtag" securepath="replace" regex.type="ERE" regex.submatch="1" regex.expression="oracle_(.*rabbit.*)\\/[a-zA-Z0-9]+\\[")
|
||||
constant(value="/docker.log")
|
||||
}
|
||||
|
||||
if $programname contains 'oracle' and $programname contains 'rabbit' then \
|
||||
?DockerLogFileName_Rabbit
|
||||
|
||||
$FileCreateMode 0600
|
||||
@@ -26,9 +26,7 @@ Shut down and cleans up containers, networks, services, running scripts:
|
||||
| oracle-validator-3 | Launches Oracle containers for third validator |
|
||||
| blocks | Auto mines blocks |
|
||||
| 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-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 |
|
||||
|
||||
#### Ultimate e2e testing
|
||||
|
||||
@@ -4,7 +4,7 @@ Documentation regarding the Ultimate end-to-end tests.
|
||||
|
||||
## 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.
|
||||
|
||||
|
||||
@@ -16,14 +16,14 @@ Run the Parity nodes, deploy the bridge contracts, deploy Oracle using the deplo
|
||||
|
||||
```bash
|
||||
./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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
0xc9e38bfdB9c635F0796ad83CC8705dc379F41c04
|
||||
0x6f359aC418a5f7538F7755A33C9c7dDf38785524
|
||||
0xF9698Eb93702dfdd0e2d802088d4c21822a8A977
|
||||
|
||||
@@ -5,9 +5,11 @@ set -e # exit when any command fails
|
||||
docker-compose build e2e
|
||||
while [ "$1" != "" ]; do
|
||||
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
|
||||
docker-compose build monitor
|
||||
docker-compose build monitor-amb
|
||||
elif [ "$1" == "alm" ]; then
|
||||
docker-compose build alm
|
||||
fi
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
COMMON_HOME_BRIDGE_ADDRESS=0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS=0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0
|
||||
COMMON_HOME_BRIDGE_ADDRESS=0x8397be90BCF57b0B71219f555Fe121b22e5a994C
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS=0x1feB40aD9420b186F019A717c37f5546165d411E
|
||||
|
||||
COMMON_HOME_RPC_URL=http://localhost:8541
|
||||
COMMON_FOREIGN_RPC_URL=http://localhost:8542
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
COMMON_HOME_RPC_URL=http://parity1:8545
|
||||
COMMON_FOREIGN_RPC_URL=http://parity2:8545
|
||||
COMMON_HOME_BRIDGE_ADDRESS=0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS=0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0
|
||||
COMMON_HOME_BRIDGE_ADDRESS=0x8397be90BCF57b0B71219f555Fe121b22e5a994C
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS=0x1feB40aD9420b186F019A717c37f5546165d411E
|
||||
MONITOR_HOME_START_BLOCK=0
|
||||
MONITOR_FOREIGN_START_BLOCK=0
|
||||
MONITOR_VALIDATOR_HOME_TX_LIMIT=300000
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
COMMON_HOME_RPC_URL=http://parity1:8545
|
||||
COMMON_FOREIGN_RPC_URL=http://parity2:8545
|
||||
COMMON_HOME_BRIDGE_ADDRESS=0x488Af810997eD1730cB3a3918cD83b3216E6eAda
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS=0x488Af810997eD1730cB3a3918cD83b3216E6eAda
|
||||
COMMON_HOME_BRIDGE_ADDRESS=0x5118AC62AE912Dd5B51EEfF7338c4fcb0248Ba8c
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS=0x32198D570fffC7033641F8A9094FFDCaAEF42624
|
||||
MONITOR_HOME_START_BLOCK=0
|
||||
MONITOR_FOREIGN_START_BLOCK=0
|
||||
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,16 +4,14 @@ 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=0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS=0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0
|
||||
ORACLE_VALIDATOR_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
|
||||
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9
|
||||
COMMON_HOME_GAS_PRICE_SUPPLIER_URL=https://gasprice.poa.network/
|
||||
COMMON_HOME_BRIDGE_ADDRESS=0x8397be90BCF57b0B71219f555Fe121b22e5a994C
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS=0x1feB40aD9420b186F019A717c37f5546165d411E
|
||||
COMMON_HOME_GAS_PRICE_SUPPLIER_URL=
|
||||
COMMON_HOME_GAS_PRICE_SPEED_TYPE=standard
|
||||
COMMON_HOME_GAS_PRICE_FALLBACK=1000000000
|
||||
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_SUPPLIER_URL=
|
||||
COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE=standard
|
||||
COMMON_FOREIGN_GAS_PRICE_FALLBACK=10000000000
|
||||
ORACLE_FOREIGN_GAS_PRICE_UPDATE_INTERVAL=600000
|
||||
@@ -24,3 +22,4 @@ ORACLE_ALLOW_HTTP_FOR_RPC=yes
|
||||
ORACLE_HOME_START_BLOCK=1
|
||||
ORACLE_FOREIGN_START_BLOCK=1
|
||||
ORACLE_HOME_TO_FOREIGN_BLOCK_LIST=/mono/oracle/access-lists/block_list.txt
|
||||
ORACLE_FOREIGN_ARCHIVE_RPC_URL=http://parity2:8545
|
||||
|
||||
@@ -4,10 +4,8 @@ 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=0x488Af810997eD1730cB3a3918cD83b3216E6eAda
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS=0x488Af810997eD1730cB3a3918cD83b3216E6eAda
|
||||
ORACLE_VALIDATOR_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
|
||||
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9
|
||||
COMMON_HOME_BRIDGE_ADDRESS=0x5118AC62AE912Dd5B51EEfF7338c4fcb0248Ba8c
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS=0x32198D570fffC7033641F8A9094FFDCaAEF42624
|
||||
COMMON_HOME_GAS_PRICE_SUPPLIER_URL=https://gasprice.poa.network/
|
||||
COMMON_HOME_GAS_PRICE_SPEED_TYPE=standard
|
||||
COMMON_HOME_GAS_PRICE_FALLBACK=1
|
||||
|
||||
@@ -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,34 +35,26 @@
|
||||
"address": "0xB4579fd5AfEaB60B03Db3F408AAdD315035943f7",
|
||||
"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": {
|
||||
"home": "0x488Af810997eD1730cB3a3918cD83b3216E6eAda",
|
||||
"foreign": "0x488Af810997eD1730cB3a3918cD83b3216E6eAda",
|
||||
"foreignToken": "0x7cc4b1851c35959d34e635a470f6b5c43ba3c9c9",
|
||||
"chaiToken": "0x06af07097c9eeb7fd685c692751d5c66db49c215",
|
||||
"home": "0x5118AC62AE912Dd5B51EEfF7338c4fcb0248Ba8c",
|
||||
"foreign": "0x32198D570fffC7033641F8A9094FFDCaAEF42624",
|
||||
"foreignToken": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
|
||||
"monitor": "http://monitor-erc20-native:3012/bridge"
|
||||
},
|
||||
"amb": {
|
||||
"home": "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0",
|
||||
"foreign": "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0",
|
||||
"homeBox": "0x6C4EaAb8756d53Bf599FFe2347FAFF1123D6C8A1",
|
||||
"foreignBox": "0x6C4EaAb8756d53Bf599FFe2347FAFF1123D6C8A1",
|
||||
"blockedHomeBox": "0x6f359aC418a5f7538F7755A33C9c7dDf38785524",
|
||||
"home": "0x8397be90BCF57b0B71219f555Fe121b22e5a994C",
|
||||
"foreign": "0x1feB40aD9420b186F019A717c37f5546165d411E",
|
||||
"homeBox": "0xb008E9076fCbDB2C3AF84225Bc07Eb35B2bE5ECD",
|
||||
"foreignBox": "0x4a58D6d8D416a5fBCAcf3dC52eb8bE8948E25127",
|
||||
"blockedHomeBox": "0xF9698Eb93702dfdd0e2d802088d4c21822a8A977",
|
||||
"monitor": "http://monitor-amb:3013/bridge"
|
||||
},
|
||||
"amb2": {
|
||||
"home": "0x5A42E119990c3F3A80Fea20aAF4c3Ff4DB240Cc9",
|
||||
"foreign": "0x897527391ad3837604973d78D3514f44c36AB9FC",
|
||||
"homeBox": "0xb008E9076fCbDB2C3AF84225Bc07Eb35B2bE5ECD",
|
||||
"foreignBox": "0x4a58D6d8D416a5fBCAcf3dC52eb8bE8948E25127"
|
||||
},
|
||||
"homeRPC": {
|
||||
"URL": "http://parity1:8545",
|
||||
"ID": "77"
|
||||
|
||||
@@ -9,7 +9,7 @@ HOME_RPC_URL=http://parity1:8545
|
||||
HOME_BRIDGE_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
|
||||
HOME_VALIDATORS_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
|
||||
HOME_UPGRADEABLE_ADMIN=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
|
||||
HOME_MAX_AMOUNT_PER_TX=8000000
|
||||
HOME_MAX_AMOUNT_PER_TX=2000000
|
||||
HOME_REQUIRED_BLOCK_CONFIRMATIONS=1
|
||||
HOME_GAS_PRICE=1000000000
|
||||
|
||||
@@ -17,7 +17,7 @@ FOREIGN_RPC_URL=http://parity2:8545
|
||||
FOREIGN_BRIDGE_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
|
||||
FOREIGN_VALIDATORS_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
|
||||
FOREIGN_UPGRADEABLE_ADMIN=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
|
||||
FOREIGN_MAX_AMOUNT_PER_TX=8000000
|
||||
FOREIGN_MAX_AMOUNT_PER_TX=2000000
|
||||
FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS=1
|
||||
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,8 +31,8 @@ FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS=1
|
||||
FOREIGN_GAS_PRICE=10000000000
|
||||
FOREIGN_REWARDABLE=false
|
||||
|
||||
BLOCK_REWARD_ADDRESS=0xF9698Eb93702dfdd0e2d802088d4c21822a8A977
|
||||
ERC20_TOKEN_ADDRESS=0x7cc4b1851c35959d34e635a470f6b5c43ba3c9c9
|
||||
BLOCK_REWARD_ADDRESS=0xdbeE25CbE97e4A5CC6c499875774dc7067E9426B
|
||||
ERC20_TOKEN_ADDRESS=0x6B175474E89094C44Da98b954EedeAC495271d0F
|
||||
|
||||
REQUIRED_NUMBER_OF_VALIDATORS=1
|
||||
VALIDATORS="0xaaB52d66283F7A1D5978bcFcB55721ACB467384b 0xdCC784657C78054aa61FbcFFd2605F32374816A4 0xDcef88209a20D52165230104B245803C3269454d"
|
||||
|
||||
@@ -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"
|
||||
networks:
|
||||
- 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:
|
||||
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-oracle:${ORACLE_TAG:-local}
|
||||
env_file: ../e2e-commons/components-envs/oracle-erc20-native.env
|
||||
@@ -59,6 +40,9 @@ services:
|
||||
- ultimate
|
||||
oracle-amb:
|
||||
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
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
@@ -78,25 +62,6 @@ services:
|
||||
command: "true"
|
||||
networks:
|
||||
- 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:
|
||||
image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-monitor:${MONITOR_TAG:-local}
|
||||
env_file: ../e2e-commons/components-envs/monitor-erc20-native.env
|
||||
@@ -107,6 +72,9 @@ services:
|
||||
- ultimate
|
||||
monitor-amb:
|
||||
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
|
||||
entrypoint: yarn check-and-start
|
||||
ports:
|
||||
|
||||
@@ -1,10 +1,37 @@
|
||||
#!/usr/bin/env bash
|
||||
cd $(dirname $0)
|
||||
|
||||
if [ $CI ]; then exit $rc; fi
|
||||
if [ $CI ]; then
|
||||
rm -rf logs || true
|
||||
|
||||
mkdir ./logs
|
||||
|
||||
for project in "" validator{1,2,3}; do
|
||||
for container in $(docker-compose -p "$project" ps | tail -n +3 | awk '{print $1}') ; do
|
||||
if [[ -z "$project" ]]; then
|
||||
path="./logs/$container.log"
|
||||
else
|
||||
mkdir -p "./logs/$project"
|
||||
path="./logs/$project/$container.log"
|
||||
fi
|
||||
docker logs "$container" > "$path" 2>&1
|
||||
done
|
||||
done
|
||||
|
||||
touch ../oracle/.env
|
||||
for file in ../oracle/docker-compose-{amb,transfer}.yml; do
|
||||
for container in $(docker-compose -f "$file" ps | tail -n +3 | awk '{print $1}') ; do
|
||||
mkdir -p "./logs/oracle"
|
||||
docker logs "$container" > "./logs/oracle/$container.log" 2>&1
|
||||
done
|
||||
done
|
||||
|
||||
exit $rc;
|
||||
fi
|
||||
|
||||
ps | grep node | grep -v grep | grep -v yarn | awk '{print "kill " $1}' | /bin/bash
|
||||
docker-compose down
|
||||
docker-compose -p validator1 down
|
||||
docker-compose -p validator2 down
|
||||
docker-compose -p validator3 down
|
||||
docker network rm ultimate || true
|
||||
|
||||
@@ -5,9 +5,11 @@ set -e # exit when any command fails
|
||||
docker-compose pull e2e
|
||||
while [ "$1" != "" ]; do
|
||||
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
|
||||
docker-compose pull monitor
|
||||
docker-compose pull monitor-amb
|
||||
elif [ "$1" == "alm" ]; then
|
||||
docker-compose pull alm
|
||||
fi
|
||||
|
||||
@@ -9,26 +9,13 @@ ENVS_PATH="../contracts-envs"
|
||||
# mock bridge validators contract with the one with deterministic isValidatorDuty
|
||||
mv "$CONTRACTS_PATH/build/contracts/BridgeValidatorsDeterministic.json" "$CONTRACTS_PATH/build/contracts/BridgeValidators.json"
|
||||
|
||||
echo -e "\n\n############ Deploying native-to-erc ############\n"
|
||||
cp "$ENVS_PATH/native-to-erc.env" "$DEPLOY_PATH/.env"
|
||||
cd "$DEPLOY_PATH"
|
||||
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"
|
||||
cp "$ENVS_PATH/erc-to-native.env" "$DEPLOY_PATH/.env"
|
||||
cd "$DEPLOY_PATH"
|
||||
node src/utils/deployBlockReward.js
|
||||
cd - > /dev/null
|
||||
|
||||
echo -e "\n\n############ Deploying erc-to-native ############\n"
|
||||
cp "$ENVS_PATH/erc-to-native.env" "$DEPLOY_PATH/.env"
|
||||
cd "$DEPLOY_PATH"
|
||||
node deploy.js
|
||||
cd - > /dev/null
|
||||
@@ -48,3 +35,9 @@ echo -e "\n\n############ Deploying one more test contract for amb ############\
|
||||
cd "$DEPLOY_PATH"
|
||||
node src/utils/deployTestBox.js
|
||||
cd - > /dev/null
|
||||
|
||||
echo -e "\n\n############ Deploying one more amb without oracle for confirm relay tests ############\n"
|
||||
cp "$ENVS_PATH/amb.env" "$DEPLOY_PATH/.env"
|
||||
cd "$DEPLOY_PATH"
|
||||
node deploy.js
|
||||
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,46 @@ docker network create --driver bridge ultimate || true
|
||||
docker-compose up -d parity1 parity2 e2e
|
||||
|
||||
startValidator () {
|
||||
docker-compose $1 run -d --name $4 redis
|
||||
docker-compose $1 run -d --name $5 rabbit
|
||||
if [[ -z "$MODE" || "$MODE" == native-to-erc ]]; then
|
||||
docker-compose $1 run $2 $3 -d oracle yarn watcher:signature-request
|
||||
docker-compose $1 run $2 $3 -d oracle yarn watcher:collected-signatures
|
||||
docker-compose $1 run $2 $3 -d oracle yarn watcher:affirmation-request
|
||||
fi
|
||||
if [[ -z "$MODE" || "$MODE" == erc-to-erc ]]; then
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:signature-request
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:collected-signatures
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:affirmation-request
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:transfer
|
||||
fi
|
||||
db_env="-e ORACLE_QUEUE_URL=amqp://$3 -e ORACLE_REDIS_URL=redis://$2"
|
||||
|
||||
docker-compose $1 run -d --name $2 redis
|
||||
docker-compose $1 run -d --name $3 rabbit
|
||||
|
||||
if [[ -z "$MODE" || "$MODE" == erc-to-native ]]; then
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:signature-request
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:collected-signatures
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:affirmation-request
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:transfer
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn worker:convert-to-chai
|
||||
docker-compose $1 run $oraclePK $db_env -d oracle-erc20-native yarn watcher:signature-request
|
||||
docker-compose $1 run $oracleAddr $db_env -d oracle-erc20-native yarn watcher:collected-signatures
|
||||
docker-compose $1 run $oracleAddr $db_env -d oracle-erc20-native yarn watcher:affirmation-request
|
||||
docker-compose $1 run $oracleAddr $db_env -d oracle-erc20-native yarn watcher:transfer
|
||||
fi
|
||||
if [[ -z "$MODE" || "$MODE" == amb ]]; then
|
||||
docker-compose $1 run $2 $3 -d oracle-amb yarn watcher:signature-request
|
||||
docker-compose $1 run $2 $3 -d oracle-amb yarn watcher:collected-signatures
|
||||
docker-compose $1 run $2 $3 -d oracle-amb yarn watcher:affirmation-request
|
||||
docker-compose $1 run $oraclePK $db_env -d oracle-amb yarn watcher:signature-request
|
||||
docker-compose $1 run $oracleAddr $db_env -d oracle-amb yarn watcher:collected-signatures
|
||||
docker-compose $1 run $oracleAddr $db_env -d oracle-amb yarn watcher:affirmation-request
|
||||
docker-compose $1 run $oracleAddr $db_env -d oracle-amb yarn watcher:information-request
|
||||
fi
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn sender:home
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn sender:foreign
|
||||
docker-compose $1 run $2 $3 -d oracle yarn manager:shutdown
|
||||
}
|
||||
|
||||
startAMBValidator () {
|
||||
docker-compose $1 run -d --name $4 redis
|
||||
docker-compose $1 run -d --name $5 rabbit
|
||||
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
|
||||
docker-compose $1 run $oraclePK $db_env -d oracle-amb yarn sender:home
|
||||
docker-compose $1 run $oraclePK $db_env -d oracle-amb yarn sender:foreign
|
||||
docker-compose $1 run $oracleAddr $db_env -d oracle-amb yarn manager:shutdown
|
||||
}
|
||||
|
||||
while [ "$1" != "" ]; do
|
||||
if [ "$1" == "oracle" ]; then
|
||||
startValidator "" "" "" "redis" "rabbit"
|
||||
oracleAddr="-e ORACLE_VALIDATOR_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b"
|
||||
oraclePK="-e ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9"
|
||||
startValidator "-p validator1" redis rabbit
|
||||
fi
|
||||
|
||||
if [ "$1" == "oracle-validator-2" ]; then
|
||||
oracle2name="-p validator2"
|
||||
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 "$oracle2name" "$oracle2Values" "$oracle2comp" "redis2" "rabbit2"
|
||||
oracleAddr="-e ORACLE_VALIDATOR_ADDRESS=0xdCC784657C78054aa61FbcFFd2605F32374816A4"
|
||||
oraclePK="-e ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=5a5c3645d0f04e9eb4f27f94ed4c244a225587405b8838e7456f7781ce3a9513"
|
||||
startValidator "-p validator2" redis2 rabbit2
|
||||
fi
|
||||
|
||||
if [ "$1" == "oracle-validator-3" ]; then
|
||||
oracle3name="-p validator3"
|
||||
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 "$oracle3name" "$oracle3Values" "$oracle3comp" "redis3" "rabbit3"
|
||||
oracleAddr="-e ORACLE_VALIDATOR_ADDRESS=0xDcef88209a20D52165230104B245803C3269454d"
|
||||
oraclePK="-e ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=f877f62a1c19f852cff1d29f0fb1ecac18821c0080d4cc0520c60c098293dca1"
|
||||
startValidator "-p validator3" redis3 rabbit3
|
||||
fi
|
||||
|
||||
if [ "$1" == "alm" ]; then
|
||||
@@ -94,33 +76,50 @@ while [ "$1" != "" ]; do
|
||||
amb)
|
||||
docker-compose up -d monitor-amb
|
||||
;;
|
||||
native-to-erc)
|
||||
docker-compose up -d monitor
|
||||
;;
|
||||
erc-to-erc)
|
||||
docker-compose up -d monitor-erc20
|
||||
;;
|
||||
erc-to-native)
|
||||
docker-compose up -d monitor-erc20-native
|
||||
;;
|
||||
*)
|
||||
docker-compose up -d monitor monitor-erc20 monitor-erc20-native monitor-amb
|
||||
docker-compose up -d monitor-erc20-native monitor-amb
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ "$1" == "alm-e2e" ]; then
|
||||
startAMBValidator "" "" "" "redis" "rabbit"
|
||||
MODE=amb
|
||||
|
||||
oracle2name="-p validator2"
|
||||
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"
|
||||
startAMBValidator "$oracle2name" "$oracle2Values" "$oracle2comp" "redis2" "rabbit2"
|
||||
oracleAddr="-e ORACLE_VALIDATOR_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b"
|
||||
oraclePK="-e ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9"
|
||||
startValidator "-p validator1" redis rabbit
|
||||
|
||||
oracle3name="-p validator3"
|
||||
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"
|
||||
startAMBValidator "$oracle3name" "$oracle3Values" "$oracle3comp" "redis3" "rabbit3"
|
||||
oracleAddr="-e ORACLE_VALIDATOR_ADDRESS=0xdCC784657C78054aa61FbcFFd2605F32374816A4"
|
||||
oraclePK="-e ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=5a5c3645d0f04e9eb4f27f94ed4c244a225587405b8838e7456f7781ce3a9513"
|
||||
startValidator "-p validator2" redis2 rabbit2
|
||||
|
||||
oracleAddr="-e ORACLE_VALIDATOR_ADDRESS=0xDcef88209a20D52165230104B245803C3269454d"
|
||||
oraclePK="-e ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=f877f62a1c19f852cff1d29f0fb1ecac18821c0080d4cc0520c60c098293dca1"
|
||||
startValidator "-p validator3" redis3 rabbit3
|
||||
fi
|
||||
|
||||
if [ "$1" == "generate-amb-tx" ]; then
|
||||
docker-compose run e2e yarn workspace oracle-e2e run generate-amb-tx
|
||||
fi
|
||||
|
||||
if [ "$1" == "manual-amb-relay" ]; then
|
||||
oraclePK="-e ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9"
|
||||
env="-e COMMON_HOME_BRIDGE_ADDRESS=0x5A42E119990c3F3A80Fea20aAF4c3Ff4DB240Cc9 -e COMMON_FOREIGN_BRIDGE_ADDRESS=0x897527391ad3837604973d78D3514f44c36AB9FC"
|
||||
# these tx hash are hardcoded and need to be updated manually
|
||||
# once e2e environment setup process is changed
|
||||
echo '0xea625a823bc5018dc3a4efe349f623e5ebb8c987b55f44d50d6556f42af9a400' > txHashes.txt
|
||||
docker-compose -p validator1 run -v $(pwd)/txHashes.txt:/tmp/txHashes.txt $oraclePK $env oracle-amb yarn confirm:affirmation-request \
|
||||
/tmp/txHashes.txt \
|
||||
0x031c42e44485002c9215a5b1b75e9516131485ce29884a58765bf7a0038538f9
|
||||
docker-compose -p validator1 run $oraclePK $env oracle-amb yarn confirm:signature-request \
|
||||
0x1506a18af91afe732167ccbc178b55fc2547da4a814d13c015b6f496cf171754 | tee .tmp.log
|
||||
tx_hash=$(cat .tmp.log | grep generatedTransactionHash | jq -r .generatedTransactionHash)
|
||||
rm .tmp.log
|
||||
rm txHashes.txt
|
||||
docker-compose -p validator1 run $oraclePK $env oracle-amb yarn confirm:collected-signatures $tx_hash
|
||||
fi
|
||||
|
||||
shift # Shift all the parameters down by one
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "mocha --timeout 120000",
|
||||
"start": "mocha --timeout 120000 --exit",
|
||||
"lint": "eslint . --ignore-path ../.eslintignore"
|
||||
},
|
||||
"author": "",
|
||||
@@ -14,7 +14,7 @@
|
||||
"axios": "0.19.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.18"
|
||||
"node": ">= 12.22"
|
||||
},
|
||||
"devDependencies": {}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
while true; do
|
||||
docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor yarn check-all
|
||||
pid1=$!
|
||||
docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20 yarn check-all
|
||||
pid2=$!
|
||||
docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20-native yarn check-all
|
||||
pid3=$!
|
||||
pid1=$!
|
||||
docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-amb yarn check-all
|
||||
pid4=$!
|
||||
pid2=$!
|
||||
|
||||
wait $pid1
|
||||
wait $pid2
|
||||
wait $pid3
|
||||
wait $pid4
|
||||
done
|
||||
|
||||
@@ -5,12 +5,6 @@ case "$mode" in
|
||||
amb)
|
||||
script=./test/amb.js
|
||||
;;
|
||||
native-to-erc)
|
||||
script=./test/nativeToErc.js
|
||||
;;
|
||||
erc-to-erc)
|
||||
script=./test/ercToErc.js
|
||||
;;
|
||||
erc-to-native)
|
||||
script=./test/ercToNative.js
|
||||
;;
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
const assert = require('assert')
|
||||
const axios = require('axios')
|
||||
const { nativeToErcBridge, ercToErcBridge, ercToNativeBridge, validator } = require('../../e2e-commons/constants.json')
|
||||
const { ercToNativeBridge, validator } = require('../../e2e-commons/constants.json')
|
||||
|
||||
const types = [
|
||||
{ description: 'NATIVE TO ERC', baseUrl: nativeToErcBridge.monitor },
|
||||
{ description: 'ERC TO ERC', baseUrl: ercToErcBridge.monitor },
|
||||
{ description: 'ERC TO NATIVE', baseUrl: ercToNativeBridge.monitor }
|
||||
]
|
||||
const types = [{ description: 'ERC TO NATIVE', baseUrl: ercToNativeBridge.monitor }]
|
||||
|
||||
types.forEach(type => {
|
||||
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 axios = require('axios')
|
||||
const { ercToNativeBridge, user, foreignRPC, validator } = require('../../e2e-commons/constants.json')
|
||||
const {
|
||||
waitUntil,
|
||||
sendTokens,
|
||||
addValidator,
|
||||
initializeChaiToken,
|
||||
convertDaiToChai,
|
||||
setMinDaiTokenBalance
|
||||
} = require('../utils')
|
||||
const { waitUntil, sendTokens, addValidator } = require('../utils')
|
||||
|
||||
const baseUrl = ercToNativeBridge.monitor
|
||||
|
||||
@@ -52,58 +45,4 @@ describe('ERC TO NATIVE with changing state of contracts', () => {
|
||||
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 {
|
||||
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 { ERC20_ABI, BRIDGE_VALIDATORS_ABI, FOREIGN_ERC_TO_NATIVE_ABI, BOX_ABI } = require('../commons')
|
||||
|
||||
const waitUntil = async (predicate, step = 100, timeout = 60000) => {
|
||||
const stopTime = Date.now() + timeout
|
||||
@@ -36,7 +29,7 @@ const sendEther = async (rpcUrl, account, to) => {
|
||||
const sendTokens = async (rpcUrl, account, tokenAddress, recipientAddress) => {
|
||||
const web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl))
|
||||
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({
|
||||
from: account.address,
|
||||
@@ -62,7 +55,7 @@ const sendAMBMessage = async (rpcUrl, account, boxAddress, bridgeAddress, boxOth
|
||||
const addValidator = async (rpcUrl, account, bridgeAddress) => {
|
||||
const web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl))
|
||||
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 foreignBridgeValidators = new web3.eth.Contract(BRIDGE_VALIDATORS_ABI, foreignValidatorsAddress)
|
||||
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 = {
|
||||
waitUntil,
|
||||
sendEther,
|
||||
sendTokens,
|
||||
addValidator,
|
||||
sendAMBMessage,
|
||||
initializeChaiToken,
|
||||
setMinDaiTokenBalance,
|
||||
convertDaiToChai
|
||||
sendAMBMessage
|
||||
}
|
||||
|
||||
@@ -6,12 +6,6 @@ check_files_exist() {
|
||||
rc=0
|
||||
for f in "${FILES[@]}"; do
|
||||
command="test -f responses/bridge/$f"
|
||||
if [[ -z "$MODE" || "$MODE" == native-to-erc ]]; then
|
||||
(docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor /bin/bash -c "$command") || rc=1
|
||||
fi
|
||||
if [[ -z "$MODE" || "$MODE" == erc-to-erc ]]; then
|
||||
(docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20 /bin/bash -c "$command") || rc=1
|
||||
fi
|
||||
if [[ -z "$MODE" || "$MODE" == erc-to-native ]]; then
|
||||
(docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20-native /bin/bash -c "$command") || rc=1
|
||||
fi
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:10 as contracts
|
||||
FROM node:12 as contracts
|
||||
|
||||
WORKDIR /mono
|
||||
|
||||
@@ -11,7 +11,7 @@ COPY ./contracts/truffle-config.js ./
|
||||
COPY ./contracts/contracts ./contracts
|
||||
RUN npm run compile
|
||||
|
||||
FROM node:10
|
||||
FROM node:12
|
||||
|
||||
WORKDIR /mono
|
||||
COPY package.json .
|
||||
|
||||
@@ -12,12 +12,12 @@ const { web3Home } = require('./utils/web3')
|
||||
|
||||
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() {
|
||||
try {
|
||||
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)
|
||||
logger.debug('Bridge mode:', bridgeMode)
|
||||
logger.debug('calling getEventsInfo()')
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
require('dotenv').config()
|
||||
const logger = require('./logger')('checkWorker3')
|
||||
const stuckTransfers = require('./stuckTransfers')
|
||||
const detectMediators = require('./detectMediators')
|
||||
const detectFailures = require('./detectFailures')
|
||||
const { writeFile, createDir } = require('./utils/file')
|
||||
@@ -8,22 +7,13 @@ const { web3Home } = require('./utils/web3')
|
||||
const { saveCache } = require('./utils/web3Cache')
|
||||
|
||||
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() {
|
||||
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)
|
||||
if (bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC_V1) {
|
||||
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) {
|
||||
if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) {
|
||||
createDir(`/responses/${MONITOR_BRIDGE_NAME}`)
|
||||
|
||||
logger.debug('calling detectMediators()')
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
require('dotenv').config()
|
||||
const logger = require('./logger')('detectMediators.js')
|
||||
const { isHomeContract, isForeignContract } = require('./utils/web3Cache')
|
||||
const eventsInfo = require('./utils/events')
|
||||
const { getHomeTxSender, getForeignTxSender } = require('./utils/web3Cache')
|
||||
const { addExecutionStatus } = require('./utils/message')
|
||||
const { normalizeAMBMessageEvent } = require('../commons')
|
||||
const { getHomeTxSender, getForeignTxSender, isHomeContract, isForeignContract } = require('./utils/web3Cache')
|
||||
const { addExecutionStatus, addRetrievalStatus } = require('./utils/message')
|
||||
const { normalizeAMBMessageEvent, normalizeAMBInfoRequest } = require('../commons')
|
||||
|
||||
function countInteractions(requests) {
|
||||
const stats = {}
|
||||
@@ -30,6 +29,41 @@ function countInteractions(requests) {
|
||||
return stats
|
||||
}
|
||||
|
||||
function countInfoRequests(requests) {
|
||||
const stats = {}
|
||||
requests.forEach(msg => {
|
||||
if (!stats[msg.sender]) {
|
||||
stats[msg.sender] = {}
|
||||
}
|
||||
if (!stats[msg.sender][msg.requestSelector]) {
|
||||
stats[msg.sender][msg.requestSelector] = {
|
||||
callSucceeded: {
|
||||
callbackSucceeded: 0,
|
||||
callbackFailed: 0
|
||||
},
|
||||
callFailed: {
|
||||
callbackSucceeded: 0,
|
||||
callbackFailed: 0
|
||||
},
|
||||
pending: 0
|
||||
}
|
||||
}
|
||||
const stat = stats[msg.sender][msg.requestSelector]
|
||||
if (msg.callStatus === true && msg.callbackStatus === true) {
|
||||
stat.callSucceeded.callbackSucceeded += 1
|
||||
} else if (msg.callStatus === true && msg.callbackStatus === false) {
|
||||
stat.callSucceeded.callbackFailed += 1
|
||||
} else if (msg.callStatus === false && msg.callbackStatus === true) {
|
||||
stat.callFailed.callbackSucceeded += 1
|
||||
} else if (msg.callStatus === false && msg.callbackStatus === false) {
|
||||
stat.callFailed.callbackFailed += 1
|
||||
} else {
|
||||
stat.pending += 1
|
||||
}
|
||||
})
|
||||
return stats
|
||||
}
|
||||
|
||||
const normalize = event => ({
|
||||
...normalizeAMBMessageEvent(event),
|
||||
txHash: event.transactionHash,
|
||||
@@ -88,10 +122,13 @@ async function main(mode) {
|
||||
homeToForeignRequests,
|
||||
foreignToHomeRequests,
|
||||
homeToForeignConfirmations,
|
||||
foreignToHomeConfirmations
|
||||
foreignToHomeConfirmations,
|
||||
informationRequests,
|
||||
informationResponses
|
||||
} = await eventsInfo(mode)
|
||||
const homeToForeign = homeToForeignRequests.map(normalize).map(addExecutionStatus(homeToForeignConfirmations))
|
||||
const foreignToHome = foreignToHomeRequests.map(normalize).map(addExecutionStatus(foreignToHomeConfirmations))
|
||||
const infoRequests = informationRequests.map(normalizeAMBInfoRequest).map(addRetrievalStatus(informationResponses))
|
||||
|
||||
for (const event of homeToForeign) {
|
||||
// AMB contract emits a single UserRequestForSignature event for every home->foreign request.
|
||||
@@ -146,6 +183,7 @@ async function main(mode) {
|
||||
floatingMediators,
|
||||
remotelyControlledMediators,
|
||||
unknown,
|
||||
informationReceivers: countInfoRequests(infoRequests),
|
||||
lastChecked: Math.floor(Date.now() / 1000)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,23 +12,13 @@ const {
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS
|
||||
} = process.env
|
||||
|
||||
const {
|
||||
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')
|
||||
const { ERC20_ABI, BLOCK_REWARD_ABI, HOME_ERC_TO_NATIVE_ABI, FOREIGN_ERC_TO_NATIVE_ABI } = require('../commons')
|
||||
|
||||
async function main(bridgeMode, eventsInfo) {
|
||||
const {
|
||||
homeBlockNumber,
|
||||
foreignBlockNumber,
|
||||
homeToForeignConfirmations,
|
||||
foreignToHomeConfirmations,
|
||||
homeDelayedBlockNumber,
|
||||
foreignDelayedBlockNumber
|
||||
} = eventsInfo
|
||||
@@ -44,14 +34,6 @@ async function main(bridgeMode, eventsInfo) {
|
||||
0,
|
||||
...homeToForeignConfirmations.filter(e => e.blockNumber > foreignDelayedBlockNumber).map(e => e.value)
|
||||
)
|
||||
// Home balance should represent all UserRequestForSignature events up to block `M - requiredBlockConfirmation()`
|
||||
// and all AffirmationCompleted events up to block `M`.
|
||||
// This constant tells the difference between bridge balance at block `M - requiredBlockConfirmation() + 1`
|
||||
// and the actual value monitor is interested in.
|
||||
const lateHomeConfirmationsTotalValue = BN.sum(
|
||||
0,
|
||||
...foreignToHomeConfirmations.filter(e => e.blockNumber > homeDelayedBlockNumber).map(e => e.value)
|
||||
)
|
||||
|
||||
const blockRanges = {
|
||||
startBlockHome: MONITOR_HOME_START_BLOCK,
|
||||
@@ -60,80 +42,10 @@ async function main(bridgeMode, eventsInfo) {
|
||||
endBlockForeign: foreignBlockNumber
|
||||
}
|
||||
|
||||
if (bridgeMode === BRIDGE_MODES.ERC_TO_ERC) {
|
||||
const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_ERC_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
const erc20Address = await foreignBridge.methods.erc20token().call()
|
||||
const erc20Contract = new web3Foreign.eth.Contract(ERC20_ABI, erc20Address)
|
||||
logger.debug('calling erc20Contract.methods.balanceOf')
|
||||
const foreignErc20Balance = await erc20Contract.methods
|
||||
.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
.call({}, foreignDelayedBlockNumber)
|
||||
const 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) {
|
||||
if (bridgeMode === BRIDGE_MODES.ERC_TO_NATIVE) {
|
||||
const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
const erc20Address = await foreignBridge.methods.erc20token().call()
|
||||
const erc20Contract = new web3Foreign.eth.Contract(ERC20_ABI, erc20Address)
|
||||
let investedAmountInDai = 0
|
||||
let bridgeDsrBalance = 0
|
||||
let displayChaiToken = false
|
||||
|
||||
try {
|
||||
logger.debug('calling foreignBridge.methods.isChaiTokenEnabled')
|
||||
if (await foreignBridge.methods.isChaiTokenEnabled().call()) {
|
||||
displayChaiToken = true
|
||||
logger.debug('calling foreignBridge.methods.investedAmountInDai')
|
||||
investedAmountInDai = await foreignBridge.methods.investedAmountInDai().call()
|
||||
logger.debug('calling foreignBridge.methods.dsrBalance')
|
||||
bridgeDsrBalance = await foreignBridge.methods.dsrBalance().call()
|
||||
} else {
|
||||
logger.debug('Chai token is currently disabled')
|
||||
}
|
||||
} catch (e) {
|
||||
logger.debug('Methods for chai token are not present')
|
||||
}
|
||||
|
||||
logger.debug('calling erc20Contract.methods.balanceOf')
|
||||
const foreignErc20Balance = await erc20Contract.methods
|
||||
@@ -155,29 +67,16 @@ async function main(bridgeMode, eventsInfo) {
|
||||
const burntCoinsBN = new BN(burntCoins)
|
||||
const totalSupplyBN = mintedCoinsBN.minus(burntCoinsBN)
|
||||
const foreignErc20BalanceBN = new BN(foreignErc20Balance).plus(lateForeignConfirmationsTotalValue)
|
||||
const investedAmountInDaiBN = new BN(investedAmountInDai)
|
||||
const bridgeDsrBalanceBN = new BN(bridgeDsrBalance)
|
||||
|
||||
const diff = foreignErc20BalanceBN
|
||||
.plus(investedAmountInDaiBN)
|
||||
.minus(totalSupplyBN)
|
||||
.toFixed()
|
||||
|
||||
const foreign = {
|
||||
erc20Balance: Web3Utils.fromWei(foreignErc20Balance)
|
||||
}
|
||||
|
||||
if (displayChaiToken) {
|
||||
foreign.investedErc20Balance = Web3Utils.fromWei(investedAmountInDai)
|
||||
foreign.accumulatedInterest = Web3Utils.fromWei(bridgeDsrBalanceBN.minus(investedAmountInDaiBN).toString(10))
|
||||
}
|
||||
|
||||
const diff = foreignErc20BalanceBN.minus(totalSupplyBN).toFixed()
|
||||
logger.debug('Done')
|
||||
return {
|
||||
home: {
|
||||
totalSupply: Web3Utils.fromWei(totalSupplyBN.toFixed())
|
||||
},
|
||||
foreign,
|
||||
foreign: {
|
||||
erc20Balance: Web3Utils.fromWei(foreignErc20Balance)
|
||||
},
|
||||
balanceDiff: Number(Web3Utils.fromWei(diff)),
|
||||
...blockRanges,
|
||||
lastChecked: Math.floor(Date.now() / 1000)
|
||||
|
||||
@@ -21,7 +21,9 @@ async function main(bridgeMode, eventsInfo) {
|
||||
homeToForeignConfirmations,
|
||||
homeToForeignRequests,
|
||||
foreignToHomeConfirmations,
|
||||
foreignToHomeRequests
|
||||
foreignToHomeRequests,
|
||||
informationRequests,
|
||||
informationResponses
|
||||
} = eventsInfo
|
||||
|
||||
if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) {
|
||||
@@ -34,7 +36,9 @@ async function main(bridgeMode, eventsInfo) {
|
||||
fromForeignToHomeDiff: foreignToHomeConfirmations.length - foreignToHomeRequests.length,
|
||||
home: {
|
||||
toForeign: homeToForeignRequests.length,
|
||||
fromForeign: foreignToHomeConfirmations.length
|
||||
fromForeign: foreignToHomeConfirmations.length,
|
||||
informationRequests: informationRequests.length,
|
||||
informationResponses: informationResponses.length
|
||||
},
|
||||
foreign: {
|
||||
fromHome: homeToForeignConfirmations.length,
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"web3": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.18"
|
||||
"node": ">= 12.22"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^4.2.0"
|
||||
|
||||
@@ -39,7 +39,7 @@ async function getPrometheusMetrics(bridgeName) {
|
||||
const { home, foreign, ...commonBalances } = balancesFile
|
||||
|
||||
const balanceMetrics = {
|
||||
// ERC_TO_ERC or ERC_TO_NATIVE mode
|
||||
// ERC_TO_NATIVE mode
|
||||
balances_home_value: home.totalSupply,
|
||||
balances_home_txs_deposit: home.deposits,
|
||||
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,19 +2,15 @@ require('dotenv').config()
|
||||
const logger = require('../logger')('eventsUtils')
|
||||
const {
|
||||
BRIDGE_MODES,
|
||||
ERC_TYPES,
|
||||
getBridgeABIs,
|
||||
getBridgeMode,
|
||||
HOME_ERC_TO_ERC_ABI,
|
||||
HOME_ERC_TO_NATIVE_ABI,
|
||||
ERC20_ABI,
|
||||
ERC677_BRIDGE_TOKEN_ABI,
|
||||
getTokenType,
|
||||
ZERO_ADDRESS,
|
||||
OLD_AMB_USER_REQUEST_FOR_SIGNATURE_ABI,
|
||||
OLD_AMB_USER_REQUEST_FOR_AFFIRMATION_ABI
|
||||
} = require('../../commons')
|
||||
const { normalizeEventInformation } = require('./message')
|
||||
const { filterTransferBeforeES } = require('./tokenUtils')
|
||||
const { writeFile, readCacheFile } = require('./file')
|
||||
const { web3Home, web3Foreign, getHomeBlockNumber, getForeignBlockNumber } = require('./web3')
|
||||
const { getPastEvents } = require('./web3Cache')
|
||||
@@ -34,24 +30,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 { HOME_ABI, FOREIGN_ABI } = getBridgeABIs(bridgeMode)
|
||||
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 v1Bridge = bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC_V1
|
||||
let isExternalErc20
|
||||
let isExternalErc20 = false
|
||||
let erc20Contract
|
||||
let erc20Address
|
||||
let normalizeEvent = normalizeEventInformation
|
||||
if (bridgeMode !== BRIDGE_MODES.ARBITRARY_MESSAGE) {
|
||||
const erc20MethodName = bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC || v1Bridge ? 'erc677token' : 'erc20token'
|
||||
erc20Address = await foreignBridge.methods[erc20MethodName]().call()
|
||||
const tokenType = await getTokenType(
|
||||
new web3Foreign.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, erc20Address),
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS
|
||||
)
|
||||
isExternalErc20 = tokenType === ERC_TYPES.ERC20
|
||||
erc20Address = await foreignBridge.methods.erc20token().call()
|
||||
isExternalErc20 = true
|
||||
erc20Contract = new web3Foreign.eth.Contract(ERC20_ABI, erc20Address)
|
||||
} else {
|
||||
normalizeEvent = e => e
|
||||
@@ -104,7 +94,7 @@ async function main(mode) {
|
||||
|
||||
logger.debug("calling homeBridge.getPastEvents('UserRequestForSignature')")
|
||||
const homeToForeignRequestsNew = (await getPastEvents(homeBridge, {
|
||||
event: v1Bridge ? 'Deposit' : 'UserRequestForSignature',
|
||||
event: 'UserRequestForSignature',
|
||||
fromBlock: homeMigrationBlock,
|
||||
toBlock: homeDelayedBlockNumber,
|
||||
chain: 'home'
|
||||
@@ -113,7 +103,7 @@ async function main(mode) {
|
||||
|
||||
logger.debug("calling foreignBridge.getPastEvents('RelayedMessage')")
|
||||
const homeToForeignConfirmations = (await getPastEvents(foreignBridge, {
|
||||
event: v1Bridge ? 'Deposit' : 'RelayedMessage',
|
||||
event: 'RelayedMessage',
|
||||
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
||||
toBlock: foreignBlockNumber,
|
||||
chain: 'foreign',
|
||||
@@ -122,7 +112,7 @@ async function main(mode) {
|
||||
|
||||
logger.debug("calling homeBridge.getPastEvents('AffirmationCompleted')")
|
||||
const foreignToHomeConfirmations = (await getPastEvents(homeBridge, {
|
||||
event: v1Bridge ? 'Withdraw' : 'AffirmationCompleted',
|
||||
event: 'AffirmationCompleted',
|
||||
fromBlock: MONITOR_HOME_START_BLOCK,
|
||||
toBlock: homeBlockNumber,
|
||||
chain: 'home',
|
||||
@@ -131,13 +121,34 @@ async function main(mode) {
|
||||
|
||||
logger.debug("calling foreignBridge.getPastEvents('UserRequestForAffirmation')")
|
||||
const foreignToHomeRequestsNew = (await getPastEvents(foreignBridge, {
|
||||
event: v1Bridge ? 'Withdraw' : 'UserRequestForAffirmation',
|
||||
event: 'UserRequestForAffirmation',
|
||||
fromBlock: foreignMigrationBlock,
|
||||
toBlock: foreignDelayedBlockNumber,
|
||||
chain: 'foreign'
|
||||
})).map(normalizeEvent)
|
||||
foreignToHomeRequests = [...foreignToHomeRequests, ...foreignToHomeRequestsNew]
|
||||
|
||||
let informationRequests
|
||||
let informationResponses
|
||||
if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) {
|
||||
logger.debug("calling homeBridge.getPastEvents('UserRequestForInformation')")
|
||||
informationRequests = (await getPastEvents(homeBridge, {
|
||||
event: 'UserRequestForInformation',
|
||||
fromBlock: MONITOR_HOME_START_BLOCK,
|
||||
toBlock: homeDelayedBlockNumber,
|
||||
chain: 'home'
|
||||
})).map(normalizeEvent)
|
||||
|
||||
logger.debug("calling foreignBridge.getPastEvents('InformationRetrieved')")
|
||||
informationResponses = (await getPastEvents(homeBridge, {
|
||||
event: 'InformationRetrieved',
|
||||
fromBlock: MONITOR_HOME_START_BLOCK,
|
||||
toBlock: homeBlockNumber,
|
||||
safeToBlock: homeDelayedBlockNumber,
|
||||
chain: 'home'
|
||||
})).map(normalizeEvent)
|
||||
}
|
||||
|
||||
if (isExternalErc20) {
|
||||
logger.debug("calling erc20Contract.getPastEvents('Transfer')")
|
||||
let transferEvents = (await getPastEvents(erc20Contract, {
|
||||
@@ -148,80 +159,32 @@ async function main(mode) {
|
||||
filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS }
|
||||
},
|
||||
chain: 'foreign'
|
||||
}))
|
||||
.map(normalizeEvent)
|
||||
.filter(e => e.recipient !== ZERO_ADDRESS) // filter mint operation during SCD-to-MCD swaps
|
||||
.filter(e => e.recipient.toLowerCase() !== '0x5d3a536e4d6dbd6114cc1ead35777bab948e3643') // filter cDai withdraws during compounding
|
||||
|
||||
// Get transfer events for each previously used Sai token
|
||||
const saiTokenAddress = '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359'
|
||||
const halfDuplexTokenContract = new web3Foreign.eth.Contract(ERC20_ABI, saiTokenAddress)
|
||||
logger.debug('Half duplex token:', saiTokenAddress)
|
||||
logger.debug("calling halfDuplexTokenContract.getPastEvents('Transfer')")
|
||||
// https://etherscan.io/tx/0xd0c3c92c94e05bc71256055ce8c4c993e047f04e04f3283a04e4cb077b71f6c6
|
||||
const blockNumberHalfDuplexDisabled = 9884448
|
||||
const halfDuplexTransferEvents = (await getPastEvents(halfDuplexTokenContract, {
|
||||
event: 'Transfer',
|
||||
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
||||
toBlock: Math.min(blockNumberHalfDuplexDisabled, foreignDelayedBlockNumber),
|
||||
options: {
|
||||
filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS }
|
||||
},
|
||||
chain: 'foreign'
|
||||
})).map(normalizeEvent)
|
||||
|
||||
let directTransfers = transferEvents
|
||||
const tokensSwappedAbiExists = FOREIGN_ABI.filter(e => e.type === 'event' && e.name === 'TokensSwapped')[0]
|
||||
if (tokensSwappedAbiExists) {
|
||||
logger.debug('collecting half duplex tokens participated in the bridge balance')
|
||||
logger.debug("calling foreignBridge.getPastEvents('TokensSwapped')")
|
||||
const tokensSwappedEvents = await getPastEvents(foreignBridge, {
|
||||
event: 'TokensSwapped',
|
||||
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
||||
toBlock: foreignBlockNumber,
|
||||
chain: 'foreign',
|
||||
safeToBlock: foreignDelayedBlockNumber
|
||||
})
|
||||
|
||||
// Get token swap events emitted by foreign bridge
|
||||
const bridgeTokensSwappedEvents = tokensSwappedEvents.filter(e => e.address === COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
|
||||
// Get transfer events for each previous erc20
|
||||
const uniqueTokenAddressesSet = new Set(bridgeTokensSwappedEvents.map(e => e.returnValues.from))
|
||||
|
||||
// Exclude chai token from previous erc20
|
||||
try {
|
||||
logger.debug('calling foreignBridge.chaiToken() to remove it from half duplex tokens list')
|
||||
const chaiToken = await foreignBridge.methods.chaiToken().call()
|
||||
uniqueTokenAddressesSet.delete(chaiToken)
|
||||
} catch (e) {
|
||||
logger.debug('call to foreignBridge.chaiToken() failed')
|
||||
}
|
||||
// Exclude dai token from previous erc20
|
||||
try {
|
||||
logger.debug('calling foreignBridge.erc20token() to remove it from half duplex tokens list')
|
||||
const daiToken = await foreignBridge.methods.erc20token().call()
|
||||
uniqueTokenAddressesSet.delete(daiToken)
|
||||
} catch (e) {
|
||||
logger.debug('call to foreignBridge.erc20token() failed')
|
||||
}
|
||||
|
||||
const uniqueTokenAddresses = [...uniqueTokenAddressesSet]
|
||||
await Promise.all(
|
||||
uniqueTokenAddresses.map(async tokenAddress => {
|
||||
const halfDuplexTokenContract = new web3Foreign.eth.Contract(ERC20_ABI, tokenAddress)
|
||||
|
||||
logger.debug('Half duplex token:', tokenAddress)
|
||||
logger.debug("calling halfDuplexTokenContract.getPastEvents('Transfer')")
|
||||
const halfDuplexTransferEvents = (await getPastEvents(halfDuplexTokenContract, {
|
||||
event: 'Transfer',
|
||||
fromBlock: MONITOR_FOREIGN_START_BLOCK,
|
||||
toBlock: foreignDelayedBlockNumber,
|
||||
options: {
|
||||
filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS }
|
||||
},
|
||||
chain: 'foreign'
|
||||
})).map(normalizeEvent)
|
||||
|
||||
// Remove events after the ES
|
||||
logger.debug('filtering half duplex transfers happened before ES')
|
||||
const validHalfDuplexTransfers = await filterTransferBeforeES(halfDuplexTransferEvents)
|
||||
|
||||
transferEvents = [...validHalfDuplexTransfers, ...transferEvents]
|
||||
})
|
||||
)
|
||||
|
||||
// filter transfer that is part of a token swap
|
||||
directTransfers = transferEvents.filter(
|
||||
e =>
|
||||
bridgeTokensSwappedEvents.findIndex(
|
||||
t => t.transactionHash === e.referenceTx && e.recipient === ZERO_ADDRESS
|
||||
) === -1
|
||||
)
|
||||
}
|
||||
transferEvents = [...halfDuplexTransferEvents, ...transferEvents]
|
||||
|
||||
// Get transfer events that didn't have a UserRequestForAffirmation event in the same transaction
|
||||
directTransfers = directTransfers.filter(
|
||||
const directTransfers = transferEvents.filter(
|
||||
e => foreignToHomeRequests.findIndex(t => t.referenceTx === e.referenceTx) === -1
|
||||
)
|
||||
|
||||
@@ -234,6 +197,8 @@ async function main(mode) {
|
||||
homeToForeignConfirmations,
|
||||
foreignToHomeConfirmations,
|
||||
foreignToHomeRequests,
|
||||
informationRequests,
|
||||
informationResponses,
|
||||
isExternalErc20,
|
||||
bridgeMode,
|
||||
homeBlockNumber,
|
||||
|
||||
@@ -8,8 +8,8 @@ function readFile(filePath, parseJson = true) {
|
||||
const json = JSON.parse(content)
|
||||
const timeDiff = Math.floor(Date.now() / 1000) - json.lastChecked
|
||||
return Object.assign({}, json, { timeDiff })
|
||||
} catch (e) {
|
||||
console.error('readFlle', e)
|
||||
} catch (_) {
|
||||
console.error(`File ${filePath} does not exist`)
|
||||
return {
|
||||
error: 'the bridge statistics are not available'
|
||||
}
|
||||
|
||||
@@ -28,6 +28,21 @@ function addExecutionStatus(processedList) {
|
||||
}
|
||||
}
|
||||
|
||||
function addRetrievalStatus(retrievedInfoList) {
|
||||
const statuses = {}
|
||||
retrievedInfoList.forEach(e => {
|
||||
statuses[e.returnValues.messageId] = {
|
||||
callStatus: e.returnValues.status,
|
||||
callbackStatus: e.returnValues.callbackStatus
|
||||
}
|
||||
})
|
||||
return deliveredMsg => {
|
||||
deliveredMsg.callStatus = statuses[deliveredMsg.messageId].callStatus
|
||||
deliveredMsg.callbackStatus = statuses[deliveredMsg.messageId].callbackStatus
|
||||
return deliveredMsg
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the different event objects to facilitate data processing
|
||||
* @param {Object} event
|
||||
@@ -89,6 +104,7 @@ module.exports = {
|
||||
deliveredMsgNotProcessed,
|
||||
processedMsgNotDelivered,
|
||||
addExecutionStatus,
|
||||
addRetrievalStatus,
|
||||
normalizeEventInformation,
|
||||
eventWithoutReference,
|
||||
unclaimedHomeToForeignRequests,
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
// https://etherscan.io/tx/0xd0c3c92c94e05bc71256055ce8c4c993e047f04e04f3283a04e4cb077b71f6c6
|
||||
const blockNumberHalfDuplexDisabled = 9884448
|
||||
|
||||
/**
|
||||
* Returns true if the event was before the bridge stopped supporting half duplex transfers.
|
||||
*/
|
||||
async function transferBeforeES(event) {
|
||||
return event.blockNumber < blockNumberHalfDuplexDisabled
|
||||
}
|
||||
|
||||
async function filterTransferBeforeES(array) {
|
||||
const newArray = []
|
||||
// Iterate events from newer to older
|
||||
for (let i = array.length - 1; i >= 0; i--) {
|
||||
const beforeES = await transferBeforeES(array[i])
|
||||
if (beforeES) {
|
||||
// add element to first position so the new array will have the same order
|
||||
newArray.unshift(array[i])
|
||||
}
|
||||
}
|
||||
return newArray
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
filterTransferBeforeES,
|
||||
blockNumberHalfDuplexDisabled
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
require('dotenv').config()
|
||||
const Web3Utils = require('web3').utils
|
||||
const fetch = require('node-fetch')
|
||||
const logger = require('./logger')('validators')
|
||||
const { getBridgeABIs, BRIDGE_VALIDATORS_ABI, gasPriceFromSupplier } = require('../commons')
|
||||
const { web3Home, web3Foreign, getHomeBlockNumber, getForeignBlockNumber } = require('./utils/web3')
|
||||
@@ -81,7 +80,7 @@ async function main(bridgeMode) {
|
||||
if (MONITOR_VALIDATOR_HOME_TX_LIMIT) {
|
||||
logger.debug('calling home getGasPrices')
|
||||
homeGasPrice =
|
||||
(await gasPriceFromSupplier(() => fetch(COMMON_HOME_GAS_PRICE_SUPPLIER_URL), homeGasPriceSupplierOpts)) ||
|
||||
(await gasPriceFromSupplier(COMMON_HOME_GAS_PRICE_SUPPLIER_URL, homeGasPriceSupplierOpts)) ||
|
||||
Web3Utils.toBN(COMMON_HOME_GAS_PRICE_FALLBACK)
|
||||
homeGasPriceGwei = Web3Utils.fromWei(homeGasPrice.toString(), 'gwei')
|
||||
homeTxCost = homeGasPrice.mul(Web3Utils.toBN(MONITOR_VALIDATOR_HOME_TX_LIMIT))
|
||||
@@ -93,13 +92,9 @@ async function main(bridgeMode) {
|
||||
|
||||
if (MONITOR_VALIDATOR_FOREIGN_TX_LIMIT) {
|
||||
logger.debug('calling foreign getGasPrices')
|
||||
const fetchFn =
|
||||
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL === 'gas-price-oracle'
|
||||
? null
|
||||
: () => fetch(COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL)
|
||||
|
||||
foreignGasPrice =
|
||||
(await gasPriceFromSupplier(fetchFn, foreignGasPriceSupplierOpts)) ||
|
||||
(await gasPriceFromSupplier(COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL, foreignGasPriceSupplierOpts)) ||
|
||||
Web3Utils.toBN(COMMON_FOREIGN_GAS_PRICE_FALLBACK)
|
||||
foreignGasPriceGwei = Web3Utils.fromWei(foreignGasPrice.toString(), 'gwei')
|
||||
foreignTxCost = foreignGasPrice.mul(Web3Utils.toBN(MONITOR_VALIDATOR_FOREIGN_TX_LIMIT))
|
||||
|
||||
@@ -5,10 +5,9 @@
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "mocha",
|
||||
"generate-amb-tx": "node ./scripts/generate-amb-tx.js",
|
||||
"lint": "eslint . --ignore-path ../.eslintignore",
|
||||
"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",
|
||||
"alm": "mocha test/amb.js"
|
||||
},
|
||||
@@ -21,11 +20,11 @@
|
||||
"promise-retry": "^1.1.1",
|
||||
"shelljs": "^0.8.2",
|
||||
"tree-kill": "^1.2.0",
|
||||
"web3": "1.0.0-beta.34",
|
||||
"web3": "^1.3.0",
|
||||
"websocket": "^1.0.28"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.18"
|
||||
"node": ">= 12.22"
|
||||
},
|
||||
"devDependencies": {}
|
||||
}
|
||||
|
||||
@@ -5,18 +5,12 @@ case "$mode" in
|
||||
amb)
|
||||
script=./test/amb.js
|
||||
;;
|
||||
native-to-erc)
|
||||
script=./test/nativeToErc.js
|
||||
;;
|
||||
erc-to-erc)
|
||||
script=./test/ercToErc.js
|
||||
;;
|
||||
erc-to-native)
|
||||
script=./test/ercToNative.js
|
||||
;;
|
||||
esac
|
||||
|
||||
MODE="$mode" ../e2e-commons/up.sh deploy blocks oracle oracle-validator-2 oracle-validator-3
|
||||
MODE="$mode" ../e2e-commons/up.sh deploy generate-amb-tx manual-amb-relay blocks oracle oracle-validator-2 oracle-validator-3
|
||||
|
||||
docker-compose -f ../e2e-commons/docker-compose.yml run e2e yarn workspace oracle-e2e run start $script
|
||||
rc=$?
|
||||
|
||||
29
oracle-e2e/scripts/generate-amb-tx.js
Normal file
29
oracle-e2e/scripts/generate-amb-tx.js
Normal file
@@ -0,0 +1,29 @@
|
||||
const Web3 = require('web3')
|
||||
const { user, homeRPC, foreignRPC, amb2: amb } = require('../../e2e-commons/constants.json')
|
||||
const { BOX_ABI } = require('../../commons')
|
||||
|
||||
const homeWeb3 = new Web3(new Web3.providers.HttpProvider(homeRPC.URL))
|
||||
const foreignWeb3 = new Web3(new Web3.providers.HttpProvider(foreignRPC.URL))
|
||||
|
||||
homeWeb3.eth.accounts.wallet.add(user.privateKey)
|
||||
foreignWeb3.eth.accounts.wallet.add(user.privateKey)
|
||||
|
||||
const opts = {
|
||||
from: user.address,
|
||||
gas: 400000,
|
||||
gasPrice: '1'
|
||||
}
|
||||
const homeBox = new homeWeb3.eth.Contract(BOX_ABI, amb.homeBox, opts)
|
||||
const foreignBox = new foreignWeb3.eth.Contract(BOX_ABI, amb.foreignBox, opts)
|
||||
|
||||
async function main() {
|
||||
const res1 = await homeBox.methods.setValueOnOtherNetwork(123, amb.home, amb.foreignBox).send()
|
||||
const res2 = await foreignBox.methods.setValueOnOtherNetwork(456, amb.foreign, amb.homeBox).send()
|
||||
const res3 = await foreignBox.methods.setValueOnOtherNetwork(789, amb.foreign, amb.homeBox).send()
|
||||
|
||||
console.log(res1.transactionHash)
|
||||
console.log(res2.transactionHash)
|
||||
console.log(res3.transactionHash)
|
||||
}
|
||||
|
||||
main()
|
||||
@@ -1,8 +1,9 @@
|
||||
const Web3 = require('web3')
|
||||
const assert = require('assert')
|
||||
const { ASYNC_CALL_ERRORS } = require('../../oracle/src/utils/constants')
|
||||
const { user, homeRPC, foreignRPC, amb, validator } = require('../../e2e-commons/constants.json')
|
||||
const { uniformRetry } = require('../../e2e-commons/utils')
|
||||
const { BOX_ABI, HOME_AMB_ABI, FOREIGN_AMB_ABI } = require('../../commons')
|
||||
const { BOX_ABI, HOME_AMB_ABI, FOREIGN_AMB_ABI, ambInformationSignatures } = require('../../commons')
|
||||
const { delay, setRequiredSignatures } = require('./utils')
|
||||
|
||||
const { toBN } = Web3.utils
|
||||
@@ -10,23 +11,69 @@ const { toBN } = Web3.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 = amb.home
|
||||
const COMMON_FOREIGN_BRIDGE_ADDRESS = amb.foreign
|
||||
|
||||
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 homeBox = new homeWeb3.eth.Contract(BOX_ABI, amb.homeBox)
|
||||
const blockHomeBox = new homeWeb3.eth.Contract(BOX_ABI, amb.blockedHomeBox)
|
||||
const foreignBox = new foreignWeb3.eth.Contract(BOX_ABI, amb.foreignBox)
|
||||
const homeBridge = new homeWeb3.eth.Contract(HOME_AMB_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
||||
const foreignBridge = new foreignWeb3.eth.Contract(FOREIGN_AMB_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
const opts = {
|
||||
from: user.address,
|
||||
gas: 400000,
|
||||
gasPrice: '1'
|
||||
}
|
||||
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)
|
||||
|
||||
function validateBlock(web3, serialized, block) {
|
||||
assert.strictEqual(serialized.length, 2 + 64 * 12)
|
||||
const values = web3.eth.abi.decodeParameter(
|
||||
'(uint256,bytes32,address,uint256,uint256,bytes32,bytes32,bytes32,bytes32,uint256,uint256,uint256)',
|
||||
serialized
|
||||
)
|
||||
assert.strictEqual(values[0], block.number.toString(), 'wrong block number returned')
|
||||
assert.strictEqual(values[1], block.hash, 'wrong block hash returned')
|
||||
assert.strictEqual(values[2], block.miner, 'wrong block miner returned')
|
||||
assert.strictEqual(values[3], block.gasUsed.toString(), 'wrong block gasUsed returned')
|
||||
assert.strictEqual(values[4], block.gasLimit.toString(), 'wrong block gasLimit returned')
|
||||
assert.strictEqual(values[5], block.parentHash, 'wrong block parentHash returned')
|
||||
assert.strictEqual(values[6], block.receiptsRoot, 'wrong block receiptsRoot returned')
|
||||
assert.strictEqual(values[7], block.stateRoot, 'wrong block stateRoot returned')
|
||||
assert.strictEqual(values[8], block.transactionsRoot, 'wrong block transactionsRoot returned')
|
||||
assert.strictEqual(values[9], block.timestamp.toString(), 'wrong block timestamp returned')
|
||||
assert.strictEqual(values[10], block.difficulty, 'wrong block difficulty returned')
|
||||
assert.strictEqual(values[11], block.totalDifficulty, 'wrong block totalDifficulty returned')
|
||||
}
|
||||
|
||||
function validateTransaction(web3, serialized, tx) {
|
||||
assert.strictEqual(serialized.length, 64 * 13 + tx.input.length + 56)
|
||||
const values = web3.eth.abi.decodeParameter(
|
||||
'(bytes32,uint256,bytes32,uint256,address,address,uint256,uint256,uint256,uint256,bytes)',
|
||||
serialized
|
||||
)
|
||||
assert.strictEqual(values[0], tx.hash, 'wrong txHash returned')
|
||||
assert.strictEqual(values[1], tx.blockNumber.toString(), 'wrong tx blockNumber returned')
|
||||
assert.strictEqual(values[2], tx.blockHash.toString(), 'wrong tx blockHash returned')
|
||||
assert.strictEqual(values[3], tx.transactionIndex.toString(), 'wrong tx transactionIndex returned')
|
||||
assert.strictEqual(values[4], tx.from, 'wrong tx from returned')
|
||||
assert.strictEqual(values[5], tx.to, 'wrong tx to returned')
|
||||
assert.strictEqual(values[6], tx.value, 'wrong tx value returned')
|
||||
assert.strictEqual(values[7], tx.nonce.toString(), 'wrong tx nonce returned')
|
||||
assert.strictEqual(values[8], tx.gas.toString(), 'wrong tx gas returned')
|
||||
assert.strictEqual(values[9], tx.gasPrice, 'wrong tx gasPrice returned')
|
||||
assert.strictEqual(values[10], tx.input, 'wrong tx data returned')
|
||||
}
|
||||
|
||||
describe('arbitrary message bridging', () => {
|
||||
let requiredSignatures = 1
|
||||
before(async () => {
|
||||
for (const method of ambInformationSignatures) {
|
||||
const selector = homeWeb3.utils.soliditySha3(method)
|
||||
await homeBridge.methods.enableAsyncRequestSelector(selector, true).send({ from: validator.address })
|
||||
}
|
||||
|
||||
// Only 1 validator is used in ultimate tests
|
||||
if (process.env.ULTIMATE === 'true') {
|
||||
return
|
||||
@@ -56,6 +103,19 @@ describe('arbitrary message bridging', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
if (process.env.ULTIMATE !== 'true') {
|
||||
describe('Confirm Relay', () => {
|
||||
it('should process lost affirmation-request via confirm relay', async () => {
|
||||
const value = await homeBox.methods.value().call()
|
||||
assert(value === '789', 'incorrect value')
|
||||
})
|
||||
|
||||
it('should process lost signature-request & collected-signatures via confirm relay', async () => {
|
||||
const value = await foreignBox.methods.value().call()
|
||||
assert(value === '123', 'incorrect value')
|
||||
})
|
||||
})
|
||||
}
|
||||
describe('Home to Foreign', () => {
|
||||
describe('Subsidized Mode', () => {
|
||||
it('should bridge message', async () => {
|
||||
@@ -64,15 +124,13 @@ describe('arbitrary message bridging', () => {
|
||||
const initialValue = await foreignBox.methods.value().call()
|
||||
assert(!toBN(initialValue).eq(toBN(newValue)), 'initial value should be different from new value')
|
||||
|
||||
await homeBox.methods
|
||||
const res = await homeBox.methods
|
||||
.setValueOnOtherNetwork(newValue, amb.home, amb.foreignBox)
|
||||
.send({
|
||||
from: user.address,
|
||||
gas: '400000'
|
||||
})
|
||||
.send()
|
||||
.catch(e => {
|
||||
console.error(e)
|
||||
})
|
||||
console.log(res.transactionHash)
|
||||
|
||||
// check that value changed and balance decreased
|
||||
await uniformRetry(async retry => {
|
||||
@@ -98,10 +156,7 @@ describe('arbitrary message bridging', () => {
|
||||
|
||||
await blockHomeBox.methods
|
||||
.setValueOnOtherNetwork(newValue, amb.home, amb.foreignBox)
|
||||
.send({
|
||||
from: user.address,
|
||||
gas: '400000'
|
||||
})
|
||||
.send()
|
||||
.catch(e => {
|
||||
console.error(e)
|
||||
})
|
||||
@@ -137,10 +192,7 @@ describe('arbitrary message bridging', () => {
|
||||
|
||||
await homeBox.methods
|
||||
.setValueOnOtherNetworkUsingManualLane(newValue, amb.home, amb.foreignBox)
|
||||
.send({
|
||||
from: user.address,
|
||||
gas: '400000'
|
||||
})
|
||||
.send()
|
||||
.catch(e => {
|
||||
console.error(e)
|
||||
})
|
||||
@@ -171,15 +223,13 @@ describe('arbitrary message bridging', () => {
|
||||
const initialValue = await homeBox.methods.value().call()
|
||||
assert(!toBN(initialValue).eq(toBN(newValue)), 'initial value should be different from new value')
|
||||
|
||||
await foreignBox.methods
|
||||
const res = await foreignBox.methods
|
||||
.setValueOnOtherNetwork(newValue, amb.foreign, amb.homeBox)
|
||||
.send({
|
||||
from: user.address,
|
||||
gas: '400000'
|
||||
})
|
||||
.send()
|
||||
.catch(e => {
|
||||
console.error(e)
|
||||
})
|
||||
console.log(res.transactionHash)
|
||||
|
||||
// check that value changed and balance decreased
|
||||
await uniformRetry(async retry => {
|
||||
@@ -191,4 +241,338 @@ 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(), ASYNC_CALL_ERRORS.REVERT, '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(), ASYNC_CALL_ERRORS.REVERT, '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(), 25]
|
||||
)
|
||||
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')
|
||||
assert.strictEqual(
|
||||
await homeBox.methods.data().call(),
|
||||
ASYNC_CALL_ERRORS.BLOCK_IS_IN_THE_FUTURE,
|
||||
'returned data is incorrect'
|
||||
)
|
||||
})
|
||||
|
||||
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()
|
||||
const block = await foreignWeb3.eth.getBlock(blockNumber)
|
||||
validateBlock(homeWeb3, data, block)
|
||||
})
|
||||
|
||||
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 * 12)
|
||||
})
|
||||
|
||||
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()
|
||||
validateBlock(homeWeb3, data, block)
|
||||
})
|
||||
|
||||
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 = '0x7262f7dbe6c30599edded2137fbbe93c271b37f5c54dd27f713f0cf510e3b4dd'
|
||||
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()
|
||||
validateTransaction(homeWeb3, data, tx)
|
||||
})
|
||||
|
||||
it('should make async eth_getTransactionReceipt', async () => {
|
||||
const txHash = '0x7262f7dbe6c30599edded2137fbbe93c271b37f5c54dd27f713f0cf510e3b4dd'
|
||||
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 values = homeWeb3.eth.abi.decodeParameter(
|
||||
'(bytes32,uint256,bytes32,uint256,address,address,uint256,bool,(address,bytes32[],bytes)[])',
|
||||
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.blockHash, 'wrong tx blockHash returned')
|
||||
assert.strictEqual(values[3], receipt.transactionIndex.toString(), 'wrong tx transactionIndex returned')
|
||||
assert.strictEqual(values[4].toLowerCase(), receipt.from, 'wrong tx from returned')
|
||||
assert.strictEqual(values[5].toLowerCase(), receipt.to, 'wrong tx to returned')
|
||||
assert.strictEqual(values[6], receipt.gasUsed.toString(), 'wrong gasUsed to returned')
|
||||
assert.strictEqual(values[7], receipt.status, 'wrong tx status returned')
|
||||
assert.strictEqual(values[8].length, 1, 'wrong logs length returned')
|
||||
assert.strictEqual(values[8][0][0], receipt.logs[0].address, 'wrong log address returned')
|
||||
assert.strictEqual(values[8][0][1].length, 2, 'wrong log topics length returned')
|
||||
assert.strictEqual(values[8][0][1][0], receipt.logs[0].topics[0], 'wrong event signature returned')
|
||||
assert.strictEqual(values[8][0][1][1], receipt.logs[0].topics[1], 'wrong message id returned')
|
||||
assert.strictEqual(values[8][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 assert = require('assert')
|
||||
const promiseRetry = require('promise-retry')
|
||||
const {
|
||||
user,
|
||||
secondUser,
|
||||
@@ -10,7 +9,7 @@ const {
|
||||
homeRPC,
|
||||
foreignRPC
|
||||
} = require('../../e2e-commons/constants.json')
|
||||
const { ERC677_BRIDGE_TOKEN_ABI, FOREIGN_ERC_TO_NATIVE_ABI, HOME_ERC_TO_NATIVE_ABI } = require('../../commons')
|
||||
const { ERC20_ABI, FOREIGN_ERC_TO_NATIVE_ABI, HOME_ERC_TO_NATIVE_ABI } = require('../../commons')
|
||||
const { uniformRetry, sleep } = require('../../e2e-commons/utils')
|
||||
const { setRequiredSignatures } = require('./utils')
|
||||
|
||||
@@ -28,12 +27,16 @@ 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, 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 homeBridge = new homeWeb3.eth.Contract(HOME_ERC_TO_NATIVE_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
||||
|
||||
describe('erc to native', () => {
|
||||
before(async () => {
|
||||
console.log('Initializing interest')
|
||||
await foreignBridge.methods
|
||||
.initializeInterest(ercToNativeBridge.foreignToken, 1, 1, validator.address)
|
||||
.send({ from: validator.address, gas: '4000000' })
|
||||
if (process.env.ULTIMATE === 'true') {
|
||||
return
|
||||
}
|
||||
@@ -101,6 +104,8 @@ describe('erc to native', () => {
|
||||
|
||||
const transferValue = homeWeb3.utils.toWei('0.05')
|
||||
|
||||
// transfer that should not be processed by the filter
|
||||
await erc20Token.methods.transfer(secondUser.address, transferValue).send({ from: user.address, gas: 100000 })
|
||||
// send tokens to foreign bridge
|
||||
await erc20Token.methods
|
||||
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, transferValue)
|
||||
@@ -111,6 +116,7 @@ describe('erc to native', () => {
|
||||
.catch(e => {
|
||||
console.error(e)
|
||||
})
|
||||
await foreignBridge.methods.investDai().send({ from: validator.address, gas: '4000000' })
|
||||
|
||||
// check that balance increases
|
||||
await uniformRetry(async retry => {
|
||||
@@ -196,211 +202,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 +1 @@
|
||||
--timeout 120000
|
||||
--timeout 120000 --exit
|
||||
|
||||
@@ -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"],
|
||||
"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
|
||||
|
||||
@@ -11,7 +11,7 @@ COPY ./contracts/truffle-config.js ./
|
||||
COPY ./contracts/contracts ./contracts
|
||||
RUN npm run compile
|
||||
|
||||
FROM node:10
|
||||
FROM node:12
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y build-essential libc6-dev libc6-dev-i386 wget && \
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user