diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 79671ef58..19ba97635 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -182,6 +182,7 @@ jobs: deployment: runs-on: ubuntu-latest needs: + - build-e2e-images - build-molecule-runner strategy: fail-fast: false @@ -197,11 +198,11 @@ jobs: run: docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }} - run: deployment-e2e/molecule.sh ${{ matrix.task }} ultimate: + if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/tags') || contains(github.event.head_commit.message, 'ultimate') runs-on: ubuntu-latest needs: - initialize - build-e2e-images - if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/tags') strategy: fail-fast: false matrix: @@ -209,12 +210,16 @@ jobs: include: - task: erc-to-erc ui-e2e-grep: 'ERC TO ERC' + ui-config: 'e2e-commons/components-envs/ui-erc20.env' - task: erc-to-native ui-e2e-grep: 'ERC TO NATIVE' + ui-config: 'e2e-commons/components-envs/ui-erc20-native.env' - task: native-to-erc ui-e2e-grep: 'NATIVE TO ERC' + ui-config: 'e2e-commons/components-envs/ui.env' - task: amb-stake-erc-to-erc ui-e2e-grep: 'AMB-STAKE-ERC-TO-ERC' + ui-config: 'e2e-commons/components-envs/ui-amb-stake-erc20-erc20.env' steps: - uses: actions/checkout@v2 with: @@ -240,7 +245,20 @@ jobs: - name: Deploy contracts run: ${{ steps.cache-repo.outputs.cache-hit }} && e2e-commons/up.sh deploy blocks - name: Pull e2e oracle image - run: docker-compose -f ./e2e-commons/docker-compose.yml pull oracle + run: | + docker-compose -f ./e2e-commons/docker-compose.yml pull oracle + docker tag ${DOCKER_IMAGE_BASE}/tokenbridge-e2e-oracle:${ORACLE_TAG} poanetwork/tokenbridge-oracle:latest + - if: ${{ matrix.ui-e2e-grep }} + name: Pull e2e ui image + run: | + docker-compose -f ./e2e-commons/docker-compose.yml pull ui + docker build \ + --build-arg DOCKER_IMAGE_BASE=${DOCKER_IMAGE_BASE} \ + --build-arg UI_TAG=${UI_TAG} \ + --build-arg DOT_ENV_PATH=${{ matrix.ui-config }} \ + -f ./e2e-commons/Dockerfile.ui \ + -t ui_ui:latest \ + . - name: Deploy oracle and ui run: deployment-e2e/molecule.sh ultimate-${{ matrix.task }} - name: Reset docker socket permissions diff --git a/.gitignore b/.gitignore index 7cea05397..9655fe720 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,6 @@ monitor/responses/* monitor/cache/* !monitor/cache/.gitkeep !monitor/.gitkeep + +# Local Netlify folder +.netlify \ No newline at end of file diff --git a/alm/package.json b/alm/package.json index dfee20a9f..41ede67e7 100644 --- a/alm/package.json +++ b/alm/package.json @@ -3,6 +3,7 @@ "version": "0.1.0", "private": true, "dependencies": { + "@ethersproject/bignumber": ">=5.0.0-beta.130", "@react-hook/window-size": "^3.0.6", "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.3.2", @@ -15,6 +16,8 @@ "@types/react-router-dom": "^5.1.5", "@types/styled-components": "^5.1.0", "@use-it/interval": "^0.1.3", + "@web3-react/core": "^6.1.1", + "@web3-react/injected-connector": "^6.0.7", "customize-cra": "^1.0.0", "date-fns": "^2.14.0", "dotenv": "^8.2.0", @@ -27,8 +30,9 @@ "react-scripts": "3.0.1", "styled-components": "^5.1.1", "typescript": "^3.5.2", - "web3": "1.2.7", - "web3-eth-contract": "1.2.7" + "web3": "1.2.11", + "web3-eth-contract": "1.2.11", + "web3-utils": "1.2.11" }, "scripts": { "start": "yarn createSnapshots && ./load-env.sh react-app-rewired start", diff --git a/alm/public/_redirects b/alm/public/_redirects new file mode 100644 index 000000000..78f7f2067 --- /dev/null +++ b/alm/public/_redirects @@ -0,0 +1 @@ +/* /index.html 200 \ No newline at end of file diff --git a/alm/src/App.tsx b/alm/src/App.tsx index 3ab3eaf66..81f3bc0cd 100644 --- a/alm/src/App.tsx +++ b/alm/src/App.tsx @@ -1,14 +1,18 @@ import React from 'react' import { BrowserRouter } from 'react-router-dom' +import { Web3ReactProvider } from '@web3-react/core' +import Web3 from 'web3' import { MainPage } from './components/MainPage' import { StateProvider } from './state/StateProvider' function App() { return ( - - - + new Web3(provider)}> + + + + ) } diff --git a/alm/src/components/ConfirmationsContainer.tsx b/alm/src/components/ConfirmationsContainer.tsx index 4edc9488a..57ff0b7d0 100644 --- a/alm/src/components/ConfirmationsContainer.tsx +++ b/alm/src/components/ConfirmationsContainer.tsx @@ -49,7 +49,16 @@ export const ConfirmationsContainer = ({ message, receipt, fromHome, timestamp } } = useStateProvider() const { requiredSignatures, validatorList } = useValidatorContract({ fromHome, receipt }) const { blockConfirmations } = useBlockConfirmations({ fromHome, receipt }) - const { confirmations, status, executionData, signatureCollected, waitingBlocksResolved } = useMessageConfirmations({ + const { + confirmations, + status, + executionData, + signatureCollected, + waitingBlocksResolved, + setExecutionData, + executionEventsFetched, + setPendingExecution + } = useMessageConfirmations({ message, receipt, fromHome, @@ -102,7 +111,17 @@ export const ConfirmationsContainer = ({ message, receipt, fromHome, timestamp } validatorList={validatorList} waitingBlocksResolved={waitingBlocksResolved} /> - {signatureCollected && } + {signatureCollected && ( + + )} ) diff --git a/alm/src/components/ExecutionConfirmation.tsx b/alm/src/components/ExecutionConfirmation.tsx index d1af0a908..1541e7bf6 100644 --- a/alm/src/components/ExecutionConfirmation.tsx +++ b/alm/src/components/ExecutionConfirmation.tsx @@ -1,24 +1,45 @@ import React from 'react' import { formatTimestamp, formatTxHash, getExplorerTxUrl } from '../utils/networks' import { useWindowWidth } from '@react-hook/window-size' -import { SEARCHING_TX, VALIDATOR_CONFIRMATION_STATUS } from '../config/constants' +import { SEARCHING_TX, VALIDATOR_CONFIRMATION_STATUS, ALM_HOME_TO_FOREIGN_MANUAL_EXECUTION } from '../config/constants' import { SimpleLoading } from './commons/Loading' import styled from 'styled-components' import { ExecutionData } from '../hooks/useMessageConfirmations' import { GreyLabel, RedLabel, SuccessLabel } from './commons/Labels' import { ExplorerTxLink } from './commons/ExplorerTxLink' import { Thead, AgeTd, StatusTd } from './commons/Table' +import { ManualExecutionButton } from './ManualExecutionButton' const StyledExecutionConfirmation = styled.div` margin-top: 30px; ` export interface ExecutionConfirmationParams { + messageData: string executionData: ExecutionData + setExecutionData: Function + signatureCollected: boolean | string[] isHome: boolean + executionEventsFetched: boolean + setPendingExecution: Function } -export const ExecutionConfirmation = ({ executionData, isHome }: ExecutionConfirmationParams) => { +export const ExecutionConfirmation = ({ + messageData, + executionData, + setExecutionData, + signatureCollected, + isHome, + executionEventsFetched, + setPendingExecution +}: ExecutionConfirmationParams) => { + const availableManualExecution = + !isHome && + (executionData.status === VALIDATOR_CONFIRMATION_STATUS.WAITING || + (executionData.status === VALIDATOR_CONFIRMATION_STATUS.UNDEFINED && + executionEventsFetched && + !!executionData.validator)) + const requiredManualExecution = availableManualExecution && ALM_HOME_TO_FOREIGN_MANUAL_EXECUTION const windowWidth = useWindowWidth() const txExplorerLink = getExplorerTxUrl(executionData.txHash, isHome) @@ -48,26 +69,47 @@ export const ExecutionConfirmation = ({ executionData, isHome }: ExecutionConfir - + - + {!requiredManualExecution && } + {availableManualExecution && } - - {getExecutionStatusElement(executionData.status)} - - {executionData.timestamp > 0 ? ( - - {formatTimestamp(executionData.timestamp)} - - ) : executionData.status === VALIDATOR_CONFIRMATION_STATUS.WAITING ? ( - '' + + {getExecutionStatusElement(executionData.status)} + {!requiredManualExecution && ( + + {executionData.timestamp > 0 ? ( + + {formatTimestamp(executionData.timestamp)} + + ) : executionData.status === VALIDATOR_CONFIRMATION_STATUS.WAITING ? ( + '' + ) : ( + SEARCHING_TX + )} + + )} + {availableManualExecution && ( + + )}
Executed by{requiredManualExecution ? 'Execution info' : 'Executed by'} StatusAgeAgeActions
{formattedValidator ? formattedValidator : } + {requiredManualExecution ? ( + 'Manual user action is required to complete the operation' + ) : formattedValidator ? ( + formattedValidator ) : ( - SEARCHING_TX + )} - + + +
diff --git a/alm/src/components/MainPage.tsx b/alm/src/components/MainPage.tsx index 88ced8153..9697d65c1 100644 --- a/alm/src/components/MainPage.tsx +++ b/alm/src/components/MainPage.tsx @@ -8,6 +8,7 @@ import { TransactionReceipt } from 'web3-eth' import { InfoAlert } from './commons/InfoAlert' import { ExplorerTxLink } from './commons/ExplorerTxLink' import { FOREIGN_NETWORK_NAME, HOME_NETWORK_NAME } from '../config/constants' +import { ErrorAlert } from './commons/ErrorAlert' const StyledMainPage = styled.div` text-align: center; @@ -51,7 +52,7 @@ export interface FormSubmitParams { export const MainPage = () => { const history = useHistory() - const { home, foreign } = useStateProvider() + const { home, foreign, error, setError } = useStateProvider() const [networkName, setNetworkName] = useState('') const [receipt, setReceipt] = useState>(null) const [showInfoAlert, setShowInfoAlert] = useState(false) @@ -131,6 +132,7 @@ export const MainPage = () => { )} + {error && setError('')} error={error} />} } /> { + const { foreign, setError } = useStateProvider() + const { library, activate, account, active } = useWeb3React() + const [manualExecution, setManualExecution] = useState(false) + + useEffect( + () => { + if (!manualExecution || !foreign.chainId) return + + if (!active) { + activate(new InjectedConnector({ supportedChainIds: [foreign.chainId] }), e => { + if (e.message.includes('Unsupported chain id')) { + setError(INCORRECT_CHAIN_ERROR) + const { ethereum } = window as any + + // remove the error message after chain is correctly changed to the foreign one + const listener = (chainId: string) => { + if (parseInt(chainId.slice(2), 16) === foreign.chainId) { + ethereum.removeListener('chainChanged', listener) + setError((error: string) => (error === INCORRECT_CHAIN_ERROR ? '' : error)) + } + } + ethereum.on('chainChanged', listener) + } else { + setError(e.message) + } + setManualExecution(false) + }) + return + } + + if (!library || !foreign.bridgeContract) return + + const signatures = packSignatures(signatureCollected.map(signatureToVRS)) + const data = foreign.bridgeContract.methods.executeSignatures(messageData, signatures).encodeABI() + setManualExecution(false) + + library.eth + .sendTransaction({ + from: account, + to: foreign.bridgeAddress, + data + }) + .on('transactionHash', (txHash: string) => { + setExecutionData({ + status: VALIDATOR_CONFIRMATION_STATUS.PENDING, + validator: account, + txHash, + timestamp: Math.floor(new Date().getTime() / 1000.0), + executionResult: false + }) + setPendingExecution(true) + }) + .on('error', (e: Error) => setError(e.message)) + }, + [ + manualExecution, + library, + activate, + active, + account, + foreign.chainId, + foreign.bridgeAddress, + foreign.bridgeContract, + setError, + messageData, + signatureCollected, + setExecutionData, + setPendingExecution + ] + ) + + return ( +
+ setManualExecution(true)}> + Execute + +
+ ) +} diff --git a/alm/src/components/commons/CloseIcon.tsx b/alm/src/components/commons/CloseIcon.tsx index 702e3edf5..732421152 100644 --- a/alm/src/components/commons/CloseIcon.tsx +++ b/alm/src/components/commons/CloseIcon.tsx @@ -1,6 +1,6 @@ import React from 'react' -export const CloseIcon = () => ( +export const CloseIcon = ({ color }: { color?: string }) => ( ) diff --git a/alm/src/components/commons/ErrorAlert.tsx b/alm/src/components/commons/ErrorAlert.tsx new file mode 100644 index 000000000..af3e3f598 --- /dev/null +++ b/alm/src/components/commons/ErrorAlert.tsx @@ -0,0 +1,31 @@ +import React from 'react' +import styled from 'styled-components' +import { InfoIcon } from './InfoIcon' +import { CloseIcon } from './CloseIcon' + +const StyledErrorAlert = styled.div` + border: 1px solid var(--failed-color); + border-radius: 4px; + margin-bottom: 20px; + padding-top: 10px; +` + +const CloseIconContainer = styled.div` + cursor: pointer; +` + +const TextContainer = styled.div` + flex-direction: column; +` + +export const ErrorAlert = ({ onClick, error }: { onClick: () => void; error: string }) => ( +
+ + + {error} + + + + +
+) diff --git a/alm/src/components/commons/InfoIcon.tsx b/alm/src/components/commons/InfoIcon.tsx index f8d84f927..9fd62c6ec 100644 --- a/alm/src/components/commons/InfoIcon.tsx +++ b/alm/src/components/commons/InfoIcon.tsx @@ -1,6 +1,6 @@ import React from 'react' -export const InfoIcon = () => ( +export const InfoIcon = ({ color }: { color?: string }) => ( ( data-icon="info-circle" width="1em" height="1em" - fill="#1890ff" + fill={color || '#1890ff'} aria-hidden="true" > diff --git a/alm/src/config/constants.ts b/alm/src/config/constants.ts index 6c2e2fba7..5685440d3 100644 --- a/alm/src/config/constants.ts +++ b/alm/src/config/constants.ts @@ -13,6 +13,9 @@ export const FOREIGN_EXPLORER_TX_TEMPLATE: string = process.env.REACT_APP_ALM_FO export const HOME_EXPLORER_API: string = process.env.REACT_APP_ALM_HOME_EXPLORER_API || '' export const FOREIGN_EXPLORER_API: string = process.env.REACT_APP_ALM_FOREIGN_EXPLORER_API || '' +export const ALM_HOME_TO_FOREIGN_MANUAL_EXECUTION: boolean = + (process.env.REACT_APP_ALM_HOME_TO_FOREIGN_MANUAL_EXECUTION || '').toLowerCase() === 'true' + export const HOME_RPC_POLLING_INTERVAL: number = 5000 export const FOREIGN_RPC_POLLING_INTERVAL: number = 5000 export const BLOCK_RANGE: number = 50 @@ -61,3 +64,5 @@ export const VALIDATOR_CONFIRMATION_STATUS = { } export const SEARCHING_TX = 'Searching Transaction...' + +export const INCORRECT_CHAIN_ERROR = `Incorrect chain chosen. Switch to ${FOREIGN_NETWORK_NAME} in the wallet.` diff --git a/alm/src/config/descriptions.ts b/alm/src/config/descriptions.ts index 7d6682b05..f7bf3cc7a 100644 --- a/alm/src/config/descriptions.ts +++ b/alm/src/config/descriptions.ts @@ -1,4 +1,6 @@ // %t will be replaced by the time -> x minutes/hours/days ago +import { ALM_HOME_TO_FOREIGN_MANUAL_EXECUTION } from './constants' + export const TRANSACTION_STATUS_DESCRIPTION: { [key: string]: string } = { SUCCESS_MULTIPLE_MESSAGES: 'was initiated %t and contains several bridge messages. Specify one of them:', SUCCESS_ONE_MESSAGE: 'was initiated %t', @@ -24,7 +26,7 @@ export const CONFIRMATIONS_STATUS_LABEL_HOME: { [key: string]: string } = { SUCCESS_MESSAGE_FAILED: 'Success', EXECUTION_FAILED: 'Execution failed', EXECUTION_PENDING: 'Execution pending', - EXECUTION_WAITING: 'Execution waiting', + EXECUTION_WAITING: ALM_HOME_TO_FOREIGN_MANUAL_EXECUTION ? 'Manual execution waiting' : 'Execution waiting', FAILED: 'Confirmation Failed', PENDING: 'Confirmation Pending', WAITING_VALIDATORS: 'Confirmation Waiting', @@ -55,11 +57,12 @@ export const CONFIRMATIONS_STATUS_DESCRIPTION_HOME: { [key: string]: string } = SUCCESS_MESSAGE_FAILED: 'The specified transaction was included in a block,\nthe validators collected signatures and the cross-chain relay was executed correctly,\nbut the contained message execution failed.\nContact the support of the application you used to produce the transaction for the clarifications.', EXECUTION_FAILED: - 'The specified transaction was included in a block\nand the validators collected signatures. The\nvalidator’s transaction with collected signatures was\nsent but did not succeed. Contact to the validators by messaging\non %linkhttps://forum.poa.network/c/support', + 'The specified transaction was included in a block\nand the validators collected signatures. The\n transaction with collected signatures was\nsent but did not succeed. Contact to the validators by messaging\non %linkhttps://forum.poa.network/c/support', EXECUTION_PENDING: - 'The specified transaction was included in a block\nand the validators collected signatures. The\nvalidator’s transaction with collected signatures was\nsent but is not yet added to a block.', - EXECUTION_WAITING: - 'The specified transaction was included in a block\nand the validators collected signatures. Either\n1. One of the validators is waiting for chain finalization.\n2. A validator skipped its duty to relay signatures.\n3. The execution transaction is still pending (e.g. due to the gas price spike).\nCheck status again after a few blocks. If the issue still persists contact to the validators by messaging on %linkhttps://forum.poa.network/c/support', + 'The specified transaction was included in a block\nand the validators collected signatures. The\n transaction with collected signatures was\nsent but is not yet added to a block.', + EXECUTION_WAITING: ALM_HOME_TO_FOREIGN_MANUAL_EXECUTION + ? 'The specified transaction was included in a block\nand the validators collected signatures.\nNow the manual user action is required to complete message execution.\n Please, press the "Execute" button.' + : 'The specified transaction was included in a block\nand the validators collected signatures. Either\n1. One of the validators is waiting for chain finalization.\n2. A validator skipped its duty to relay signatures.\n3. The execution transaction is still pending (e.g. due to the gas price spike).\nCheck status again after a few blocks or force execution by pressing the "Execute" button.\nIf the issue still persists contact to the validators by messaging on %linkhttps://forum.poa.network/c/support', FAILED: 'The specified transaction was included in a block,\nbut transactions with signatures sent by a majority of\nvalidators failed. The cross-chain relay request will\nnot be processed. Contact to the validators by\nmessaging on %linkhttps://forum.poa.network/c/support', PENDING: diff --git a/alm/src/hooks/useMessageConfirmations.ts b/alm/src/hooks/useMessageConfirmations.ts index c470185cf..f21b7208a 100644 --- a/alm/src/hooks/useMessageConfirmations.ts +++ b/alm/src/hooks/useMessageConfirmations.ts @@ -3,7 +3,6 @@ import { TransactionReceipt } from 'web3-eth' import { MessageObject } from '../utils/web3' import { useEffect, useState } from 'react' import { EventData } from 'web3-eth-contract' -import { getAffirmationsSigned, getMessagesSigned } from '../utils/contract' import { BLOCK_RANGE, CONFIRMATIONS_STATUS, @@ -43,6 +42,7 @@ export interface BasicConfirmationParam { export interface ConfirmationParam extends BasicConfirmationParam { txHash: string timestamp: number + signature?: string } export interface ExecutionData { @@ -63,11 +63,12 @@ export const useMessageConfirmations = ({ blockConfirmations }: useMessageConfirmationsParams) => { const { home, foreign } = useStateProvider() - const [confirmations, setConfirmations] = useState>([]) + const [confirmations, setConfirmations] = useState([]) const [status, setStatus] = useState(CONFIRMATIONS_STATUS.UNDEFINED) const [waitingBlocks, setWaitingBlocks] = useState(false) const [waitingBlocksResolved, setWaitingBlocksResolved] = useState(false) const [signatureCollected, setSignatureCollected] = useState(false) + const [executionEventsFetched, setExecutionEventsFetched] = useState(false) const [collectedSignaturesEvent, setCollectedSignaturesEvent] = useState>(null) const [executionData, setExecutionData] = useState({ status: VALIDATOR_CONFIRMATION_STATUS.UNDEFINED, @@ -93,7 +94,7 @@ export const useMessageConfirmations = ({ // Check if the validators are waiting for block confirmations to verify the message useEffect( () => { - if (!receipt || !blockConfirmations) return + if (!receipt || !blockConfirmations || waitingBlocksResolved) return const subscriptions: Array = [] @@ -126,7 +127,16 @@ export const useMessageConfirmations = ({ blockProvider.stop() } }, - [blockConfirmations, foreign.web3, fromHome, validatorList, home.web3, receipt] + [ + blockConfirmations, + foreign.web3, + fromHome, + validatorList, + home.web3, + receipt, + setConfirmations, + waitingBlocksResolved + ] ) // The collected signature event is only fetched once the signatures are collected on tx from home to foreign, to calculate if @@ -173,6 +183,7 @@ export const useMessageConfirmations = ({ useEffect( () => { if (!fromHome || !home.web3 || !receipt || !collectedSignaturesEvent || !blockConfirmations) return + if (waitingBlocksForExecutionResolved) return const subscriptions: Array = [] @@ -201,7 +212,7 @@ export const useMessageConfirmations = ({ homeBlockNumberProvider.stop() } }, - [collectedSignaturesEvent, fromHome, blockConfirmations, home.web3, receipt] + [collectedSignaturesEvent, fromHome, blockConfirmations, home.web3, receipt, waitingBlocksForExecutionResolved] ) // Checks if validators verified the message @@ -218,14 +229,12 @@ export const useMessageConfirmations = ({ }) } - const confirmationContractMethod = fromHome ? getMessagesSigned : getAffirmationsSigned - getConfirmationsForTx( message.data, home.web3, validatorList, home.bridgeContract, - confirmationContractMethod, + fromHome, setConfirmations, requiredSignatures, setSignatureCollected, @@ -251,7 +260,8 @@ export const useMessageConfirmations = ({ home.bridgeContract, requiredSignatures, waitingBlocksResolved, - timestamp + timestamp, + setConfirmations ] ) @@ -289,7 +299,8 @@ export const useMessageConfirmations = ({ getExecutionFailedTransactionForMessage, setFailedExecution, getExecutionPendingTransactionsForMessage, - setPendingExecution + setPendingExecution, + setExecutionEventsFetched ) return () => { @@ -369,6 +380,9 @@ export const useMessageConfirmations = ({ status, signatureCollected, executionData, - waitingBlocksResolved + setExecutionData, + waitingBlocksResolved, + executionEventsFetched, + setPendingExecution } } diff --git a/alm/src/state/StateProvider.tsx b/alm/src/state/StateProvider.tsx index c495ef65f..e324c9b64 100644 --- a/alm/src/state/StateProvider.tsx +++ b/alm/src/state/StateProvider.tsx @@ -1,4 +1,4 @@ -import React, { createContext, ReactNode } from 'react' +import React, { createContext, ReactNode, useState } from 'react' import { useNetwork } from '../hooks/useNetwork' import { HOME_RPC_URL, @@ -25,6 +25,8 @@ export interface StateContext { home: BaseNetworkParams foreign: BaseNetworkParams loading: boolean + error: string + setError: Function } const initialState = { @@ -42,7 +44,9 @@ const initialState = { bridgeAddress: FOREIGN_BRIDGE_ADDRESS, bridgeContract: null }, - loading: true + loading: true, + error: '', + setError: () => {} } const StateContext = createContext(initialState) @@ -54,6 +58,7 @@ export const StateProvider = ({ children }: { children: ReactNode }) => { homeWeb3: homeNetwork.web3, foreignWeb3: foreignNetwork.web3 }) + const [error, setError] = useState('') const value = { home: { @@ -68,7 +73,9 @@ export const StateProvider = ({ children }: { children: ReactNode }) => { bridgeContract: foreignBridge, ...foreignNetwork }, - loading: homeNetwork.loading || foreignNetwork.loading + loading: homeNetwork.loading || foreignNetwork.loading, + error, + setError } return {children} diff --git a/alm/src/utils/__tests__/getConfirmationsForTx.test.ts b/alm/src/utils/__tests__/getConfirmationsForTx.test.ts index 7667f25af..adbbe8d65 100644 --- a/alm/src/utils/__tests__/getConfirmationsForTx.test.ts +++ b/alm/src/utils/__tests__/getConfirmationsForTx.test.ts @@ -9,7 +9,7 @@ import { BasicConfirmationParam } from '../../hooks/useMessageConfirmations' jest.mock('../validatorConfirmationHelpers') -const getValidatorSuccessTransaction = helpers.getValidatorSuccessTransaction as jest.Mock +const getSuccessExecutionTransaction = helpers.getSuccessExecutionTransaction as jest.Mock const getValidatorConfirmation = helpers.getValidatorConfirmation as jest.Mock const getValidatorFailedTransaction = helpers.getValidatorFailedTransaction as jest.Mock const getValidatorPendingTransaction = helpers.getValidatorPendingTransaction as jest.Mock @@ -24,8 +24,15 @@ const validator1 = '0x45b96809336A8b714BFbdAB3E4B5e0fe5d839908' const validator2 = '0xAe8bFfc8BBc6AAa9E21ED1E4e4957fe798BEA25f' const validator3 = '0x285A6eB779be4db94dA65e2F3518B1c5F0f71244' const validatorList = [validator1, validator2, validator3] -const bridgeContract = {} as Contract -const confirmationContractMethod = () => {} +const signature = + '0x519d704bceed17423daa79c20531cc34fc27a4be6e53fc5069a8023019188ca4519d704bceed17423daa79c20531cc34fc27a4be6e53fc5069a8023019188ca4' +const bridgeContract = { + methods: { + signature: () => ({ + call: () => signature + }) + } +} as Contract const requiredSignatures = 2 const waitingBlocksResolved = true let subscriptions: Array = [] @@ -42,7 +49,7 @@ const unsubscribe = () => { beforeEach(() => { // Clear all instances and calls to constructor and all methods: - getValidatorSuccessTransaction.mockClear() + getSuccessExecutionTransaction.mockClear() getValidatorConfirmation.mockClear() getValidatorFailedTransaction.mockClear() getValidatorPendingTransaction.mockClear() @@ -54,7 +61,7 @@ describe('getConfirmationsForTx', () => { validator, status: validator !== validator3 ? VALIDATOR_CONFIRMATION_STATUS.SUCCESS : VALIDATOR_CONFIRMATION_STATUS.UNDEFINED })) - getValidatorSuccessTransaction.mockImplementation(() => async (validatorData: BasicConfirmationParam) => ({ + getSuccessExecutionTransaction.mockImplementation(() => async (validatorData: BasicConfirmationParam) => ({ validator: validatorData.validator, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS, txHash: '', @@ -83,7 +90,7 @@ describe('getConfirmationsForTx', () => { web3, validatorList, bridgeContract, - confirmationContractMethod, + true, setResult, requiredSignatures, setSignatureCollected, @@ -102,9 +109,9 @@ describe('getConfirmationsForTx', () => { expect(subscriptions.length).toEqual(1) expect(setResult).toBeCalledTimes(2) expect(getValidatorConfirmation).toBeCalledTimes(1) - expect(getValidatorSuccessTransaction).toBeCalledTimes(1) + expect(getSuccessExecutionTransaction).toBeCalledTimes(1) expect(setSignatureCollected).toBeCalledTimes(1) - expect(setSignatureCollected.mock.calls[0][0]).toEqual(true) + expect(setSignatureCollected.mock.calls[0][0]).toEqual([signature, signature]) expect(getValidatorFailedTransaction).toBeCalledTimes(1) expect(setFailedConfirmations).toBeCalledTimes(1) @@ -134,7 +141,7 @@ describe('getConfirmationsForTx', () => { validator, status: validator === validator3 ? VALIDATOR_CONFIRMATION_STATUS.SUCCESS : VALIDATOR_CONFIRMATION_STATUS.UNDEFINED })) - getValidatorSuccessTransaction.mockImplementation(() => async (validatorData: BasicConfirmationParam) => ({ + getSuccessExecutionTransaction.mockImplementation(() => async (validatorData: BasicConfirmationParam) => ({ validator: validatorData.validator, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS, txHash: '', @@ -163,7 +170,7 @@ describe('getConfirmationsForTx', () => { web3, validatorList, bridgeContract, - confirmationContractMethod, + true, setResult, requiredSignatures, setSignatureCollected, @@ -181,7 +188,7 @@ describe('getConfirmationsForTx', () => { expect(setResult).toBeCalledTimes(2) expect(getValidatorConfirmation).toBeCalledTimes(1) - expect(getValidatorSuccessTransaction).toBeCalledTimes(1) + expect(getSuccessExecutionTransaction).toBeCalledTimes(1) expect(setSignatureCollected).toBeCalledTimes(1) expect(setSignatureCollected.mock.calls[0][0]).toEqual(false) @@ -198,7 +205,7 @@ describe('getConfirmationsForTx', () => { validator, status: validator !== validator3 ? VALIDATOR_CONFIRMATION_STATUS.SUCCESS : VALIDATOR_CONFIRMATION_STATUS.UNDEFINED })) - getValidatorSuccessTransaction.mockImplementation(() => async (validatorData: BasicConfirmationParam) => ({ + getSuccessExecutionTransaction.mockImplementation(() => async (validatorData: BasicConfirmationParam) => ({ validator: validatorData.validator, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS, txHash: validatorData.validator !== validator3 ? '0x123' : '', @@ -227,7 +234,7 @@ describe('getConfirmationsForTx', () => { web3, validatorList, bridgeContract, - confirmationContractMethod, + true, setResult, requiredSignatures, setSignatureCollected, @@ -246,9 +253,9 @@ describe('getConfirmationsForTx', () => { expect(subscriptions.length).toEqual(0) expect(setResult).toBeCalledTimes(2) expect(getValidatorConfirmation).toBeCalledTimes(1) - expect(getValidatorSuccessTransaction).toBeCalledTimes(1) + expect(getSuccessExecutionTransaction).toBeCalledTimes(1) expect(setSignatureCollected).toBeCalledTimes(1) - expect(setSignatureCollected.mock.calls[0][0]).toEqual(true) + expect(setSignatureCollected.mock.calls[0][0]).toEqual([signature, signature]) expect(getValidatorFailedTransaction).toBeCalledTimes(1) expect(setFailedConfirmations).toBeCalledTimes(1) @@ -283,7 +290,7 @@ describe('getConfirmationsForTx', () => { ? VALIDATOR_CONFIRMATION_STATUS.SUCCESS : VALIDATOR_CONFIRMATION_STATUS.UNDEFINED })) - getValidatorSuccessTransaction.mockImplementation(() => async (validatorData: BasicConfirmationParam) => ({ + getSuccessExecutionTransaction.mockImplementation(() => async (validatorData: BasicConfirmationParam) => ({ validator: validatorData.validator, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS, txHash: validatorData.validator !== validator3 && validatorData.validator !== validator4 ? '0x123' : '', @@ -315,7 +322,7 @@ describe('getConfirmationsForTx', () => { web3, validatorList, bridgeContract, - confirmationContractMethod, + true, setResult, requiredSignatures, setSignatureCollected, @@ -334,9 +341,9 @@ describe('getConfirmationsForTx', () => { expect(subscriptions.length).toEqual(0) expect(setResult).toBeCalledTimes(2) expect(getValidatorConfirmation).toBeCalledTimes(1) - expect(getValidatorSuccessTransaction).toBeCalledTimes(1) + expect(getSuccessExecutionTransaction).toBeCalledTimes(1) expect(setSignatureCollected).toBeCalledTimes(1) - expect(setSignatureCollected.mock.calls[0][0]).toEqual(true) + expect(setSignatureCollected.mock.calls[0][0]).toEqual([signature, signature]) expect(getValidatorFailedTransaction).toBeCalledTimes(1) expect(setFailedConfirmations).toBeCalledTimes(1) @@ -372,7 +379,7 @@ describe('getConfirmationsForTx', () => { validator, status: validator === validator1 ? VALIDATOR_CONFIRMATION_STATUS.SUCCESS : VALIDATOR_CONFIRMATION_STATUS.UNDEFINED })) - getValidatorSuccessTransaction.mockImplementation(() => async (validatorData: BasicConfirmationParam) => ({ + getSuccessExecutionTransaction.mockImplementation(() => async (validatorData: BasicConfirmationParam) => ({ validator: validatorData.validator, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS, txHash: validatorData.validator === validator1 ? '0x123' : '', @@ -407,7 +414,7 @@ describe('getConfirmationsForTx', () => { web3, validatorList, bridgeContract, - confirmationContractMethod, + true, setResult, requiredSignatures, setSignatureCollected, @@ -425,7 +432,7 @@ describe('getConfirmationsForTx', () => { expect(setResult).toBeCalledTimes(2) expect(getValidatorConfirmation).toBeCalledTimes(1) - expect(getValidatorSuccessTransaction).toBeCalledTimes(1) + expect(getSuccessExecutionTransaction).toBeCalledTimes(1) expect(setSignatureCollected).toBeCalledTimes(1) expect(setSignatureCollected.mock.calls[0][0]).toEqual(false) @@ -461,7 +468,7 @@ describe('getConfirmationsForTx', () => { validator, status: validator === validator1 ? VALIDATOR_CONFIRMATION_STATUS.SUCCESS : VALIDATOR_CONFIRMATION_STATUS.UNDEFINED })) - getValidatorSuccessTransaction.mockImplementation(() => async (validatorData: BasicConfirmationParam) => ({ + getSuccessExecutionTransaction.mockImplementation(() => async (validatorData: BasicConfirmationParam) => ({ validator: validatorData.validator, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS, txHash: validatorData.validator === validator1 ? '0x123' : '', @@ -493,7 +500,7 @@ describe('getConfirmationsForTx', () => { web3, validatorList, bridgeContract, - confirmationContractMethod, + true, setResult, requiredSignatures, setSignatureCollected, @@ -512,7 +519,7 @@ describe('getConfirmationsForTx', () => { expect(subscriptions.length).toEqual(0) expect(setResult).toBeCalledTimes(2) expect(getValidatorConfirmation).toBeCalledTimes(1) - expect(getValidatorSuccessTransaction).toBeCalledTimes(1) + expect(getSuccessExecutionTransaction).toBeCalledTimes(1) expect(setSignatureCollected).toBeCalledTimes(1) expect(setSignatureCollected.mock.calls[0][0]).toEqual(false) @@ -555,7 +562,7 @@ describe('getConfirmationsForTx', () => { status: validator !== validator2 ? VALIDATOR_CONFIRMATION_STATUS.SUCCESS : VALIDATOR_CONFIRMATION_STATUS.UNDEFINED })) - getValidatorSuccessTransaction + getSuccessExecutionTransaction .mockImplementationOnce(() => async (validatorData: BasicConfirmationParam) => ({ validator: validatorData.validator, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS, @@ -604,7 +611,7 @@ describe('getConfirmationsForTx', () => { web3, validatorList, bridgeContract, - confirmationContractMethod, + true, setResult, requiredSignatures, setSignatureCollected, @@ -622,7 +629,7 @@ describe('getConfirmationsForTx', () => { expect(setResult).toBeCalledTimes(2) expect(getValidatorConfirmation).toBeCalledTimes(1) - expect(getValidatorSuccessTransaction).toBeCalledTimes(1) + expect(getSuccessExecutionTransaction).toBeCalledTimes(1) expect(setSignatureCollected).toBeCalledTimes(1) expect(setSignatureCollected.mock.calls[0][0]).toEqual(false) @@ -654,7 +661,7 @@ describe('getConfirmationsForTx', () => { web3, validatorList, bridgeContract, - confirmationContractMethod, + true, setResult, requiredSignatures, setSignatureCollected, @@ -672,10 +679,10 @@ describe('getConfirmationsForTx', () => { expect(setResult).toBeCalledTimes(4) expect(getValidatorConfirmation).toBeCalledTimes(2) - expect(getValidatorSuccessTransaction).toBeCalledTimes(2) + expect(getSuccessExecutionTransaction).toBeCalledTimes(2) expect(setSignatureCollected).toBeCalledTimes(2) expect(setSignatureCollected.mock.calls[0][0]).toEqual(false) - expect(setSignatureCollected.mock.calls[1][0]).toEqual(true) + expect(setSignatureCollected.mock.calls[1][0]).toEqual([signature, signature]) expect(getValidatorFailedTransaction).toBeCalledTimes(2) expect(setFailedConfirmations).toBeCalledTimes(2) diff --git a/alm/src/utils/__tests__/getFinalizationEvent.test.ts b/alm/src/utils/__tests__/getFinalizationEvent.test.ts index 506533ed3..f6ce8ff1e 100644 --- a/alm/src/utils/__tests__/getFinalizationEvent.test.ts +++ b/alm/src/utils/__tests__/getFinalizationEvent.test.ts @@ -61,6 +61,7 @@ describe('getFinalizationEvent', () => { const setFailedExecution = jest.fn() const getPendingExecution = jest.fn() const setPendingExecution = jest.fn() + const setExecutionEventsFetched = jest.fn() await getFinalizationEvent( contract, @@ -76,7 +77,8 @@ describe('getFinalizationEvent', () => { getFailedExecution, setFailedExecution, getPendingExecution, - setPendingExecution + setPendingExecution, + setExecutionEventsFetched ) unsubscribe() @@ -110,6 +112,7 @@ describe('getFinalizationEvent', () => { const setFailedExecution = jest.fn() const getPendingExecution = jest.fn() const setPendingExecution = jest.fn() + const setExecutionEventsFetched = jest.fn() await getFinalizationEvent( contract, @@ -125,7 +128,8 @@ describe('getFinalizationEvent', () => { getFailedExecution, setFailedExecution, getPendingExecution, - setPendingExecution + setPendingExecution, + setExecutionEventsFetched ) unsubscribe() @@ -159,6 +163,7 @@ describe('getFinalizationEvent', () => { const setFailedExecution = jest.fn() const getPendingExecution = jest.fn().mockResolvedValue([]) const setPendingExecution = jest.fn() + const setExecutionEventsFetched = jest.fn() await getFinalizationEvent( contract, @@ -174,7 +179,8 @@ describe('getFinalizationEvent', () => { getFailedExecution, setFailedExecution, getPendingExecution, - setPendingExecution + setPendingExecution, + setExecutionEventsFetched ) unsubscribe() @@ -208,6 +214,7 @@ describe('getFinalizationEvent', () => { const setFailedExecution = jest.fn() const getPendingExecution = jest.fn().mockResolvedValue([{ hash: txHash }]) const setPendingExecution = jest.fn() + const setExecutionEventsFetched = jest.fn() await getFinalizationEvent( contract, @@ -223,7 +230,8 @@ describe('getFinalizationEvent', () => { getFailedExecution, setFailedExecution, getPendingExecution, - setPendingExecution + setPendingExecution, + setExecutionEventsFetched ) unsubscribe() @@ -264,6 +272,7 @@ describe('getFinalizationEvent', () => { const setFailedExecution = jest.fn() const getPendingExecution = jest.fn().mockResolvedValue([]) const setPendingExecution = jest.fn() + const setExecutionEventsFetched = jest.fn() await getFinalizationEvent( contract, @@ -279,7 +288,8 @@ describe('getFinalizationEvent', () => { getFailedExecution, setFailedExecution, getPendingExecution, - setPendingExecution + setPendingExecution, + setExecutionEventsFetched ) unsubscribe() diff --git a/alm/src/utils/executionWaitingForBlocks.ts b/alm/src/utils/executionWaitingForBlocks.ts index 0ba40e4ee..08ac77230 100644 --- a/alm/src/utils/executionWaitingForBlocks.ts +++ b/alm/src/utils/executionWaitingForBlocks.ts @@ -15,13 +15,19 @@ export const checkWaitingBlocksForExecution = async ( const currentBlock = blockProvider.get() if (currentBlock && currentBlock >= targetBlock) { - setExecutionData({ + const undefinedExecutionState = { status: VALIDATOR_CONFIRMATION_STATUS.UNDEFINED, validator: collectedSignaturesEvent.returnValues.authorityResponsibleForRelay, txHash: '', timestamp: 0, executionResult: false - }) + } + setExecutionData( + (data: any) => + data.status === VALIDATOR_CONFIRMATION_STATUS.UNDEFINED || data.status === VALIDATOR_CONFIRMATION_STATUS.WAITING + ? undefinedExecutionState + : data + ) setWaitingBlocksForExecutionResolved(true) setWaitingBlocksForExecution(false) blockProvider.stop() @@ -31,13 +37,20 @@ export const checkWaitingBlocksForExecution = async ( nextInterval = 500 } else { setWaitingBlocksForExecution(true) - setExecutionData({ + const waitingExecutionState = { status: VALIDATOR_CONFIRMATION_STATUS.WAITING, validator: collectedSignaturesEvent.returnValues.authorityResponsibleForRelay, txHash: '', timestamp: 0, executionResult: false - }) + } + setExecutionData( + (data: any) => + data.status === VALIDATOR_CONFIRMATION_STATUS.UNDEFINED || + data.status === VALIDATOR_CONFIRMATION_STATUS.WAITING + ? waitingExecutionState + : data + ) } const timeoutId = setTimeout( () => diff --git a/alm/src/utils/getConfirmationsForTx.ts b/alm/src/utils/getConfirmationsForTx.ts index c077912ee..04492df7e 100644 --- a/alm/src/utils/getConfirmationsForTx.ts +++ b/alm/src/utils/getConfirmationsForTx.ts @@ -7,11 +7,12 @@ import { APIPendingTransaction, GetPendingTransactionParams } from './explorer' +import { getAffirmationsSigned, getMessagesSigned } from './contract' import { getValidatorConfirmation, getValidatorFailedTransaction, getValidatorPendingTransaction, - getValidatorSuccessTransaction + getSuccessExecutionTransaction } from './validatorConfirmationHelpers' import { ConfirmationParam } from '../hooks/useMessageConfirmations' @@ -20,7 +21,7 @@ export const getConfirmationsForTx = async ( web3: Maybe, validatorList: string[], bridgeContract: Maybe, - confirmationContractMethod: Function, + fromHome: boolean, setResult: Function, requiredSignatures: number, setSignatureCollected: Function, @@ -35,6 +36,8 @@ export const getConfirmationsForTx = async ( ) => { if (!web3 || !validatorList || !validatorList.length || !bridgeContract || !waitingBlocksResolved) return + const confirmationContractMethod = fromHome ? getMessagesSigned : getAffirmationsSigned + // If all the information was not collected, then it should retry let shouldRetry = false const hashMsg = web3.utils.soliditySha3Raw(messageData) @@ -110,7 +113,7 @@ export const getConfirmationsForTx = async ( shouldRetry = true } - let signatureCollectedResult = false + let signatureCollectedResult: boolean | string[] = false if (successConfirmations.length === requiredSignatures) { // If signatures collected, it should set other signatures not found as not required const notRequiredConfirmations = missingConfirmations.map(c => ({ @@ -123,13 +126,21 @@ export const getConfirmationsForTx = async ( validatorConfirmations[index] = validatorData }) signatureCollectedResult = true + + if (fromHome) { + signatureCollectedResult = await Promise.all( + Array.from(Array(requiredSignatures).keys()).map(i => bridgeContract.methods.signature(hashMsg, i).call()) + ) + } } // get transactions from success signatures const successConfirmationWithData = await Promise.all( validatorConfirmations .filter(c => c.status === VALIDATOR_CONFIRMATION_STATUS.SUCCESS) - .map(getValidatorSuccessTransaction(bridgeContract, messageData, timestamp, getSuccessTransactions)) + .map( + getSuccessExecutionTransaction(web3, bridgeContract, fromHome, messageData, timestamp, getSuccessTransactions) + ) ) const successConfirmationWithTxFound = successConfirmationWithData.filter(v => v.txHash !== '') @@ -162,7 +173,7 @@ export const getConfirmationsForTx = async ( web3, validatorList, bridgeContract, - confirmationContractMethod, + fromHome, setResult, requiredSignatures, setSignatureCollected, diff --git a/alm/src/utils/getFinalizationEvent.ts b/alm/src/utils/getFinalizationEvent.ts index 72bca3e9e..8f383a087 100644 --- a/alm/src/utils/getFinalizationEvent.ts +++ b/alm/src/utils/getFinalizationEvent.ts @@ -25,7 +25,8 @@ export const getFinalizationEvent = async ( getFailedExecution: (args: GetFailedTransactionParams) => Promise, setFailedExecution: Function, getPendingExecution: (args: GetPendingTransactionParams) => Promise, - setPendingExecution: Function + setPendingExecution: Function, + setExecutionEventsFetched: Function ) => { if (!contract || !web3 || !waitingBlocksResolved) return // Since it filters by the message id, only one event will be fetched @@ -55,6 +56,7 @@ export const getFinalizationEvent = async ( executionResult: event.returnValues.status }) } else { + setExecutionEventsFetched(true) // If event is defined, it means it is a message from Home to Foreign if (collectedSignaturesEvent) { const validator = collectedSignaturesEvent.returnValues.authorityResponsibleForRelay @@ -128,7 +130,8 @@ export const getFinalizationEvent = async ( getFailedExecution, setFailedExecution, getPendingExecution, - setPendingExecution + setPendingExecution, + setExecutionEventsFetched ), interval ) diff --git a/alm/src/utils/signatures.ts b/alm/src/utils/signatures.ts new file mode 100644 index 000000000..7d963e787 --- /dev/null +++ b/alm/src/utils/signatures.ts @@ -0,0 +1,26 @@ +import Web3 from 'web3' + +function strip0x(s: string) { + return Web3.utils.isHexStrict(s) ? s.substr(2) : s +} + +export interface Signature { + v: string + r: string + s: string +} + +export function signatureToVRS(rawSignature: string): Signature { + const signature = strip0x(rawSignature) + const v = signature.substr(64 * 2) + const r = signature.substr(0, 32 * 2) + const s = signature.substr(32 * 2, 32 * 2) + return { v, r, s } +} + +export function packSignatures(array: Array): string { + const length = strip0x(Web3.utils.toHex(array.length)) + const msgLength = length.length === 1 ? `0${length}` : length + const [v, r, s] = array.reduce(([vs, rs, ss], { v, r, s }) => [vs + v, rs + r, ss + s], ['', '', '']) + return `0x${msgLength}${v}${r}${s}` +} diff --git a/alm/src/utils/validatorConfirmationHelpers.ts b/alm/src/utils/validatorConfirmationHelpers.ts index 0b5c65e61..4ac872c76 100644 --- a/alm/src/utils/validatorConfirmationHelpers.ts +++ b/alm/src/utils/validatorConfirmationHelpers.ts @@ -45,8 +45,10 @@ export const getValidatorConfirmation = ( } } -export const getValidatorSuccessTransaction = ( +export const getSuccessExecutionTransaction = ( + web3: Web3, bridgeContract: Contract, + fromHome: boolean, messageData: string, timestamp: number, getSuccessTransactions: (args: GetFailedTransactionParams) => Promise diff --git a/commons/message.js b/commons/message.js index 1afb41171..f1444fc5c 100644 --- a/commons/message.js +++ b/commons/message.js @@ -2,10 +2,6 @@ function strip0x(input) { return input.replace(/^0x/, '') } -function addTxHashToData({ encodedData, transactionHash }) { - return encodedData.slice(0, 2) + strip0x(transactionHash) + encodedData.slice(2) -} - /** * Decodes the datatype byte from the AMB message. * First (the most significant bit) denotes if the message should be forwarded to the manual lane. @@ -33,8 +29,18 @@ function parseAMBMessage(message) { } } +const normalizeAMBMessageEvent = e => { + let msgData = e.returnValues.encodedData + if (!e.returnValues.messageId) { + // append tx hash to an old message, where message id was not used + // for old messages, e.messageId is a corresponding transactionHash + msgData = e.transactionHash + msgData.slice(2) + } + return parseAMBMessage(msgData) +} + module.exports = { - addTxHashToData, + strip0x, parseAMBMessage, - strip0x + normalizeAMBMessageEvent } diff --git a/commons/test/message.test.js b/commons/test/message.test.js index 1d446b9c1..22a140339 100644 --- a/commons/test/message.test.js +++ b/commons/test/message.test.js @@ -1,6 +1,6 @@ const { BN } = require('web3-utils') const { expect } = require('chai').use(require('bn-chai')(BN)) -const { parseAMBMessage, strip0x, addTxHashToData } = require('../message') +const { parseAMBMessage, strip0x } = require('../message') describe('strip0x', () => { it('should remove 0x from input', () => { @@ -24,28 +24,6 @@ describe('strip0x', () => { expect(result).to.be.equal(input) }) }) -describe('addTxHashToData', () => { - it('should add txHash to encoded data at position 2', () => { - // Given - const msgSender = '0x003667154bb32e42bb9e1e6532f19d187fa0082e' - const msgExecutor = '0xf4bef13f9f4f2b203faf0c3cbbaabe1afe056955' - const msgGasLimit = '000000000000000000000000000000000000000000000000000000005b877705' - const msgDataType = '00' - const msgData = '0xb1591967aed668a4b27645ff40c444892d91bf5951b382995d4d4f6ee3a2ce03' - const encodedData = `0x${strip0x(msgSender)}${strip0x(msgExecutor)}${msgGasLimit}${msgDataType}${strip0x(msgData)}` - - const transactionHash = '0xbdceda9d8c94838aca10c687da1411a07b1390e88239c0638cb9cc264219cc10' - const message = `0x${strip0x(transactionHash)}${strip0x(msgSender)}${strip0x( - msgExecutor - )}${msgGasLimit}${msgDataType}${strip0x(msgData)}` - - // When - const result = addTxHashToData({ encodedData, transactionHash }) - - // Then - expect(result).to.be.equal(message) - }) -}) describe('parseAMBMessage', () => { it('should parse data type 00', () => { const msgSender = '0x003667154bb32e42bb9e1e6532f19d187fa0082e' diff --git a/deployment-e2e/molecule/ultimate-amb-stake-erc-to-erc/molecule.yml b/deployment-e2e/molecule/ultimate-amb-stake-erc-to-erc/molecule.yml index 3992216f4..b6c1b3265 100644 --- a/deployment-e2e/molecule/ultimate-amb-stake-erc-to-erc/molecule.yml +++ b/deployment-e2e/molecule/ultimate-amb-stake-erc-to-erc/molecule.yml @@ -32,8 +32,6 @@ provisioner: inventory: host_vars: oracle-amb-host: - COMMON_HOME_RPC_URL: "http://parity1:8545" - COMMON_FOREIGN_RPC_URL: "http://parity2:8545" ORACLE_VALIDATOR_ADDRESS: "0xaaB52d66283F7A1D5978bcFcB55721ACB467384b" ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9" ui-amb-stake-erc-to-erc-host: diff --git a/deployment-e2e/molecule/ultimate-amb/molecule.yml b/deployment-e2e/molecule/ultimate-amb/molecule.yml index d03304204..c523faf8c 100644 --- a/deployment-e2e/molecule/ultimate-amb/molecule.yml +++ b/deployment-e2e/molecule/ultimate-amb/molecule.yml @@ -21,8 +21,6 @@ provisioner: inventory: host_vars: oracle-amb-host: - COMMON_HOME_RPC_URL: "http://parity1:8545" - COMMON_FOREIGN_RPC_URL: "http://parity2:8545" ORACLE_VALIDATOR_ADDRESS: "0xaaB52d66283F7A1D5978bcFcB55721ACB467384b" ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9" verifier: diff --git a/deployment-e2e/molecule/ultimate-commons/converge.yml b/deployment-e2e/molecule/ultimate-commons/converge.yml index 23630e5ba..560142793 100644 --- a/deployment-e2e/molecule/ultimate-commons/converge.yml +++ b/deployment-e2e/molecule/ultimate-commons/converge.yml @@ -1,5 +1,3 @@ --- -- import_playbook: ../../../deployment/site.yml -# The docker-compose files have to be modified, in order to join the docker containers over network with the parity containers - import_playbook: ./oracle-docker-compose.yml -- import_playbook: ./ui-docker-compose.yml +- import_playbook: ../../../deployment/site.yml diff --git a/deployment-e2e/molecule/ultimate-commons/oracle-add-docker-external-network.yml b/deployment-e2e/molecule/ultimate-commons/oracle-add-docker-external-network.yml deleted file mode 100644 index 77cb562fa..000000000 --- a/deployment-e2e/molecule/ultimate-commons/oracle-add-docker-external-network.yml +++ /dev/null @@ -1,26 +0,0 @@ ---- -- name: Slurp docker compose file - slurp: - src: "/home/poadocker/bridge/oracle/{{ file }}.yml" - register: docker_compose_slurp -- name: Parse docker compose file - set_fact: - docker_compose_parsed: "{{ docker_compose_slurp['content'] | b64decode | from_yaml }}" - -- name: Add the external network used to connect to Parity nodes - set_fact: - docker_compose_parsed: "{{ docker_compose_parsed |combine({'networks': {'ultimate': {'external': 'true'}}}, recursive=True) }}" - -- name: Add all Oracle containers to the network - set_fact: - docker_compose_parsed: "{{ docker_compose_parsed | combine({'services': {item: {'networks': docker_compose_parsed.services[item].networks | union(['ultimate'])}}}, recursive=True) }}" - with_items: "{{ docker_compose_parsed.services }}" - -- name: Expose Redis port to allow connecting from redis-cli - set_fact: - docker_compose_parsed: "{{ docker_compose_parsed | combine({'services': {'redis': {'ports': ['6379:6379']}}}, recursive=True) }}" - -- name: Write updated docker file - copy: - content: "{{ docker_compose_parsed | to_yaml }}" - dest: "/home/poadocker/bridge/oracle/{{ file }}.yml" diff --git a/deployment-e2e/molecule/ultimate-commons/oracle-docker-compose.yml b/deployment-e2e/molecule/ultimate-commons/oracle-docker-compose.yml index e36b57db7..510b6d662 100644 --- a/deployment-e2e/molecule/ultimate-commons/oracle-docker-compose.yml +++ b/deployment-e2e/molecule/ultimate-commons/oracle-docker-compose.yml @@ -1,33 +1,22 @@ --- -- name: Overwrite Oracle the docker-compose +- name: Prepare Oracle for ultimate tests hosts: oracle become: true tasks: - - name: stop the service - shell: service poabridge stop - - - name: ReTag current oracle image - shell: docker tag $(docker images --format '{{ '{{' }}.Repository{{ '}}' }}:{{ '{{' }}.Tag{{ '}}' }}' | grep -m 1 tokenbridge-e2e-oracle) oracle:ultimate-testing + - name: Connect parity to oracle networks + shell: "docker network create {{ item }} && docker network connect {{ item }} parity1 && docker network connect {{ item }} parity2" + with_items: + - oracle_net_db_bridge_request + - oracle_net_db_bridge_collected + - oracle_net_db_bridge_affirmation + - oracle_net_db_bridge_transfer + - oracle_net_db_bridge_senderhome + - oracle_net_db_bridge_senderforeign + - oracle_net_rabbit_bridge_request + - oracle_net_rabbit_bridge_collected + - oracle_net_rabbit_bridge_affirmation + - oracle_net_rabbit_bridge_transfer + - oracle_net_rabbit_bridge_senderhome + - oracle_net_rabbit_bridge_senderforeign delegate_to: 127.0.0.1 become: false - - - name: Replace oracle image - replace: - path: "/home/poadocker/bridge/oracle/{{ item }}.yml" - regexp: 'poanetwork/tokenbridge-oracle:latest' - replace: "oracle:ultimate-testing" - with_items: - - docker-compose - - docker-compose-transfer - - docker-compose-erc-native - - - include_tasks: oracle-add-docker-external-network.yml - with_items: - - docker-compose - - docker-compose-transfer - - docker-compose-erc-native - loop_control: - loop_var: file - - - name: start the service - shell: service poabridge start diff --git a/deployment-e2e/molecule/ultimate-commons/ui-docker-compose.yml b/deployment-e2e/molecule/ultimate-commons/ui-docker-compose.yml deleted file mode 100644 index 452c958d4..000000000 --- a/deployment-e2e/molecule/ultimate-commons/ui-docker-compose.yml +++ /dev/null @@ -1,32 +0,0 @@ ---- -- name: Overwrite UI the docker-compose - hosts: ui - become: true - tasks: - - name: stop the service - shell: service tokenbridge-ui stop - - - name: Slurp docker compose file - slurp: - src: "/home/poadocker/bridge/ui/docker-compose.yml" - register: docker_compose_slurp - - name: Parse docker compose file - set_fact: - docker_compose_parsed: "{{ docker_compose_slurp['content'] | b64decode | from_yaml }}" - - - name: Add the external network used to connect to Parity nodes - set_fact: - docker_compose_parsed: "{{ docker_compose_parsed |combine({'networks': {'ultimate': {'external': 'true'}}}, recursive=True) }}" - - - name: Add all UI containers to the network - set_fact: - docker_compose_parsed: "{{ docker_compose_parsed | combine({'services': {item: {'networks': ['ultimate']}}}, recursive=True) }}" - with_items: "{{ docker_compose_parsed.services }}" - - - name: Write new docker-compose file - copy: - content: "{{ docker_compose_parsed | to_yaml }}" - dest: "/home/poadocker/bridge/ui/docker-compose.yml" - - - name: start the service - shell: service tokenbridge-ui start diff --git a/deployment-e2e/molecule/ultimate-erc-to-erc/molecule.yml b/deployment-e2e/molecule/ultimate-erc-to-erc/molecule.yml index 161a8fd7a..e082e6fe3 100644 --- a/deployment-e2e/molecule/ultimate-erc-to-erc/molecule.yml +++ b/deployment-e2e/molecule/ultimate-erc-to-erc/molecule.yml @@ -32,8 +32,6 @@ provisioner: inventory: host_vars: oracle-erc-to-erc-host: - COMMON_HOME_RPC_URL: "http://parity1:8545" - COMMON_FOREIGN_RPC_URL: "http://parity2:8545" ORACLE_VALIDATOR_ADDRESS: "0xaaB52d66283F7A1D5978bcFcB55721ACB467384b" ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9" ui-erc-to-erc-host: diff --git a/deployment-e2e/molecule/ultimate-erc-to-native/molecule.yml b/deployment-e2e/molecule/ultimate-erc-to-native/molecule.yml index cab9437be..b155c1871 100644 --- a/deployment-e2e/molecule/ultimate-erc-to-native/molecule.yml +++ b/deployment-e2e/molecule/ultimate-erc-to-native/molecule.yml @@ -32,8 +32,6 @@ provisioner: inventory: host_vars: oracle-erc-to-native-host: - COMMON_HOME_RPC_URL: "http://parity1:8545" - COMMON_FOREIGN_RPC_URL: "http://parity2:8545" ORACLE_VALIDATOR_ADDRESS: "0xaaB52d66283F7A1D5978bcFcB55721ACB467384b" ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9" ORACLE_HOME_START_BLOCK: 1 diff --git a/deployment-e2e/molecule/ultimate-native-to-erc/molecule.yml b/deployment-e2e/molecule/ultimate-native-to-erc/molecule.yml index 2bfae2603..2126c88fe 100644 --- a/deployment-e2e/molecule/ultimate-native-to-erc/molecule.yml +++ b/deployment-e2e/molecule/ultimate-native-to-erc/molecule.yml @@ -32,8 +32,6 @@ provisioner: inventory: host_vars: oracle-native-to-erc-host: - COMMON_HOME_RPC_URL: "http://parity1:8545" - COMMON_FOREIGN_RPC_URL: "http://parity2:8545" ORACLE_VALIDATOR_ADDRESS: "0xaaB52d66283F7A1D5978bcFcB55721ACB467384b" ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9" ui-native-to-erc-host: diff --git a/deployment/group_vars/ultimate.yml b/deployment/group_vars/ultimate.yml index 65547f695..c47e68300 100644 --- a/deployment/group_vars/ultimate.yml +++ b/deployment/group_vars/ultimate.yml @@ -5,13 +5,13 @@ ORACLE_ALLOW_HTTP_FOR_RPC: yes ORACLE_LOG_LEVEL: debug ## Home contract -COMMON_HOME_RPC_URL: "https://sokol.poa.network" +COMMON_HOME_RPC_URL: "http://parity1:8545" UI_HOME_NETWORK_DISPLAY_NAME: "POA Sokol" UI_HOME_WITHOUT_EVENTS: false ORACLE_HOME_RPC_POLLING_INTERVAL: 5000 ## Foreign contract -COMMON_FOREIGN_RPC_URL: "https://sokol.poa.network" +COMMON_FOREIGN_RPC_URL: "http://parity2:8545" UI_FOREIGN_NETWORK_DISPLAY_NAME: "Kovan" UI_FOREIGN_WITHOUT_EVENTS: false ORACLE_FOREIGN_RPC_POLLING_INTERVAL: 1000 @@ -52,3 +52,7 @@ MONITOR_FOREIGN_START_BLOCK: 0 MONITOR_VALIDATOR_HOME_TX_LIMIT: 300000 MONITOR_VALIDATOR_FOREIGN_TX_LIMIT: 300000 MONITOR_TX_NUMBER_THRESHOLD: 100 + +# disable building and pulling of docker images from the Docker Hub +skip_pull: true +skip_build: true diff --git a/deployment/roles/monitor/tasks/jumpbox.yml b/deployment/roles/monitor/tasks/jumpbox.yml index 5e230b79f..611031a8c 100644 --- a/deployment/roles/monitor/tasks/jumpbox.yml +++ b/deployment/roles/monitor/tasks/jumpbox.yml @@ -3,3 +3,4 @@ shell: docker-compose pull args: chdir: "{{ bridge_path }}/monitor" + when: skip_pull is undefined diff --git a/deployment/roles/oracle/tasks/jumpbox.yml b/deployment/roles/oracle/tasks/jumpbox.yml index 3d1dcf1cf..81a508438 100644 --- a/deployment/roles/oracle/tasks/jumpbox.yml +++ b/deployment/roles/oracle/tasks/jumpbox.yml @@ -3,3 +3,4 @@ shell: docker-compose pull args: chdir: "{{ bridge_path }}/oracle" + when: skip_pull is undefined diff --git a/deployment/roles/ui/tasks/jumpbox.yml b/deployment/roles/ui/tasks/jumpbox.yml index 947e28a9c..947ba9f25 100644 --- a/deployment/roles/ui/tasks/jumpbox.yml +++ b/deployment/roles/ui/tasks/jumpbox.yml @@ -3,3 +3,4 @@ shell: docker-compose build args: chdir: "{{ bridge_path }}/ui" + when: skip_build is undefined diff --git a/e2e-commons/components-envs/ui-amb-stake-erc20-erc20.env b/e2e-commons/components-envs/ui-amb-stake-erc20-erc20.env index e5bd1765e..2c30a798e 100644 --- a/e2e-commons/components-envs/ui-amb-stake-erc20-erc20.env +++ b/e2e-commons/components-envs/ui-amb-stake-erc20-erc20.env @@ -19,5 +19,5 @@ COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE=standard COMMON_FOREIGN_GAS_PRICE_FALLBACK=5000000000 UI_FOREIGN_GAS_PRICE_UPDATE_INTERVAL=15000 COMMON_FOREIGN_GAS_PRICE_FACTOR=1 -UI_PORT=3000 +UI_PORT=3003 UI_STYLES=stake diff --git a/e2e-commons/components-envs/ui-erc20-native.env b/e2e-commons/components-envs/ui-erc20-native.env index 6ba0ac073..7cbd7c7d6 100644 --- a/e2e-commons/components-envs/ui-erc20-native.env +++ b/e2e-commons/components-envs/ui-erc20-native.env @@ -19,5 +19,5 @@ COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE=standard COMMON_FOREIGN_GAS_PRICE_FALLBACK=5000000000 UI_FOREIGN_GAS_PRICE_UPDATE_INTERVAL=15000 COMMON_FOREIGN_GAS_PRICE_FACTOR=1 -UI_PORT=3000 +UI_PORT=3002 UI_STYLES=core diff --git a/e2e-commons/components-envs/ui-erc20.env b/e2e-commons/components-envs/ui-erc20.env index ca0d11400..ac851a15a 100644 --- a/e2e-commons/components-envs/ui-erc20.env +++ b/e2e-commons/components-envs/ui-erc20.env @@ -19,5 +19,5 @@ COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE=standard COMMON_FOREIGN_GAS_PRICE_FALLBACK=5000000000 UI_FOREIGN_GAS_PRICE_UPDATE_INTERVAL=15000 COMMON_FOREIGN_GAS_PRICE_FACTOR=1 -UI_PORT=3000 +UI_PORT=3001 UI_STYLES=core diff --git a/e2e-commons/docker-compose.yml b/e2e-commons/docker-compose.yml index d6863e2ae..21499f538 100644 --- a/e2e-commons/docker-compose.yml +++ b/e2e-commons/docker-compose.yml @@ -4,12 +4,14 @@ networks: external: true services: parity1: + container_name: parity1 build: ../parity ports: - "8541:8545" networks: - ultimate parity2: + container_name: parity2 build: context: ../parity dockerfile: Dockerfile-foreign diff --git a/e2e-commons/up.sh b/e2e-commons/up.sh index 0bdf21a20..ace0de63b 100755 --- a/e2e-commons/up.sh +++ b/e2e-commons/up.sh @@ -80,9 +80,9 @@ while [ "$1" != "" ]; do docker-compose up -d ui ui-erc20 ui-erc20-native ui-amb-stake-erc20-erc20 docker-compose run -d -p 3000:3000 ui yarn start - docker-compose run -d -p 3001:3000 ui-erc20 yarn start - docker-compose run -d -p 3002:3000 ui-erc20-native yarn start - docker-compose run -d -p 3003:3000 ui-amb-stake-erc20-erc20 yarn start + docker-compose run -d -p 3001:3001 ui-erc20 yarn start + docker-compose run -d -p 3002:3002 ui-erc20-native yarn start + docker-compose run -d -p 3003:3003 ui-amb-stake-erc20-erc20 yarn start fi if [ "$1" == "alm" ]; then diff --git a/monitor/checkWorker3.js b/monitor/checkWorker3.js index fdab50cb2..08ad3dad2 100644 --- a/monitor/checkWorker3.js +++ b/monitor/checkWorker3.js @@ -1,8 +1,10 @@ require('dotenv').config() const logger = require('./logger')('checkWorker3') const stuckTransfers = require('./stuckTransfers') +const detectMediators = require('./detectMediators') const { writeFile, createDir } = require('./utils/file') 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') @@ -20,6 +22,15 @@ async function checkWorker3() { transfers.health = true writeFile(`/responses/${MONITOR_BRIDGE_NAME}/stuckTransfers.json`, transfers) logger.debug('Done') + } else if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) { + createDir(`/responses/${MONITOR_BRIDGE_NAME}`) + logger.debug('calling detectMediators()') + const mediators = await detectMediators(bridgeMode) + mediators.ok = true + mediators.health = true + writeFile(`/responses/${MONITOR_BRIDGE_NAME}/mediators.json`, mediators) + saveCache() + logger.debug('Done') } } catch (e) { logger.error('checkWorker3.js', e) diff --git a/monitor/detectMediators.js b/monitor/detectMediators.js new file mode 100644 index 000000000..8016e12b3 --- /dev/null +++ b/monitor/detectMediators.js @@ -0,0 +1,147 @@ +require('dotenv').config() +const logger = require('./logger')('stuckTransfers.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') + +function countInteractions(requests) { + const stats = {} + requests.forEach(msg => { + if (!stats[msg.sender]) { + stats[msg.sender] = {} + } + if (!stats[msg.sender][msg.executor]) { + stats[msg.sender][msg.executor] = 0 + } + stats[msg.sender][msg.executor] += 1 + }) + return stats +} + +const normalize = event => ({ + ...normalizeAMBMessageEvent(event), + txHash: event.transactionHash, + logIndex: event.transactionLogIndex +}) + +const flat = arrays => Array.prototype.concat.apply([], arrays) + +function findPermanentMediators(homeToForeignC2C, foreignToHomeC2C) { + return flat( + Object.entries(homeToForeignC2C).map(([homeMediator, homeStats]) => + Object.entries(foreignToHomeC2C) + .map(([foreignMediator, foreignStats]) => ({ + homeMediator, + foreignMediator, + homeToForeignRequests: homeStats[foreignMediator], + foreignToHomeRequests: foreignStats[homeMediator] + })) + .filter(stats => stats.homeToForeignRequests && stats.foreignToHomeRequests) + ) + ) +} + +function findFloatingMediators(homeToForeignC2C, foreignToHomeC2C) { + return Object.entries(homeToForeignC2C) + .map(([homeMediator, homeStats]) => { + const noResponses = ([executor]) => !foreignToHomeC2C[executor] || !foreignToHomeC2C[executor][homeMediator] + const executorRequestPairs = Object.entries(homeStats).filter(noResponses) + return { + mediator: homeMediator, + executors: executorRequestPairs.map(pair => pair[0]), + requests: executorRequestPairs.map(pair => pair[1]) + } + }) + .filter(stats => stats.executors.length > 0) +} + +function findRemotelyControlledMediators(statsU2C) { + return Object.entries(statsU2C).map(([user, stats]) => ({ + user, + executors: Object.keys(stats), + requests: Object.values(stats) + })) +} + +function findUnknown(statsA2U) { + return Object.entries(statsA2U).map(([sender, stats]) => ({ + sender, + executors: Object.keys(stats), + requests: Object.values(stats) + })) +} + +async function main(mode) { + const { + homeToForeignRequests, + foreignToHomeRequests, + homeToForeignConfirmations, + foreignToHomeConfirmations + } = await eventsInfo(mode) + const homeToForeign = homeToForeignRequests + .map(normalize) + .map(addExecutionStatus(homeToForeignConfirmations)) + .filter(x => typeof x.status === 'boolean') + const foreignToHome = foreignToHomeRequests + .map(normalize) + .map(addExecutionStatus(foreignToHomeConfirmations)) + .filter(x => typeof x.status === 'boolean') + + for (const event of homeToForeign) { + // AMB contract emits a single UserRequestForSignature event for every home->foreign request. + // If index of such event in logs is not equal to 0x0, then some other events occurred before it, + // meaning that the sender was a contract. + // Alternatively, the sender is a contract, if the message sender is not equal to tx.origin. + event.isSenderAContract = event.logIndex !== '0x0' || (await getHomeTxSender(event.txHash)) !== event.sender + + // Executor is definitely a contract if a message execution failed, since message calls to EOA always succeed. + // Alternatively, the executor is checked to be a contract by looking at its bytecode size. + event.isExecutorAContract = !event.status || (await isForeignContract(event.executor)) + } + for (const event of foreignToHome) { + // AMB contract emits a single UserRequestForAffirmation event for every foreign->home request. + // If index of such event in logs is not equal to 0x0, then some other events occurred before it, + // meaning that the sender was a contract. + // Alternatively, the sender is a contract, if the message sender is not equal to tx.origin. + event.isSenderAContract = event.logIndex !== '0x0' || (await getForeignTxSender(event.txHash)) !== event.sender + + // Executor is definitely a contract if a message execution failed, since message calls to EOA always succeed. + // Alternatively, the executor is checked to be a contract by looking at its bytecode size. + event.isExecutorAContract = !event.status || (await isHomeContract(event.executor)) + } + const C2C = event => event.isSenderAContract && event.isExecutorAContract + const U2C = event => !event.isSenderAContract && event.isExecutorAContract + const A2U = event => !event.isExecutorAContract + + const homeToForeignC2C = countInteractions(homeToForeign.filter(C2C)) + const foreignToHomeC2C = countInteractions(foreignToHome.filter(C2C)) + const homeToForeignU2C = countInteractions(homeToForeign.filter(U2C)) + const foreignToHomeU2C = countInteractions(foreignToHome.filter(U2C)) + const homeToForeignA2U = countInteractions(homeToForeign.filter(A2U)) + const foreignToHomeA2U = countInteractions(foreignToHome.filter(A2U)) + + const permanentMediators = findPermanentMediators(homeToForeignC2C, foreignToHomeC2C) + const floatingMediators = { + home: findFloatingMediators(homeToForeignC2C, foreignToHomeC2C), + foreign: findFloatingMediators(foreignToHomeC2C, homeToForeignC2C) + } + const remotelyControlledMediators = { + home: findRemotelyControlledMediators(homeToForeignU2C), + foreign: findRemotelyControlledMediators(foreignToHomeU2C) + } + const unknown = { + home: findUnknown(homeToForeignA2U), + foreign: findUnknown(foreignToHomeA2U) + } + + logger.debug('Done') + return { + permanentMediators, + floatingMediators, + remotelyControlledMediators, + unknown + } +} +module.exports = main diff --git a/monitor/utils/message.js b/monitor/utils/message.js index fe8406289..fed4c8d53 100644 --- a/monitor/utils/message.js +++ b/monitor/utils/message.js @@ -1,32 +1,33 @@ -const { parseAMBMessage } = require('../../commons') +const { normalizeAMBMessageEvent } = require('../../commons') const { readAccessListFile } = require('./file') const { MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST, MONITOR_HOME_TO_FOREIGN_BLOCK_LIST } = process.env const keyAMB = e => [e.messageId, e.sender, e.executor].join(',').toLowerCase() -const normalizeAMBMessage = e => { - let msgData = e.returnValues.encodedData - if (!e.returnValues.messageId) { - // append tx hash to an old message, where message id was not used - // for old messages, e.messageId is a corresponding transactionHash - msgData = e.transactionHash + msgData.slice(2) - } - return parseAMBMessage(msgData) -} - function deliveredMsgNotProcessed(processedList) { const keys = new Set() processedList.forEach(processedMsg => keys.add(keyAMB(processedMsg.returnValues))) - return deliveredMsg => !keys.has(keyAMB(normalizeAMBMessage(deliveredMsg))) + return deliveredMsg => !keys.has(keyAMB(normalizeAMBMessageEvent(deliveredMsg))) } function processedMsgNotDelivered(deliveredList) { const keys = new Set() - deliveredList.forEach(deliveredMsg => keys.add(keyAMB(normalizeAMBMessage(deliveredMsg)))) + deliveredList.forEach(deliveredMsg => keys.add(keyAMB(normalizeAMBMessageEvent(deliveredMsg)))) return processedMsg => !keys.has(keyAMB(processedMsg.returnValues)) } +function addExecutionStatus(processedList) { + const statuses = {} + processedList.forEach(processedMsg => { + statuses[keyAMB(processedMsg.returnValues)] = processedMsg.returnValues.status + }) + return deliveredMsg => { + deliveredMsg.status = statuses[keyAMB(deliveredMsg)] + return deliveredMsg + } +} + /** * Normalizes the different event objects to facilitate data processing * @param {Object} event @@ -70,23 +71,24 @@ const manuallyProcessedAMBHomeToForeignRequests = () => { if (MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST) { const allowanceList = readAccessListFile(MONITOR_HOME_TO_FOREIGN_ALLOWANCE_LIST) return e => { - const { sender, executor, decodedDataType } = normalizeAMBMessage(e) + const { sender, executor, decodedDataType } = normalizeAMBMessageEvent(e) return (!allowanceList.includes(sender) && !allowanceList.includes(executor)) || decodedDataType.manualLane } } else if (MONITOR_HOME_TO_FOREIGN_BLOCK_LIST) { const blockList = readAccessListFile(MONITOR_HOME_TO_FOREIGN_BLOCK_LIST) return e => { - const { sender, executor, decodedDataType } = normalizeAMBMessage(e) + const { sender, executor, decodedDataType } = normalizeAMBMessageEvent(e) return blockList.includes(sender) || blockList.includes(executor) || decodedDataType.manualLane } } else { - return e => normalizeAMBMessage(e).decodedDataType.manualLane + return e => normalizeAMBMessageEvent(e).decodedDataType.manualLane } } module.exports = { deliveredMsgNotProcessed, processedMsgNotDelivered, + addExecutionStatus, normalizeEventInformation, eventWithoutReference, unclaimedHomeToForeignRequests, diff --git a/monitor/utils/web3Cache.js b/monitor/utils/web3Cache.js index 17fab65a0..b1f6f228f 100644 --- a/monitor/utils/web3Cache.js +++ b/monitor/utils/web3Cache.js @@ -1,6 +1,6 @@ const logger = require('../logger')('web3Cache') const { readCacheFile, writeCacheFile } = require('./file') -const { web3Home } = require('./web3') +const { web3Home, web3Foreign } = require('./web3') const { getPastEvents: commonGetPastEvents } = require('../../commons') const { MONITOR_BRIDGE_NAME, MONITOR_CACHE_EVENTS } = process.env @@ -9,16 +9,49 @@ let isDirty = false const homeTxSendersCacheFile = `./cache/${MONITOR_BRIDGE_NAME}/home/txSenders.json` const cachedHomeTxSenders = readCacheFile(homeTxSendersCacheFile) || {} +const foreignTxSendersCacheFile = `./cache/${MONITOR_BRIDGE_NAME}/foreign/txSenders.json` +const cachedForeignTxSenders = readCacheFile(foreignTxSendersCacheFile) || {} +const homeIsContractCacheFile = `./cache/${MONITOR_BRIDGE_NAME}/home/isContract.json` +const cachedHomeIsContract = readCacheFile(homeIsContractCacheFile) || {} +const foreignIsContractCacheFile = `./cache/${MONITOR_BRIDGE_NAME}/foreign/isContract.json` +const cachedForeignIsContract = readCacheFile(foreignIsContractCacheFile) || {} async function getHomeTxSender(txHash) { if (!cachedHomeTxSenders[txHash]) { - logger.debug(`Fetching sender for tx ${txHash}`) + logger.debug(`Fetching sender for home tx ${txHash}`) cachedHomeTxSenders[txHash] = (await web3Home.eth.getTransaction(txHash)).from.toLowerCase() isDirty = true } return cachedHomeTxSenders[txHash] } +async function getForeignTxSender(txHash) { + if (!cachedForeignTxSenders[txHash]) { + logger.debug(`Fetching sender for foreign tx ${txHash}`) + cachedForeignTxSenders[txHash] = (await web3Foreign.eth.getTransaction(txHash)).from.toLowerCase() + isDirty = true + } + return cachedForeignTxSenders[txHash] +} + +async function isHomeContract(address) { + if (typeof cachedHomeIsContract[address] !== 'boolean') { + logger.debug(`Fetching home contract code size for tx ${address}`) + cachedHomeIsContract[address] = (await web3Home.eth.getCode(address)).length > 2 + isDirty = true + } + return cachedHomeIsContract[address] +} + +async function isForeignContract(address) { + if (typeof cachedForeignIsContract[address] !== 'boolean') { + logger.debug(`Fetching foreign contract code size for tx ${address}`) + cachedForeignIsContract[address] = (await web3Foreign.eth.getCode(address)).length > 2 + isDirty = true + } + return cachedForeignIsContract[address] +} + async function getPastEvents(contract, options) { if (MONITOR_CACHE_EVENTS !== 'true') { return commonGetPastEvents(contract, options) @@ -123,11 +156,16 @@ function saveCache() { if (isDirty) { logger.debug('Saving cache on disk') writeCacheFile(homeTxSendersCacheFile, cachedHomeTxSenders) + writeCacheFile(homeIsContractCacheFile, cachedHomeIsContract) + writeCacheFile(foreignIsContractCacheFile, cachedForeignIsContract) } } module.exports = { getHomeTxSender, + getForeignTxSender, + isHomeContract, + isForeignContract, getPastEvents, saveCache } diff --git a/oracle-e2e/test/amb.js b/oracle-e2e/test/amb.js index 66c73c80c..6ffd5d2eb 100644 --- a/oracle-e2e/test/amb.js +++ b/oracle-e2e/test/amb.js @@ -142,7 +142,7 @@ describe('arbitrary message bridging', () => { console.error(e) }) - await delay(5000) + await delay(10000) const newSignatures = await homeBridge.getPastEvents('SignedForUserRequest', { fromBlock: 0, diff --git a/oracle/config/foreign-sender.config.js b/oracle/config/foreign-sender.config.js index 4234ee06a..aa347c0f8 100644 --- a/oracle/config/foreign-sender.config.js +++ b/oracle/config/foreign-sender.config.js @@ -1,6 +1,6 @@ const baseConfig = require('./base.config') -const { web3Foreign, web3ForeignRedundant } = require('../src/services/web3') +const { web3Foreign, web3ForeignRedundant, web3ForeignFallback } = require('../src/services/web3') module.exports = { ...baseConfig.bridgeConfig, @@ -9,5 +9,6 @@ module.exports = { id: 'foreign', name: 'sender-foreign', web3: web3Foreign, - web3Redundant: web3ForeignRedundant + web3Redundant: web3ForeignRedundant, + web3Fallback: web3ForeignFallback } diff --git a/oracle/config/home-sender.config.js b/oracle/config/home-sender.config.js index 51d9084e4..ee2bd5700 100644 --- a/oracle/config/home-sender.config.js +++ b/oracle/config/home-sender.config.js @@ -1,6 +1,6 @@ const baseConfig = require('./base.config') -const { web3Home, web3HomeRedundant } = require('../src/services/web3') +const { web3Home, web3HomeRedundant, web3HomeFallback } = require('../src/services/web3') module.exports = { ...baseConfig.bridgeConfig, @@ -9,5 +9,6 @@ module.exports = { id: 'home', name: 'sender-home', web3: web3Home, - web3Redundant: web3HomeRedundant + web3Redundant: web3HomeRedundant, + web3Fallback: web3HomeFallback } diff --git a/oracle/src/sender.js b/oracle/src/sender.js index 5eb51af62..172631a54 100644 --- a/oracle/src/sender.js +++ b/oracle/src/sender.js @@ -30,6 +30,8 @@ const config = require(path.join('../config/', process.argv[2])) const web3Instance = config.web3 const web3Redundant = ORACLE_TX_REDUNDANCY === 'true' ? config.web3Redundant : config.web3 +const { web3Fallback } = config + const nonceKey = `${config.id}:nonce` let chainId = 0 @@ -128,7 +130,7 @@ async function main({ msg, ackMsg, nackMsg, channel, scheduleForRetry, scheduleT try { if (isResend) { - const tx = await web3Instance.eth.getTransaction(job.txHash) + const tx = await web3Fallback.eth.getTransaction(job.txHash) if (tx && tx.blockNumber !== null) { logger.debug(`Transaction ${job.txHash} was successfully mined`) diff --git a/oracle/src/services/HttpListProvider.js b/oracle/src/services/HttpListProvider.js index 4ff6a1e05..2b4c253d2 100644 --- a/oracle/src/services/HttpListProvider.js +++ b/oracle/src/services/HttpListProvider.js @@ -1,7 +1,12 @@ const fetch = require('node-fetch') const promiseRetry = require('promise-retry') +const { FALLBACK_RPC_URL_SWITCH_TIMEOUT } = require('../utils/constants') + +// From EIP-1474 and Infura documentation +const JSONRPC_ERROR_CODES = [-32603, -32002, -32005] const defaultOptions = { + name: 'main', requestTimeout: 0, retry: { retries: 0 @@ -27,23 +32,74 @@ function HttpListProvider(urls, options = {}) { this.urls = urls this.options = { ...defaultOptions, ...options } this.currentIndex = 0 + this.lastTimeUsedPrimary = 0 + this.logger = { + debug: () => {}, + info: () => {} + } +} + +HttpListProvider.prototype.setLogger = function(logger) { + this.logger = logger.child({ module: `HttpListProvider:${this.options.name}` }) } HttpListProvider.prototype.send = async function send(payload, callback) { + // if fallback URL is being used for too long, switch back to the primary URL + if (this.currentIndex > 0 && Date.now() - this.lastTimeUsedPrimary > FALLBACK_RPC_URL_SWITCH_TIMEOUT) { + this.logger.info( + { oldURL: this.urls[this.currentIndex], newURL: this.urls[0] }, + 'Switching back to the primary JSON-RPC URL' + ) + this.currentIndex = 0 + } + // save the currentIndex to avoid race condition const { currentIndex } = this try { - const [result, index] = await promiseRetry(retry => { - return trySend(payload, this.urls, currentIndex, this.options).catch(retry) - }, this.options.retry) - this.currentIndex = index + const [result, index] = await promiseRetry( + retry => this.trySend(payload, currentIndex).catch(retry), + this.options.retry + ) + + // if some of URLs failed to respond, current URL index is updated to the first URL that responded + if (currentIndex !== index) { + this.logger.info( + { index, oldURL: this.urls[currentIndex], newURL: this.urls[index] }, + 'Switching to fallback JSON-RPC URL' + ) + this.currentIndex = index + } callback(null, result) } catch (e) { callback(e) } } +HttpListProvider.prototype.trySend = async function(payload, initialIndex) { + const errors = [] + + for (let count = 0; count < this.urls.length; count++) { + const index = (initialIndex + count) % this.urls.length + + // when request is being sent to the primary URL, the corresponding time marker is updated + if (index === 0) { + this.lastTimeUsedPrimary = Date.now() + } + + const url = this.urls[index] + try { + const result = await send(url, payload, this.options) + return [result, index] + } catch (e) { + this.logger.debug({ index, url, method: payload.method, error: e.message }, `JSON-RPC has failed to respond`) + errors.push(e) + } + } + + throw new HttpListProviderError('Request failed for all urls', errors) +} + function send(url, payload, options) { return fetch(url, { headers: { @@ -61,24 +117,15 @@ function send(url, payload, options) { } }) .then(response => response.json()) -} - -async function trySend(payload, urls, initialIndex, options) { - const errors = [] - - let index = initialIndex - for (let count = 0; count < urls.length; count++) { - const url = urls[index] - try { - const result = await send(url, payload, options) - return [result, index] - } catch (e) { - errors.push(e) - } - index = (index + 1) % urls.length - } - - throw new HttpListProviderError('Request failed for all urls', errors) + .then(response => { + if ( + response.error && + (JSONRPC_ERROR_CODES.includes(response.error.code) || response.error.message.includes('ancient block')) + ) { + throw new Error(response.error.message) + } + return response + }) } module.exports = { diff --git a/oracle/src/services/RedundantHttpListProvider.js b/oracle/src/services/RedundantHttpListProvider.js index 89fe8ffa5..929fbd850 100644 --- a/oracle/src/services/RedundantHttpListProvider.js +++ b/oracle/src/services/RedundantHttpListProvider.js @@ -13,7 +13,10 @@ function RedundantHttpListProvider(urls, options = {}) { this.urls = urls this.options = { ...defaultOptions, ...options } - this.currentIndex = 0 +} + +RedundantHttpListProvider.prototype.setLogger = function(logger) { + this.logger = logger.child({ module: `RedundantHttpListProvider:${this.options.name}` }) } RedundantHttpListProvider.prototype.send = async function send(payload, callback) { diff --git a/oracle/src/services/logger.js b/oracle/src/services/logger.js index a8c5d5903..bf5caa4fe 100644 --- a/oracle/src/services/logger.js +++ b/oracle/src/services/logger.js @@ -1,5 +1,13 @@ const pino = require('pino') const path = require('path') +const { + web3Home, + web3Foreign, + web3HomeFallback, + web3ForeignFallback, + web3HomeRedundant, + web3ForeignRedundant +} = require('./web3') const config = process.env.NODE_ENV !== 'test' ? require(path.join('../../config/', process.argv[2])) : {} @@ -15,4 +23,11 @@ const logger = pino({ : {} }) +web3Home.currentProvider.setLogger(logger) +web3Foreign.currentProvider.setLogger(logger) +web3HomeFallback.currentProvider.setLogger(logger) +web3ForeignFallback.currentProvider.setLogger(logger) +web3HomeRedundant.currentProvider.setLogger(logger) +web3ForeignRedundant.currentProvider.setLogger(logger) + module.exports = logger diff --git a/oracle/src/services/web3.js b/oracle/src/services/web3.js index d669cbfda..70b195c66 100644 --- a/oracle/src/services/web3.js +++ b/oracle/src/services/web3.js @@ -41,15 +41,37 @@ const web3Home = new Web3(homeProvider) const foreignProvider = new HttpListProvider(foreignUrls, foreignOptions) const web3Foreign = new Web3(foreignProvider) -const redundantHomeProvider = new RedundantHttpListProvider(homeUrls, homeOptions) -const web3HomeRedundant = new Web3(redundantHomeProvider) +// secondary fallback providers are intended to be used in places where +// it is more likely that RPC calls to the local non-archive nodes can fail +// e.g. for checking status of the old transaction via eth_getTransactionByHash +let web3HomeFallback = web3Home +let web3ForeignFallback = web3Foreign -const redundantForeignProvider = new RedundantHttpListProvider(foreignUrls, foreignOptions) -const web3ForeignRedundant = new Web3(redundantForeignProvider) +// secondary redundant providers are intended to be used in places where +// the result of a single RPC request can be lost +// e.g. for sending transactions eth_sendRawTransaction +let web3HomeRedundant = web3Home +let web3ForeignRedundant = web3Foreign + +if (homeUrls.length > 1) { + const provider = new HttpListProvider(homeUrls, { ...homeOptions, name: 'fallback' }) + web3HomeFallback = new Web3(provider) + const redundantProvider = new RedundantHttpListProvider(homeUrls, { ...homeOptions, name: 'redundant' }) + web3HomeRedundant = new Web3(redundantProvider) +} + +if (foreignUrls.length > 1) { + const provider = new HttpListProvider(foreignUrls, { ...foreignOptions, name: 'fallback' }) + web3ForeignFallback = new Web3(provider) + const redundantProvider = new RedundantHttpListProvider(foreignUrls, { ...foreignOptions, name: 'redundant' }) + web3ForeignRedundant = new Web3(redundantProvider) +} module.exports = { web3Home, web3Foreign, web3HomeRedundant, - web3ForeignRedundant + web3ForeignRedundant, + web3HomeFallback, + web3ForeignFallback } diff --git a/oracle/src/utils/constants.js b/oracle/src/utils/constants.js index f3b5b1777..92a76db83 100644 --- a/oracle/src/utils/constants.js +++ b/oracle/src/utils/constants.js @@ -24,6 +24,7 @@ module.exports = { MAX: 1000 }, TRANSACTION_RESEND_TIMEOUT: 20 * 60 * 1000, + FALLBACK_RPC_URL_SWITCH_TIMEOUT: 60 * 60 * 1000, SENDER_QUEUE_MAX_PRIORITY: 10, SENDER_QUEUE_SEND_PRIORITY: 5, SENDER_QUEUE_CHECK_STATUS_PRIORITY: 1 diff --git a/ui/docker-compose.yml b/ui/docker-compose.yml index e2905cb12..5c2529b31 100644 --- a/ui/docker-compose.yml +++ b/ui/docker-compose.yml @@ -8,7 +8,7 @@ services: ports: - "${UI_PORT}:${UI_PORT}" env_file: ./.env - environment: + environment: - NODE_ENV=production restart: unless-stopped entrypoint: yarn start diff --git a/yarn.lock b/yarn.lock index d44dc750a..f6dc08e64 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,58 +2,65 @@ # yarn lockfile v1 -"@0x/assert@^2.1.6": - version "2.1.6" - resolved "https://registry.yarnpkg.com/@0x/assert/-/assert-2.1.6.tgz#61c5854b555bca1f1f0503754f2fd0169bee0ef1" - integrity sha512-Gu8eBnFdEuIAH2GubWYOSVz/BIoRccKof68AziduYDHxh4nSPM6NUH52xtfUGk4nXljiOXU1XHZJhcjTObI+8Q== +"@0x/assert@^3.0.17": + version "3.0.17" + resolved "https://registry.yarnpkg.com/@0x/assert/-/assert-3.0.17.tgz#dc15d038ed085744cb375044218285368f0cbfa8" + integrity sha512-NlII5893GQ9FZ+Lr+N2bSK3bQyxTBl8JUd7zeNltRPIsGco609bzG4Zat4zhlL3e/zhWY6zmzfaXK6spj4WsdQ== dependencies: - "@0x/json-schemas" "^4.0.2" - "@0x/typescript-typings" "^4.3.0" - "@0x/utils" "^4.5.2" + "@0x/json-schemas" "^5.3.3" + "@0x/typescript-typings" "^5.1.5" + "@0x/utils" "^6.1.0" + "@types/node" "12.12.54" lodash "^4.17.11" valid-url "^1.0.9" -"@0x/dev-utils@^2.3.3": - version "2.3.3" - resolved "https://registry.yarnpkg.com/@0x/dev-utils/-/dev-utils-2.3.3.tgz#9b6df00fea357fa6da02b35ca93fc89d100e1992" - integrity sha512-Pi664W/jj1U6WU+kHEPyKpflBnmKRsclB69RaL7wpnvOOFjAPhFV2/0FvIZ25w62rMzKEpfD1/1NcZ7NjAk7OQ== - dependencies: - "@0x/subproviders" "^5.0.4" - "@0x/types" "^2.4.3" - "@0x/typescript-typings" "^4.3.0" - "@0x/utils" "^4.5.2" - "@0x/web3-wrapper" "^6.0.13" +"@0x/dev-utils@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@0x/dev-utils/-/dev-utils-4.0.2.tgz#04c925c811d30ef7fb11e2b96ede4a0f9b74aab1" + integrity sha512-d1T6rOlpgPFC9fyAayJLTWZFs4xXmVOzemZ2Pvym3JHj/Jpo2LuTnK5sOlRzBFGA0IG40bwy6WQofDVVeWk1bw== + dependencies: + "@0x/subproviders" "^6.2.0" + "@0x/types" "^3.3.0" + "@0x/typescript-typings" "^5.1.5" + "@0x/utils" "^6.1.0" + "@0x/web3-wrapper" "^7.2.8" + "@types/node" "12.12.54" "@types/web3-provider-engine" "^14.0.0" chai "^4.0.1" - ethereum-types "^2.1.6" + chai-as-promised "^7.1.0" + chai-bignumber "^3.0.0" + dirty-chai "^2.0.1" + ethereum-types "^3.3.3" lodash "^4.17.11" + web3-provider-engine "14.0.6" -"@0x/json-schemas@^4.0.2": - version "4.0.2" - resolved "https://registry.yarnpkg.com/@0x/json-schemas/-/json-schemas-4.0.2.tgz#6f7c1dcde04d3acc3e8ca2f24177b9705c10e772" - integrity sha512-JHOwESZeWKAzT5Z42ZNvOvQUQ5vuRIFQWS0FNjYwV8Cv4/dRlLHd7kwxxsvlm9NxgXnOW0ddEDBbVGxhVSYNIg== +"@0x/json-schemas@^5.3.3": + version "5.3.3" + resolved "https://registry.yarnpkg.com/@0x/json-schemas/-/json-schemas-5.3.3.tgz#4b9de100385ca23b0cd58a454165df2e9758e453" + integrity sha512-u2DTXn4KRqOhlJUmFkIAqeUYIUKbYx2E+Hx6t7LhV+eIPrU5FSkk6Hv3UwYASARlMyqaWucBbGMBNCYyiVShGA== dependencies: - "@0x/typescript-typings" "^4.3.0" - "@types/node" "*" + "@0x/typescript-typings" "^5.1.5" + "@types/node" "12.12.54" jsonschema "^1.2.0" lodash.values "^4.3.0" -"@0x/sol-compiler@^3.1.15": - version "3.1.15" - resolved "https://registry.yarnpkg.com/@0x/sol-compiler/-/sol-compiler-3.1.15.tgz#aaaad55008dddd69ad1e3226aa4a2832e0dd13b3" - integrity sha512-IobhcQ/whFRL942/ykKc0fV6/YstHhvnQJ0noUZ9GabMDtaBlW6k5vAerSkXZU/YyOd8sD9nw7QSm295D6HoTA== - dependencies: - "@0x/assert" "^2.1.6" - "@0x/json-schemas" "^4.0.2" - "@0x/sol-resolver" "^2.0.11" - "@0x/types" "^2.4.3" - "@0x/typescript-typings" "^4.3.0" - "@0x/utils" "^4.5.2" - "@0x/web3-wrapper" "^6.0.13" +"@0x/sol-compiler@^4.3.1": + version "4.3.1" + resolved "https://registry.yarnpkg.com/@0x/sol-compiler/-/sol-compiler-4.3.1.tgz#dce7dea760c6032946783c2411dbb57a2c74dcca" + integrity sha512-YXoNkGG17fZKu/SKs/E8eNedTbptORnbMHhyCwt5Ok3xvTDW83GCVkhi+T+ohuzpUBU12kcCbDbUqYxiakLKwQ== + dependencies: + "@0x/assert" "^3.0.17" + "@0x/json-schemas" "^5.3.3" + "@0x/sol-resolver" "^3.1.5" + "@0x/types" "^3.3.0" + "@0x/typescript-typings" "^5.1.5" + "@0x/utils" "^6.1.0" + "@0x/web3-wrapper" "^7.2.8" + "@types/node" "12.12.54" "@types/yargs" "^11.0.0" chalk "^2.3.0" chokidar "^3.0.2" - ethereum-types "^2.1.6" + ethereum-types "^3.3.3" ethereumjs-util "^5.1.1" lodash "^4.17.11" mkdirp "^0.5.1" @@ -65,59 +72,63 @@ web3-eth-abi "^1.0.0-beta.24" yargs "^10.0.3" -"@0x/sol-coverage@^3.0.11": - version "3.0.12" - resolved "https://registry.yarnpkg.com/@0x/sol-coverage/-/sol-coverage-3.0.12.tgz#4ca602495f7bcc4f045854850cd7f20fdf64e984" - integrity sha512-V4Iq8LU8HWNctVCt+gMHKcZ0moiawpna7bd3SWQuiQIig0iNpXBBCQl9SEIwpboTcv4Xhzo4cZuCGsWwKAQSpw== +"@0x/sol-coverage@^4.0.10": + version "4.0.20" + resolved "https://registry.yarnpkg.com/@0x/sol-coverage/-/sol-coverage-4.0.20.tgz#1633ac9331fbc2cb46beb17ada20d3f7ba525c7b" + integrity sha512-VJn/cr1be9jHFGUlJPiZ7MxDGwh6DdmOYKK7+PSbzATW9NcpKuR0uatIcWNrrD3TJfeA2qAdd6bpcqf91/5MgA== dependencies: - "@0x/sol-tracing-utils" "^6.0.19" - "@0x/subproviders" "^5.0.4" - "@0x/typescript-typings" "^4.3.0" + "@0x/sol-tracing-utils" "^7.1.10" + "@0x/subproviders" "^6.2.0" + "@0x/typescript-typings" "^5.1.5" "@types/minimatch" "^3.0.3" - ethereum-types "^2.1.6" + "@types/node" "12.12.54" + ethereum-types "^3.3.3" lodash "^4.17.11" minimatch "^3.0.4" web3-provider-engine "14.0.6" -"@0x/sol-resolver@^2.0.11": - version "2.0.11" - resolved "https://registry.yarnpkg.com/@0x/sol-resolver/-/sol-resolver-2.0.11.tgz#282d545a423baf0d478c498fd3adf607339d5504" - integrity sha512-TGvkuWoEMghPB4OZaPz49OJ/J0cw/I3yV7VLbE/OeN0K/J2P8uOkzhNgWLOVSi8EK3hcJ1JVc0iDSkCnzGj4xQ== +"@0x/sol-resolver@^3.1.5": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@0x/sol-resolver/-/sol-resolver-3.1.5.tgz#f3c94bd6d522f72091f059f60af255d7135e5e6c" + integrity sha512-QO6kGPmwdtOX7LSTHVhYXWKFam2AqGGOg4CJH0AlOF7dTuwc7dDNlmeSymIkoIeOUoFu9nk+IC0s9spL0gAaZg== dependencies: - "@0x/types" "^2.4.3" - "@0x/typescript-typings" "^4.3.0" + "@0x/types" "^3.3.0" + "@0x/typescript-typings" "^5.1.5" + "@types/node" "12.12.54" lodash "^4.17.11" -"@0x/sol-trace@^2.0.19": - version "2.0.20" - resolved "https://registry.yarnpkg.com/@0x/sol-trace/-/sol-trace-2.0.20.tgz#4c14af3f5c30ab50882e9667926ca9533446711d" - integrity sha512-lkw+8l+InqXKoyVFPCxdLA0oZnLLPvmpFm+lIJwEkPjrbwIyhvQbwSwyzPW/1XUWj0wIwWOpq6PSyofWZgt4KA== +"@0x/sol-trace@^3.0.10": + version "3.0.20" + resolved "https://registry.yarnpkg.com/@0x/sol-trace/-/sol-trace-3.0.20.tgz#917fe73f0ace99112591776726db5880dff66ce5" + integrity sha512-wDHJrY5r/xf9YCbjjY4Xdl6Ie0HXzNofI2vVDGq4e9NM6aXcbN2dpsHk2jMhX+lWt0z21atpzFxaD7M9y5B4jA== dependencies: - "@0x/sol-tracing-utils" "^6.0.19" - "@0x/subproviders" "^5.0.4" - "@0x/typescript-typings" "^4.3.0" + "@0x/sol-tracing-utils" "^7.1.10" + "@0x/subproviders" "^6.2.0" + "@0x/typescript-typings" "^5.1.5" + "@types/node" "12.12.54" chalk "^2.3.0" - ethereum-types "^2.1.6" + ethereum-types "^3.3.3" ethereumjs-util "^5.1.1" lodash "^4.17.11" loglevel "^1.6.1" web3-provider-engine "14.0.6" -"@0x/sol-tracing-utils@^6.0.19": - version "6.0.19" - resolved "https://registry.yarnpkg.com/@0x/sol-tracing-utils/-/sol-tracing-utils-6.0.19.tgz#3c119c7e5b6d2bd1c94663985b7641aec85ef625" - integrity sha512-5tQOEo+dUYWiclT7UDy5IRm/EPEwDzCqAY3J8l0ecIsssBk0r2YLKKf/ugWkdwASGeAxiepjYpC+mxcxOT6yDA== - dependencies: - "@0x/dev-utils" "^2.3.3" - "@0x/sol-compiler" "^3.1.15" - "@0x/sol-resolver" "^2.0.11" - "@0x/subproviders" "^5.0.4" - "@0x/typescript-typings" "^4.3.0" - "@0x/utils" "^4.5.2" - "@0x/web3-wrapper" "^6.0.13" +"@0x/sol-tracing-utils@^7.1.10": + version "7.1.10" + resolved "https://registry.yarnpkg.com/@0x/sol-tracing-utils/-/sol-tracing-utils-7.1.10.tgz#2c0604235c924372580f92c5afd403b49fb108f1" + integrity sha512-i/YLYWplzsA5MTrvCsf5GawQsSVMQY2pKlmLqN+IQAWmthd3tj6jzh5AorJzgfc7DVYyC7/8WBJcL8yHRXyrxA== + dependencies: + "@0x/dev-utils" "^4.0.2" + "@0x/sol-compiler" "^4.3.1" + "@0x/sol-resolver" "^3.1.5" + "@0x/subproviders" "^6.2.0" + "@0x/typescript-typings" "^5.1.5" + "@0x/utils" "^6.1.0" + "@0x/web3-wrapper" "^7.2.8" + "@types/node" "12.12.54" "@types/solidity-parser-antlr" "^0.2.3" chalk "^2.3.0" - ethereum-types "^2.1.6" + ethereum-types "^3.3.3" ethereumjs-util "^5.1.1" ethers "~4.0.4" glob "^7.1.2" @@ -130,26 +141,27 @@ solc "^0.5.5" solidity-parser-antlr "^0.4.2" -"@0x/subproviders@^5.0.3", "@0x/subproviders@^5.0.4": - version "5.0.4" - resolved "https://registry.yarnpkg.com/@0x/subproviders/-/subproviders-5.0.4.tgz#e4b165634ef6a50c4bd41baacf0dbd2a9390c2f8" - integrity sha512-1LiGcOXkP5eUOl/0JRqkrqYtCvIL4NJj1GbbLIRq4TvkfqrRbF7zJM2SaayxPo3Z48zVsqk0ZE5+RrNAdK/Rrg== - dependencies: - "@0x/assert" "^2.1.6" - "@0x/types" "^2.4.3" - "@0x/typescript-typings" "^4.3.0" - "@0x/utils" "^4.5.2" - "@0x/web3-wrapper" "^6.0.13" +"@0x/subproviders@^6.1.1", "@0x/subproviders@^6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@0x/subproviders/-/subproviders-6.2.0.tgz#75ad3cb8b835aa0c0e1d2a7e150f955ec6b32658" + integrity sha512-ugux7Lzy4zmoVKlfHcj7/G6dWL3V7jMJmFj0WsmvrEIK/+9R1VyBTrP4IRm7O22ps319ZJvUYDlZc4fjKmQMEw== + dependencies: + "@0x/assert" "^3.0.17" + "@0x/types" "^3.3.0" + "@0x/typescript-typings" "^5.1.5" + "@0x/utils" "^6.1.0" + "@0x/web3-wrapper" "^7.2.8" "@ledgerhq/hw-app-eth" "^4.3.0" "@ledgerhq/hw-transport-u2f" "4.24.0" "@types/hdkey" "^0.7.0" + "@types/node" "12.12.54" "@types/web3-provider-engine" "^14.0.0" bip39 "^2.5.0" bn.js "^4.11.8" - ethereum-types "^2.1.6" + ethereum-types "^3.3.3" ethereumjs-tx "^1.3.5" ethereumjs-util "^5.1.1" - ganache-core "^2.6.0" + ganache-core "^2.10.2" hdkey "^0.7.1" json-rpc-error "2.0.0" lodash "^4.17.11" @@ -158,55 +170,57 @@ optionalDependencies: "@ledgerhq/hw-transport-node-hid" "^4.3.0" -"@0x/types@^2.4.3": - version "2.4.3" - resolved "https://registry.yarnpkg.com/@0x/types/-/types-2.4.3.tgz#ea014889789e9013fdf48ce97b79f2c016e10fb3" - integrity sha512-3z4ca9fb9pyTu9lJhTSll5EuEthkA3tLAayyZixCoCnwi4ok6PJ83PnMMsSxlRY2iXr7QGbrQr6nU64YWk2WjA== +"@0x/types@^3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@0x/types/-/types-3.3.0.tgz#98c5ee91b66c7cc1719cfece6c3e5477c90bf9c5" + integrity sha512-vne28SbgFB/x5yrTqPsSn38IIv8SQWkQ5oZzzq3/d/13kxE64tTNE+UBOd3Jhax6q1w0birF4XW1iiJlz2yPuQ== dependencies: - "@types/node" "*" - bignumber.js "~8.0.2" - ethereum-types "^2.1.6" + "@types/node" "12.12.54" + bignumber.js "~9.0.0" + ethereum-types "^3.3.3" -"@0x/typescript-typings@^4.3.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@0x/typescript-typings/-/typescript-typings-4.3.0.tgz#4813a996ac5101841d1c22f4aa1738ab56168857" - integrity sha512-6IH2JyKyl33+40tJ5rEhaMPTS2mVuRvoNmoXlCd/F0GPYSsDHMGObIXOkx+Qsw5SyCmqNs/3CTLeeCCqiSUdaw== +"@0x/typescript-typings@^5.1.5": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@0x/typescript-typings/-/typescript-typings-5.1.5.tgz#dd0ad20ef42dad9d054886fd1da72839145b5863" + integrity sha512-I55QfQNJPo8tG6j/PsTTgbeaIMbkGs5vdwVVfFkxSE8rXIEh4Qsra3JXke/7EpFZvhoUFngX4qdQyK2kI4V3sw== dependencies: "@types/bn.js" "^4.11.0" + "@types/node" "12.12.54" "@types/react" "*" - bignumber.js "~8.0.2" - ethereum-types "^2.1.6" + bignumber.js "~9.0.0" + ethereum-types "^3.3.3" popper.js "1.14.3" -"@0x/utils@^4.5.2": - version "4.5.2" - resolved "https://registry.yarnpkg.com/@0x/utils/-/utils-4.5.2.tgz#6cc89f2d0dda341e0fb4e76049a35abfb67a4ac5" - integrity sha512-NWfNcvyiOhouk662AWxX0ZVe4ednBZJS9WZT/by3DBCY/WvN7WHMpEy9M5rBCxO+JJndLYeB5eBztDp7W+Ytkw== +"@0x/utils@^6.1.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@0x/utils/-/utils-6.1.0.tgz#df5750927d8e2b82f6709d666e7fcfca0f33f66e" + integrity sha512-Yrp4eonmFPgJcP1Bnl/xiCMEfiLVrYg3WxKJqMN6AmuW9VZeBhSJDqTMv5Et3qhFTBaY5YMWiISRYeJoVdMfDw== dependencies: - "@0x/types" "^2.4.3" - "@0x/typescript-typings" "^4.3.0" - "@types/node" "*" + "@0x/types" "^3.3.0" + "@0x/typescript-typings" "^5.1.5" + "@types/node" "12.12.54" abortcontroller-polyfill "^1.1.9" - bignumber.js "~8.0.2" + bignumber.js "~9.0.0" chalk "^2.3.0" detect-node "2.0.3" - ethereum-types "^2.1.6" + ethereum-types "^3.3.3" ethereumjs-util "^5.1.1" ethers "~4.0.4" isomorphic-fetch "2.2.1" js-sha3 "^0.7.0" lodash "^4.17.11" -"@0x/web3-wrapper@^6.0.13": - version "6.0.13" - resolved "https://registry.yarnpkg.com/@0x/web3-wrapper/-/web3-wrapper-6.0.13.tgz#2e666221bd44ceebe02762028214d4aa41ad7247" - integrity sha512-LQjKBCCNdkJuhcJld+/sy+G0+sJu5qp9VDNNwJGLDxWIJpgoshhUpBPi7vUnZ79UY4SYuNcC4yM9yI61cs7ZiA== - dependencies: - "@0x/assert" "^2.1.6" - "@0x/json-schemas" "^4.0.2" - "@0x/typescript-typings" "^4.3.0" - "@0x/utils" "^4.5.2" - ethereum-types "^2.1.6" +"@0x/web3-wrapper@^7.2.8": + version "7.2.8" + resolved "https://registry.yarnpkg.com/@0x/web3-wrapper/-/web3-wrapper-7.2.8.tgz#7df4c52e358594338f8dbe76b1490a5c4c423633" + integrity sha512-T0HxSm3Kzs+fzCZI7Yk7MAjfp5vi+AMAHBbuXxJfzr3L6SFObSyHy6TPQ9NMNGrrbJi6UIOLPOX8W0P7hm0XtA== + dependencies: + "@0x/assert" "^3.0.17" + "@0x/json-schemas" "^5.3.3" + "@0x/typescript-typings" "^5.1.5" + "@0x/utils" "^6.1.0" + "@types/node" "12.12.54" + ethereum-types "^3.3.3" ethereumjs-util "^5.1.1" ethers "~4.0.4" lodash "^4.17.11" @@ -1391,7 +1405,7 @@ "@ethersproject/bytes" ">=5.0.0-beta.129" js-sha3 "0.5.7" -"@ethersproject/keccak256@^5.0.3": +"@ethersproject/keccak256@^5.0.0-beta.130", "@ethersproject/keccak256@^5.0.3": version "5.0.4" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.0.4.tgz#36ca0a7d1ae2a272da5654cb886776d0c680ef3a" integrity sha512-GNpiOUm9PGUxFNqOxYKDQBM0u68bG9XC9iOulEQ8I0tOx/4qUpgVzvgXL6ugxr0RY554Gz/NQsVqknqPzUcxpQ== @@ -2914,7 +2928,7 @@ dependencies: "@babel/types" "^7.3.0" -"@types/bn.js@^4.11.0", "@types/bn.js@^4.11.3", "@types/bn.js@^4.11.4", "@types/bn.js@^4.11.5": +"@types/bn.js@^4.11.0", "@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": version "4.11.6" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== @@ -3042,12 +3056,17 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.2.tgz#3452a24edf9fea138b48fad4a0a028a683da1e40" integrity sha512-5tabW/i+9mhrfEOUcLDu2xBPsHJ+X5Orqy9FKpale3SjDA17j5AEpYq5vfy3oAeAHGcvANRCO3NV3d2D6q3NiA== +"@types/node@12.12.54": + version "12.12.54" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.54.tgz#a4b58d8df3a4677b6c08bfbc94b7ad7a7a5f82d1" + integrity sha512-ge4xZ3vSBornVYlDnk7yZ0gK6ChHf/CHB7Gl1I0Jhah8DDnEQqBzgohYG4FX4p81TNirSETOiSyn+y1r9/IR6w== + "@types/node@>= 8": version "13.11.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.0.tgz#390ea202539c61c8fa6ba4428b57e05bc36dc47b" integrity sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ== -"@types/node@^10.0.3", "@types/node@^10.12.18", "@types/node@^10.3.2": +"@types/node@^10.0.3", "@types/node@^10.3.2": version "10.17.18" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.18.tgz#ae364d97382aacdebf583fa4e7132af2dfe56a0c" integrity sha512-DQ2hl/Jl3g33KuAUOcMrcAOtsbzb+y/ufakzAdeK9z/H/xsvkpbETZZbPNMIiQuk24f5ZRMCcZIViAwyFIiKmg== @@ -3058,14 +3077,9 @@ integrity sha512-KUyZdkGCnVPuXfsKmDUu2XLui65LZIJ2s0M57noy5e+ixUT2oK33ep7zlvgzI8LElcWqbf8AR+o/3GqAPac2zA== "@types/node@^12.12.6": - version "12.12.69" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.69.tgz#7cb6a3aa0d16664bf2dcd1450ccb8477464fbd79" - integrity sha512-2F2VQRSFmzqgUEXw75L51MgnnZqc6bKWVSUPfrDPzp6mzGGibeVwyQcpvZvBr5RnsoMRHmC8EcBQiobSeqeJxg== - -"@types/node@^12.6.1": - version "12.12.34" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.34.tgz#0a5d6ae5d22612f0cf5f10320e1fc5d2a745dcb8" - integrity sha512-BneGN0J9ke24lBRn44hVHNeDlrXRYF+VRp0HbSUNnEZahXGAysHZIqnf/hER6aabdBgzM4YOV4jrR8gj4Zfi0g== + version "12.12.67" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.67.tgz#4f86badb292e822e3b13730a1f9713ed2377f789" + integrity sha512-R48tgL2izApf+9rYNH+3RBMbRpPeW3N8f0I9HMhggeq4UXwBDqumJ14SDs4ctTMhG11pIOduZ4z3QWGOiMc9Vg== "@types/node@^8.0.0": version "8.10.59" @@ -3361,24 +3375,37 @@ resolved "https://registry.yarnpkg.com/@use-it/interval/-/interval-0.1.3.tgz#5d1096b2295d7a5dda8e8022f3abb5f9d9ef27f8" integrity sha512-chshdtDZTFoWA9aszBz1Cc04Ca9NBD2JTi/GMjdJ+HGm4q7Vy1v71+2mm22r7Kfb2nYW+lTRsPcEHdB/VFVHsQ== -"@web3-js/scrypt-shim@^0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@web3-js/scrypt-shim/-/scrypt-shim-0.1.0.tgz#0bf7529ab6788311d3e07586f7d89107c3bea2cc" - integrity sha512-ZtZeWCc/s0nMcdx/+rZwY1EcuRdemOK9ag21ty9UsHkFxsNb/AaoucUz0iPuyGe0Ku+PFuRmWZG7Z7462p9xPw== +"@web3-react/abstract-connector@^6.0.7": + version "6.0.7" + resolved "https://registry.yarnpkg.com/@web3-react/abstract-connector/-/abstract-connector-6.0.7.tgz#401b3c045f1e0fab04256311be49d5144e9badc6" + integrity sha512-RhQasA4Ox8CxUC0OENc1AJJm8UTybu/oOCM61Zjg6y0iF7Z0sqv1Ai1VdhC33hrQpA8qSBgoXN9PaP8jKmtdqg== dependencies: - scryptsy "^2.1.0" - semver "^6.3.0" + "@web3-react/types" "^6.0.7" -"@web3-js/websocket@^1.0.29": - version "1.0.30" - resolved "https://registry.yarnpkg.com/@web3-js/websocket/-/websocket-1.0.30.tgz#9ea15b7b582cf3bf3e8bc1f4d3d54c0731a87f87" - integrity sha512-fDwrD47MiDrzcJdSeTLF75aCcxVVt8B1N74rA+vh2XCAvFy4tEWJjtnUtj2QG7/zlQ6g9cQ88bZFBxwd9/FmtA== +"@web3-react/core@^6.1.1": + version "6.1.1" + resolved "https://registry.yarnpkg.com/@web3-react/core/-/core-6.1.1.tgz#06c853890723f600b387b738a4b71ef41d5cccb7" + integrity sha512-HKXOgPNCmFvrVsed+aW/HlVhwzs8t3b+nzg3BoxgJQo/5yLiJXSumHRBdUrPxhBQiHkHRZiVPAvzf/8JMnm74Q== dependencies: - debug "^2.2.0" - es5-ext "^0.10.50" - nan "^2.14.0" - typedarray-to-buffer "^3.1.5" - yaeti "^0.0.6" + "@ethersproject/keccak256" "^5.0.0-beta.130" + "@web3-react/abstract-connector" "^6.0.7" + "@web3-react/types" "^6.0.7" + tiny-invariant "^1.0.6" + tiny-warning "^1.0.3" + +"@web3-react/injected-connector@^6.0.7": + version "6.0.7" + resolved "https://registry.yarnpkg.com/@web3-react/injected-connector/-/injected-connector-6.0.7.tgz#1e0be23f51fa07fe6547fe986768a46b74c3a426" + integrity sha512-Y7aJSz6pg+MWKtvdyuqyy6LWuH+4Tqtph1LWfiyVms9II9ar/9B/de4R8wh4wjg91wmHkU+D75yP09E/Soh2RA== + dependencies: + "@web3-react/abstract-connector" "^6.0.7" + "@web3-react/types" "^6.0.7" + tiny-warning "^1.0.3" + +"@web3-react/types@^6.0.7": + version "6.0.7" + resolved "https://registry.yarnpkg.com/@web3-react/types/-/types-6.0.7.tgz#34a6204224467eedc6123abaf55fbb6baeb2809f" + integrity sha512-ofGmfDhxmNT1/P/MgVa8IKSkCStFiyvXe+U5tyZurKdrtTDFU+wJ/LxClPDtFerWpczNFPUSrKcuhfPX1sI6+A== "@webassemblyjs/ast@1.8.5": version "1.8.5" @@ -4979,16 +5006,11 @@ bignumber.js@^9.0.0: resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075" integrity sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A== -bignumber.js@^9.0.1: +bignumber.js@^9.0.1, bignumber.js@~9.0.0: version "9.0.1" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== -bignumber.js@~8.0.2: - version "8.0.2" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-8.0.2.tgz#d8c4e1874359573b1ef03011a2d861214aeef137" - integrity sha512-EiuvFrnbv0jFixEQ9f58jo7X0qI2lNGIr/MxntmVzQc5JUweDSh8y8hbTCAomFtqwUPIOWcLXP0VEOSZTG7FFw== - binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" @@ -5705,13 +5727,18 @@ ccount@^1.0.3: resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.4.tgz#9cf2de494ca84060a2a8d2854edd6dfb0445f386" integrity sha512-fpZ81yYfzentuieinmGnphk0pLkOTMm6MZdVqwd77ROvhko6iujLNGrHH5E7utq3ygWklwfmwuG+A7P+NpqT6w== -chai-as-promised@^7.1.1: +chai-as-promised@^7.1.0, chai-as-promised@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0" integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== dependencies: check-error "^1.0.2" +chai-bignumber@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chai-bignumber/-/chai-bignumber-3.0.0.tgz#e90cf1f468355bbb11a9acd051222586cd2648a9" + integrity sha512-SubOtaSI2AILWTWe2j0c6i2yFT/f9J6UBjeVGDuwDiPLkF/U5+/eTWUE3sbCZ1KgcPF6UJsDVYbIxaYA097MQA== + chai-bn@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/chai-bn/-/chai-bn-0.1.1.tgz#a8904b2dc878e5c094881f327c0029579ff2062b" @@ -6525,17 +6552,6 @@ cosmiconfig@^5.0.0, cosmiconfig@^5.0.7, cosmiconfig@^5.1.0, cosmiconfig@^5.2.0: js-yaml "^3.13.1" parse-json "^4.0.0" -coveralls@^3.0.6: - version "3.1.0" - resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.0.tgz#13c754d5e7a2dd8b44fe5269e21ca394fb4d615b" - integrity sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ== - dependencies: - js-yaml "^3.13.1" - lcov-parse "^1.0.0" - log-driver "^1.2.7" - minimist "^1.2.5" - request "^2.88.2" - create-ecdh@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" @@ -7381,6 +7397,11 @@ dir-to-object@^2.0.0: resolved "https://registry.yarnpkg.com/dir-to-object/-/dir-to-object-2.0.0.tgz#29723e9bd1c3e58e4f307bd04ff634c0370c8f8a" integrity sha512-sXs0JKIhymON7T1UZuO2Ud6VTNAx/VTBXIl4+3mjb2RgfOpt+hectX0x04YqPOPdkeOAKoJuKqwqnXXURNPNEA== +dirty-chai@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/dirty-chai/-/dirty-chai-2.0.1.tgz#6b2162ef17f7943589da840abc96e75bda01aff3" + integrity sha512-ys79pWKvDMowIDEPC6Fig8d5THiC0DJ2gmTeGzVAoEH18J8OzLud0Jh7I9IWg3NSk8x2UocznUuFmfHCXYZx9w== + dns-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" @@ -8444,7 +8465,7 @@ eth-lib@0.2.7: elliptic "^6.4.0" xhr-request-promise "^0.1.2" -eth-lib@0.2.8, eth-lib@^0.2.8: +eth-lib@0.2.8: version "0.2.8" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" integrity sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw== @@ -8545,13 +8566,13 @@ ethereum-cryptography@^0.1.3: secp256k1 "^4.0.1" setimmediate "^1.0.5" -ethereum-types@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/ethereum-types/-/ethereum-types-2.1.6.tgz#57d9d515fad86ab987c0f6962c4203be37da8579" - integrity sha512-xaN5TxLvkdFCGjGfUQ5wV00GHzDHStozP1j+K/YdmUeQXVGiD15cogYPhBVWG3pQJM/aBjtYrpMrjywvKkNC4A== +ethereum-types@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/ethereum-types/-/ethereum-types-3.3.3.tgz#b9328185034ee52efa32176eb6fd9f3e741cb231" + integrity sha512-FWW7ajHqgoqVHhPMX4sY2ycARpPFL8p/64rpToo8awNrJY7rBDnSC8esQYlAPeaiawf9fTM/xAgEm9VKY7J5kg== dependencies: - "@types/node" "*" - bignumber.js "~8.0.2" + "@types/node" "12.12.54" + bignumber.js "~9.0.0" ethereumjs-abi@0.6.5: version "0.6.5" @@ -8826,16 +8847,16 @@ eventemitter3@1.1.1: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.1.1.tgz#47786bdaa087caf7b1b75e73abc5c7d540158cd0" integrity sha1-R3hr2qCHyvext15zq8XH1UAVjNA= -eventemitter3@3.1.2, eventemitter3@^3.0.0, eventemitter3@^3.1.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" - integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q== - -eventemitter3@4.0.4, eventemitter3@^4.0.0: +eventemitter3@4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== +eventemitter3@^3.0.0, eventemitter3@^3.1.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" + integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q== + events@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" @@ -9673,7 +9694,7 @@ ganache-cli@^6.6.0: source-map-support "0.5.12" yargs "13.2.4" -ganache-core@^2.6.0: +ganache-core@^2.10.2: version "2.13.1" resolved "https://registry.yarnpkg.com/ganache-core/-/ganache-core-2.13.1.tgz#bf60399a2dd084e1090db91cbbc7ed3885dc01e4" integrity sha512-Ewg+kNcDqXtOohe7jCcP+ZUv9EMzOx2MoqOYYP3BCfxrDh3KjBXXaKK+Let7li0TghAs9lxmBgevZku35j5YzA== @@ -12523,11 +12544,6 @@ lcid@^2.0.0: dependencies: invert-kv "^2.0.0" -lcov-parse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0" - integrity sha1-6w1GtUER68VhrLTECO+TY73I9+A= - left-pad@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e" @@ -12969,11 +12985,6 @@ lodash@4.17.20: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -log-driver@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" - integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== - loglevel@^1.4.1: version "1.6.1" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" @@ -17179,7 +17190,7 @@ request-promise@^4.2.2: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request@^2.67.0, request@^2.85.0, request@^2.87.0, request@^2.88.0, request@^2.88.2: +request@^2.67.0, request@^2.85.0, request@^2.87.0, request@^2.88.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -17634,11 +17645,6 @@ scryptsy@^1.2.1: dependencies: pbkdf2 "^3.0.3" -scryptsy@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-2.1.0.tgz#8d1e8d0c025b58fdd25b6fa9a0dc905ee8faa790" - integrity sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w== - scss-tokenizer@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" @@ -19175,6 +19181,11 @@ tiny-invariant@^1.0.2: resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.0.4.tgz#346b5415fd93cb696b0c4e8a96697ff590f92463" integrity sha512-lMhRd/djQJ3MoaHEBrw8e2/uM4rs9YMNk0iOr8rHQ0QdbM7D4l0gFl3szKdeixrlyfm9Zqi4dxHCM2qVG8ND5g== +tiny-invariant@^1.0.6: + version "1.1.0" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" + integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw== + tiny-warning@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.2.tgz#1dfae771ee1a04396bdfde27a3adcebc6b648b28" @@ -20127,16 +20138,6 @@ web3-bzz@1.2.11: swarm-js "^0.1.40" underscore "1.9.1" -web3-bzz@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.7.tgz#aa0f3d162f0777a5f35367dc5b70012dd1e129d0" - integrity sha512-iTIWBR+Z+Bn09WprtKm46LmyNOasg2lUn++AjXkBTB8UNxlUybxtza84yl2ETTZUs0zuFzdSSAEgbjhygG+9oA== - dependencies: - "@types/node" "^10.12.18" - got "9.6.0" - swarm-js "^0.1.40" - underscore "1.9.1" - web3-bzz@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.3.0.tgz#83dfd77fa8a64bbb660462dffd0fee2a02ef1051" @@ -20174,15 +20175,6 @@ web3-core-helpers@1.2.11: web3-eth-iban "1.2.11" web3-utils "1.2.11" -web3-core-helpers@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.7.tgz#522f859775ea0d15e7e40359c46d4efc5da92aee" - integrity sha512-bdU++9QATGeCetVrMp8pV97aQtVkN5oLBf/TWu/qumC6jK/YqrvLlBJLdwbz0QveU8zOSap6GCvJbqKvmmbV2A== - dependencies: - underscore "1.9.1" - web3-eth-iban "1.2.7" - web3-utils "1.2.7" - web3-core-helpers@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.3.0.tgz#697cc3246a7eaaaac64ea506828d861c981c3f31" @@ -20226,17 +20218,6 @@ web3-core-method@1.2.11: web3-core-subscriptions "1.2.11" web3-utils "1.2.11" -web3-core-method@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.7.tgz#73fd80d2bf0765ff6efc454db49ac83d1769a45e" - integrity sha512-e1TI0QUnByDMbQ8QHwnjxfjKw0LIgVRY4TYrlPijET9ebqUJU1HCayn/BHIMpV6LKyR1fQj9EldWyT64wZQXkg== - dependencies: - underscore "1.9.1" - web3-core-helpers "1.2.7" - web3-core-promievent "1.2.7" - web3-core-subscriptions "1.2.7" - web3-utils "1.2.7" - web3-core-method@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.3.0.tgz#a71387af842aec7dbad5dbbd1130c14cc6c8beb3" @@ -20272,13 +20253,6 @@ web3-core-promievent@1.2.11: dependencies: eventemitter3 "4.0.4" -web3-core-promievent@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.7.tgz#fc7fa489f4cf76a040800f3dfd4b45c51bd3a39f" - integrity sha512-jNmsM/czCeMGQqKKwM9/HZVTJVIF96hdMVNN/V9TGvp+EEE7vDhB4pUocDnc/QF9Z/5QFBCVmvNWttlRgZmU0A== - dependencies: - eventemitter3 "3.1.2" - web3-core-promievent@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.3.0.tgz#e0442dd0a8989b6bdce09293976cee6d9237a484" @@ -20319,17 +20293,6 @@ web3-core-requestmanager@1.2.11: web3-providers-ipc "1.2.11" web3-providers-ws "1.2.11" -web3-core-requestmanager@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.7.tgz#9da0efce898ead7004d4ac50f748f5131cfe4d79" - integrity sha512-HJb/txjHixu1dxIebiZQKBoJCaNu4gsh7mq/uj6Z/w6tIHbybL90s/7ADyMED353yyJ2tDWtYJqeMVAR+KtdaA== - dependencies: - underscore "1.9.1" - web3-core-helpers "1.2.7" - web3-providers-http "1.2.7" - web3-providers-ipc "1.2.7" - web3-providers-ws "1.2.7" - web3-core-requestmanager@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.3.0.tgz#c5b9a0304504c0e6cce6c90bc1a3bff82732aa1f" @@ -20368,15 +20331,6 @@ web3-core-subscriptions@1.2.11: underscore "1.9.1" web3-core-helpers "1.2.11" -web3-core-subscriptions@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.7.tgz#30c64aede03182832883b17c77e21cbb0933c86e" - integrity sha512-W/CzQYOUawdMDvkgA/fmLsnG5aMpbjrs78LZMbc0MFXLpH3ofqAgO2by4QZrrTShUUTeWS0ZuEkFFL/iFrSObw== - dependencies: - eventemitter3 "3.1.2" - underscore "1.9.1" - web3-core-helpers "1.2.7" - web3-core-subscriptions@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.3.0.tgz#c2622ccd2b84f4687475398ff966b579dba0847e" @@ -20419,19 +20373,6 @@ web3-core@1.2.11: web3-core-requestmanager "1.2.11" web3-utils "1.2.11" -web3-core@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.7.tgz#9248b04331e458c76263d758c51b0cc612953900" - integrity sha512-QA0MTae0gXcr3KHe3cQ4x56+Wh43ZKWfMwg1gfCc3NNxPRM1jJ8qudzyptCAUcxUGXWpDG8syLIn1APDz5J8BQ== - dependencies: - "@types/bn.js" "^4.11.4" - "@types/node" "^12.6.1" - bignumber.js "^9.0.0" - web3-core-helpers "1.2.7" - web3-core-method "1.2.7" - web3-core-requestmanager "1.2.7" - web3-utils "1.2.7" - web3-core@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.3.0.tgz#b818903738461c1cca0163339e1d6d3fa51242cf" @@ -20474,15 +20415,6 @@ web3-eth-abi@1.2.11: underscore "1.9.1" web3-utils "1.2.11" -web3-eth-abi@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.7.tgz#6f3471b578649fddd844a14d397a3dd430fc44a5" - integrity sha512-4FnlT1q+D0XBkxSMXlIb/eG337uQeMaUdtVQ4PZ3XzxqpcoDuMgXm4o+3NRxnWmr4AMm6QKjM+hcC7c0mBKcyg== - dependencies: - ethers "4.0.0-beta.3" - underscore "1.9.1" - web3-utils "1.2.7" - web3-eth-abi@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.3.0.tgz#387b7ea9b38be69ad8856bc7b4e9a6a69bb4d22b" @@ -20550,23 +20482,6 @@ web3-eth-accounts@1.2.11: web3-core-method "1.2.11" web3-utils "1.2.11" -web3-eth-accounts@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.7.tgz#087f55d04a01b815b93151aac2fc1677436b9c59" - integrity sha512-AE7QWi/iIQIjXwlAPtlMabm/OPFF0a1PhxT1EiTckpYNP8fYs6jW7lYxEtJPPJIKqfMjoi1xkEqTVR1YZQ88lg== - dependencies: - "@web3-js/scrypt-shim" "^0.1.0" - crypto-browserify "3.12.0" - eth-lib "^0.2.8" - ethereumjs-common "^1.3.2" - ethereumjs-tx "^2.1.1" - underscore "1.9.1" - uuid "3.3.2" - web3-core "1.2.7" - web3-core-helpers "1.2.7" - web3-core-method "1.2.7" - web3-utils "1.2.7" - web3-eth-accounts@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.3.0.tgz#010acf389b2bee6d5e1aecb2fe78bfa5c8f26c7a" @@ -20627,21 +20542,6 @@ web3-eth-contract@1.2.11: web3-eth-abi "1.2.11" web3-utils "1.2.11" -web3-eth-contract@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.7.tgz#13d7f6003d6221f9a5fd61c2d3b5d039477c9674" - integrity sha512-uW23Y0iL7XroRNbf9fWZ1N6OYhEYTJX8gTuYASuRnpYrISN5QGiQML6pq/NCzqypR1bl5E0fuINZQSK/xefIVw== - dependencies: - "@types/bn.js" "^4.11.4" - underscore "1.9.1" - web3-core "1.2.7" - web3-core-helpers "1.2.7" - web3-core-method "1.2.7" - web3-core-promievent "1.2.7" - web3-core-subscriptions "1.2.7" - web3-eth-abi "1.2.7" - web3-utils "1.2.7" - web3-eth-contract@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.3.0.tgz#c758340ac800788e29fa29edc8b0c0ac957b741c" @@ -20672,20 +20572,6 @@ web3-eth-ens@1.2.11: web3-eth-contract "1.2.11" web3-utils "1.2.11" -web3-eth-ens@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.7.tgz#0bfa7d4b6c7753abbb31a2eb01a364b538f4c860" - integrity sha512-SPRnvUNWQ0CnnTDBteGIJkvFWEizJcAHlVsrFLICwcwFZu+appjX1UOaoGu2h3GXWtc/XZlu7B451Gi+Os2cTg== - dependencies: - eth-ens-namehash "2.0.8" - underscore "1.9.1" - web3-core "1.2.7" - web3-core-helpers "1.2.7" - web3-core-promievent "1.2.7" - web3-eth-abi "1.2.7" - web3-eth-contract "1.2.7" - web3-utils "1.2.7" - web3-eth-ens@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.3.0.tgz#0887ba38473c104cf5fb8a715828b3b354fa02a2" @@ -20725,14 +20611,6 @@ web3-eth-iban@1.2.11: bn.js "^4.11.9" web3-utils "1.2.11" -web3-eth-iban@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.7.tgz#832809c28586be3c667a713b77a2bcba11b7970f" - integrity sha512-2NrClz1PoQ3nSJBd+91ylCOVga9qbTxjRofq/oSCoHVAEvz3WZyttx9k5DC+0rWqwJF1h69ufFvdHAAlmN/4lg== - dependencies: - bn.js "4.11.8" - web3-utils "1.2.7" - web3-eth-iban@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.3.0.tgz#15b782dfaf273ebc4e3f389f1367f4e88ddce4a5" @@ -20775,18 +20653,6 @@ web3-eth-personal@1.2.11: web3-net "1.2.11" web3-utils "1.2.11" -web3-eth-personal@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.7.tgz#322cc2b14c37737b21772a53e4185686a04bf9be" - integrity sha512-2OAa1Spz0uB29dwCM8+1y0So7E47A4gKznjBEwXIYEcUIsvwT5X7ofFhC2XxyRpqlIWZSQAxRSSJFyupRRXzyw== - dependencies: - "@types/node" "^12.6.1" - web3-core "1.2.7" - web3-core-helpers "1.2.7" - web3-core-method "1.2.7" - web3-net "1.2.7" - web3-utils "1.2.7" - web3-eth-personal@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.3.0.tgz#d376e03dc737d961ff1f8d1aca866efad8477135" @@ -20854,25 +20720,6 @@ web3-eth@1.2.11: web3-net "1.2.11" web3-utils "1.2.11" -web3-eth@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.7.tgz#9427daefd3641200679c2946f77fc184dbfb5b4c" - integrity sha512-ljLd0oB4IjWkzFGVan4HkYhJXhSXgn9iaSaxdJixKGntZPgWMJfxeA+uLwTrlxrWzhvy4f+39WnT7wCh5e9TGg== - dependencies: - underscore "1.9.1" - web3-core "1.2.7" - web3-core-helpers "1.2.7" - web3-core-method "1.2.7" - web3-core-subscriptions "1.2.7" - web3-eth-abi "1.2.7" - web3-eth-accounts "1.2.7" - web3-eth-contract "1.2.7" - web3-eth-ens "1.2.7" - web3-eth-iban "1.2.7" - web3-eth-personal "1.2.7" - web3-net "1.2.7" - web3-utils "1.2.7" - web3-eth@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.3.0.tgz#898e5f5a8827f9bc6844e267a52eb388916a6771" @@ -20919,15 +20766,6 @@ web3-net@1.2.11: web3-core-method "1.2.11" web3-utils "1.2.11" -web3-net@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.7.tgz#c355621a8769c9c1a967c801e7db90c92a0e3808" - integrity sha512-j9qeZrS1FNyCeA0BfdLojkxOZQz3FKa1DJI+Dw9fEVhZS68vLOFANu2RB96gR9BoPHo5+k5D3NsKOoxt1gw3Gg== - dependencies: - web3-core "1.2.7" - web3-core-method "1.2.7" - web3-utils "1.2.7" - web3-net@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.3.0.tgz#b69068cccffab58911c2f08ca4abfbefb0f948c6" @@ -21014,14 +20852,6 @@ web3-providers-http@1.2.11: web3-core-helpers "1.2.11" xhr2-cookies "1.1.0" -web3-providers-http@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.7.tgz#31eb15390c103169b3d7d31bdb1ccae9e3f1629d" - integrity sha512-vazGx5onuH/zogrwkUaLFJwFcJ6CckP65VFSHoiV+GTQdkOqgoDIha7StKkslvDz4XJ2FuY/zOZHbtuOYeltXQ== - dependencies: - web3-core-helpers "1.2.7" - xhr2-cookies "1.1.0" - web3-providers-http@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.3.0.tgz#88227f64c88b32abed4359383c2663616e0dc531" @@ -21057,15 +20887,6 @@ web3-providers-ipc@1.2.11: underscore "1.9.1" web3-core-helpers "1.2.11" -web3-providers-ipc@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.7.tgz#4e6716e8723d431df3d6bfa1acd2f7c04e7071ad" - integrity sha512-/zc0y724H2zbkV4UbGGMhsEiLfafjagIzfrsWZnyTZUlSB0OGRmmFm2EkLJAgtXrLiodaHHyXKM0vB8S24bxdA== - dependencies: - oboe "2.1.4" - underscore "1.9.1" - web3-core-helpers "1.2.7" - web3-providers-ipc@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.3.0.tgz#d7c2b203733b46f7b4e7b15633d891648cf9a293" @@ -21103,16 +20924,6 @@ web3-providers-ws@1.2.11: web3-core-helpers "1.2.11" websocket "^1.0.31" -web3-providers-ws@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.7.tgz#95b1cc5dc25e9b9d6630d6754f9354313b62f532" - integrity sha512-b5XzqDpRkNVe6MFs5K6iqOEyjQikHtg3KuU2/ClCDV37hm0WN4xCRVMC0LwegulbDXZej3zT9+1CYzGaGFREzA== - dependencies: - "@web3-js/websocket" "^1.0.29" - eventemitter3 "^4.0.0" - underscore "1.9.1" - web3-core-helpers "1.2.7" - web3-providers-ws@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.3.0.tgz#84adeff65acd4624d7f5bb43c5b2b22d8f0f63a4" @@ -21153,16 +20964,6 @@ web3-shh@1.2.11: web3-core-subscriptions "1.2.11" web3-net "1.2.11" -web3-shh@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.7.tgz#5382c7bc2f39539eb2841c4576d23ade25720461" - integrity sha512-f6PAgcpG0ZAo98KqCmeHoDEx5qzm3d5plet18DkT4U6WIeYowKdec8vZaLPRR7c2XreXFJ2gQf45CB7oqR7U/w== - dependencies: - web3-core "1.2.7" - web3-core-method "1.2.7" - web3-core-subscriptions "1.2.7" - web3-net "1.2.7" - web3-shh@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.3.0.tgz#62d15297da8fb5f733dd1b98f9ade300590f4d49" @@ -21227,20 +21028,6 @@ web3-utils@1.2.6: underscore "1.9.1" utf8 "3.0.0" -web3-utils@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.7.tgz#b68e232917e4376f81cf38ef79878e5903d18e93" - integrity sha512-FBh/CPJND+eiPeUF9KVbTyTZtXNWxPWtByBaWS6e2x4ACazPX711EeNaZaChIOGSLGe6se2n7kg6wnawe/MjuQ== - dependencies: - bn.js "4.11.8" - eth-lib "0.2.7" - ethereum-bloom-filters "^1.0.6" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - underscore "1.9.1" - utf8 "3.0.0" - web3-utils@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.3.0.tgz#5bac16e5e0ec9fe7bdcfadb621655e8aa3cf14e1" @@ -21294,19 +21081,6 @@ web3@1.2.11: web3-shh "1.2.11" web3-utils "1.2.11" -web3@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.7.tgz#fcb83571036c1c6f475bc984785982a444e8d78e" - integrity sha512-jAAJHMfUlTps+jH2li1ckDFEpPrEEriU/ubegSTGRl3KRdNhEqT93+3kd7FHJTn3NgjcyURo2+f7Da1YcZL8Mw== - dependencies: - web3-bzz "1.2.7" - web3-core "1.2.7" - web3-eth "1.2.7" - web3-eth-personal "1.2.7" - web3-net "1.2.7" - web3-shh "1.2.7" - web3-utils "1.2.7" - web3@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web3/-/web3-1.3.0.tgz#8fe4cd6e2a21c91904f343ba75717ee4c76bb349"