Get required block confirmation at the moment of the transaction (#379)

This commit is contained in:
Gerardo Nardelli 2020-06-30 17:41:19 -03:00 committed by GitHub
parent 691e4294ae
commit ab814f831c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 71 additions and 33 deletions

@ -11,6 +11,7 @@ import { getConfirmationsStatusDescription } from '../utils/networks'
import { useStateProvider } from '../state/StateProvider' import { useStateProvider } from '../state/StateProvider'
import { ExecutionConfirmation } from './ExecutionConfirmation' import { ExecutionConfirmation } from './ExecutionConfirmation'
import { useValidatorContract } from '../hooks/useValidatorContract' import { useValidatorContract } from '../hooks/useValidatorContract'
import { useBlockConfirmations } from '../hooks/useBlockConfirmations'
const StatusLabel = styled.label` const StatusLabel = styled.label`
font-weight: bold; font-weight: bold;
@ -45,13 +46,15 @@ export const ConfirmationsContainer = ({ message, receipt, fromHome, timestamp }
foreign: { name: foreignName } foreign: { name: foreignName }
} = useStateProvider() } = useStateProvider()
const { requiredSignatures, validatorList } = useValidatorContract({ fromHome, receipt }) const { requiredSignatures, validatorList } = useValidatorContract({ fromHome, receipt })
const { blockConfirmations } = useBlockConfirmations({ fromHome, receipt })
const { confirmations, status, executionData, signatureCollected } = useMessageConfirmations({ const { confirmations, status, executionData, signatureCollected } = useMessageConfirmations({
message, message,
receipt, receipt,
fromHome, fromHome,
timestamp, timestamp,
requiredSignatures, requiredSignatures,
validatorList validatorList,
blockConfirmations
}) })
return ( return (

@ -0,0 +1,38 @@
import { useEffect, useState } from 'react'
import { TransactionReceipt } from 'web3-eth'
import { useStateProvider } from '../state/StateProvider'
import { Contract } from 'web3-eth-contract'
import { getRequiredBlockConfirmations } from '../utils/contract'
export interface UseBlockConfirmationsParams {
fromHome: boolean
receipt: Maybe<TransactionReceipt>
}
export const useBlockConfirmations = ({ receipt, fromHome }: UseBlockConfirmationsParams) => {
const [blockConfirmations, setBlockConfirmations] = useState(0)
const { home, foreign } = useStateProvider()
const callRequireBlockConfirmations = async (
contract: Contract,
receipt: TransactionReceipt,
setResult: Function
) => {
const result = await getRequiredBlockConfirmations(contract, receipt.blockNumber)
setResult(result)
}
useEffect(
() => {
const bridgeContract = fromHome ? home.bridgeContract : foreign.bridgeContract
if (!bridgeContract || !receipt) return
callRequireBlockConfirmations(bridgeContract, receipt, setBlockConfirmations)
},
[home.bridgeContract, foreign.bridgeContract, receipt, fromHome]
)
return {
blockConfirmations
}
}

@ -3,7 +3,6 @@ import { HOME_AMB_ABI, FOREIGN_AMB_ABI } from '../abis'
import { FOREIGN_BRIDGE_ADDRESS, HOME_BRIDGE_ADDRESS } from '../config/constants' import { FOREIGN_BRIDGE_ADDRESS, HOME_BRIDGE_ADDRESS } from '../config/constants'
import { Contract } from 'web3-eth-contract' import { Contract } from 'web3-eth-contract'
import Web3 from 'web3' import Web3 from 'web3'
import { getRequiredBlockConfirmations } from '../utils/contract'
export interface useBridgeContractsParams { export interface useBridgeContractsParams {
homeWeb3: Web3 homeWeb3: Web3
@ -13,20 +12,11 @@ export interface useBridgeContractsParams {
export const useBridgeContracts = ({ homeWeb3, foreignWeb3 }: useBridgeContractsParams) => { export const useBridgeContracts = ({ homeWeb3, foreignWeb3 }: useBridgeContractsParams) => {
const [homeBridge, setHomeBridge] = useState<Maybe<Contract>>(null) const [homeBridge, setHomeBridge] = useState<Maybe<Contract>>(null)
const [foreignBridge, setForeignBridge] = useState<Maybe<Contract>>(null) const [foreignBridge, setForeignBridge] = useState<Maybe<Contract>>(null)
const [homeBlockConfirmations, setHomeBlockConfirmations] = useState(0)
const [foreignBlockConfirmations, setForeignBlockConfirmations] = useState(0)
const callRequireBlockConfirmations = async (contract: Maybe<Contract>, setResult: Function) => {
if (!contract) return
const result = await getRequiredBlockConfirmations(contract)
setResult(result)
}
useEffect( useEffect(
() => { () => {
if (!homeWeb3) return if (!homeWeb3) return
const homeContract = new homeWeb3.eth.Contract(HOME_AMB_ABI, HOME_BRIDGE_ADDRESS) const homeContract = new homeWeb3.eth.Contract(HOME_AMB_ABI, HOME_BRIDGE_ADDRESS)
callRequireBlockConfirmations(homeContract, setHomeBlockConfirmations)
setHomeBridge(homeContract) setHomeBridge(homeContract)
}, },
[homeWeb3] [homeWeb3]
@ -36,7 +26,6 @@ export const useBridgeContracts = ({ homeWeb3, foreignWeb3 }: useBridgeContracts
() => { () => {
if (!foreignWeb3) return if (!foreignWeb3) return
const foreignContract = new foreignWeb3.eth.Contract(FOREIGN_AMB_ABI, FOREIGN_BRIDGE_ADDRESS) const foreignContract = new foreignWeb3.eth.Contract(FOREIGN_AMB_ABI, FOREIGN_BRIDGE_ADDRESS)
callRequireBlockConfirmations(foreignContract, setForeignBlockConfirmations)
setForeignBridge(foreignContract) setForeignBridge(foreignContract)
}, },
[foreignWeb3] [foreignWeb3]
@ -44,8 +33,6 @@ export const useBridgeContracts = ({ homeWeb3, foreignWeb3 }: useBridgeContracts
return { return {
homeBridge, homeBridge,
foreignBridge, foreignBridge
homeBlockConfirmations,
foreignBlockConfirmations
} }
} }

@ -32,6 +32,7 @@ export interface useMessageConfirmationsParams {
timestamp: number timestamp: number
requiredSignatures: number requiredSignatures: number
validatorList: string[] validatorList: string[]
blockConfirmations: number
} }
export interface BasicConfirmationParam { export interface BasicConfirmationParam {
@ -58,7 +59,8 @@ export const useMessageConfirmations = ({
fromHome, fromHome,
timestamp, timestamp,
requiredSignatures, requiredSignatures,
validatorList validatorList,
blockConfirmations
}: useMessageConfirmationsParams) => { }: useMessageConfirmationsParams) => {
const { home, foreign } = useStateProvider() const { home, foreign } = useStateProvider()
const [confirmations, setConfirmations] = useState<Array<ConfirmationParam>>([]) const [confirmations, setConfirmations] = useState<Array<ConfirmationParam>>([])
@ -84,7 +86,7 @@ export const useMessageConfirmations = ({
// Check if the validators are waiting for block confirmations to verify the message // Check if the validators are waiting for block confirmations to verify the message
useEffect( useEffect(
() => { () => {
if (!receipt) return if (!receipt || !blockConfirmations) return
const subscriptions: Array<number> = [] const subscriptions: Array<number> = []
@ -99,8 +101,7 @@ export const useMessageConfirmations = ({
const web3 = fromHome ? home.web3 : foreign.web3 const web3 = fromHome ? home.web3 : foreign.web3
blockProvider.start(web3) blockProvider.start(web3)
const requiredBlockConfirmations = fromHome ? home.blockConfirmations : foreign.blockConfirmations const targetBlock = receipt.blockNumber + blockConfirmations
const targetBlock = receipt.blockNumber + requiredBlockConfirmations
checkSignaturesWaitingForBLocks( checkSignaturesWaitingForBLocks(
targetBlock, targetBlock,
@ -118,7 +119,7 @@ export const useMessageConfirmations = ({
blockProvider.stop() blockProvider.stop()
} }
}, },
[foreign.blockConfirmations, foreign.web3, fromHome, home.blockConfirmations, validatorList, home.web3, receipt] [blockConfirmations, foreign.web3, fromHome, validatorList, home.web3, receipt]
) )
// The collected signature event is only fetched once the signatures are collected on tx from home to foreign, to calculate if // The collected signature event is only fetched once the signatures are collected on tx from home to foreign, to calculate if
@ -164,7 +165,7 @@ export const useMessageConfirmations = ({
// This is executed if the message is in Home to Foreign direction only // This is executed if the message is in Home to Foreign direction only
useEffect( useEffect(
() => { () => {
if (!fromHome || !home.web3 || !receipt || !collectedSignaturesEvent) return if (!fromHome || !home.web3 || !receipt || !collectedSignaturesEvent || !blockConfirmations) return
const subscriptions: Array<number> = [] const subscriptions: Array<number> = []
@ -175,7 +176,7 @@ export const useMessageConfirmations = ({
} }
homeBlockNumberProvider.start(home.web3) homeBlockNumberProvider.start(home.web3)
const targetBlock = collectedSignaturesEvent.blockNumber + home.blockConfirmations const targetBlock = collectedSignaturesEvent.blockNumber + blockConfirmations
checkWaitingBlocksForExecution( checkWaitingBlocksForExecution(
homeBlockNumberProvider, homeBlockNumberProvider,
@ -193,7 +194,7 @@ export const useMessageConfirmations = ({
homeBlockNumberProvider.stop() homeBlockNumberProvider.stop()
} }
}, },
[collectedSignaturesEvent, fromHome, home.blockConfirmations, home.web3, receipt] [collectedSignaturesEvent, fromHome, blockConfirmations, home.web3, receipt]
) )
// Checks if validators verified the message // Checks if validators verified the message

@ -18,7 +18,6 @@ export interface BaseNetworkParams {
web3: Maybe<Web3> web3: Maybe<Web3>
bridgeAddress: string bridgeAddress: string
bridgeContract: Maybe<Contract> bridgeContract: Maybe<Contract>
blockConfirmations: number
} }
export interface StateContext { export interface StateContext {
@ -33,16 +32,14 @@ const initialState = {
name: '', name: '',
web3: null, web3: null,
bridgeAddress: HOME_BRIDGE_ADDRESS, bridgeAddress: HOME_BRIDGE_ADDRESS,
bridgeContract: null, bridgeContract: null
blockConfirmations: 0
}, },
foreign: { foreign: {
chainId: 0, chainId: 0,
name: '', name: '',
web3: null, web3: null,
bridgeAddress: FOREIGN_BRIDGE_ADDRESS, bridgeAddress: FOREIGN_BRIDGE_ADDRESS,
bridgeContract: null, bridgeContract: null
blockConfirmations: 0
}, },
loading: true loading: true
} }
@ -52,7 +49,7 @@ const StateContext = createContext<StateContext>(initialState)
export const StateProvider = ({ children }: { children: ReactNode }) => { export const StateProvider = ({ children }: { children: ReactNode }) => {
const homeNetwork = useNetwork(HOME_RPC_URL) const homeNetwork = useNetwork(HOME_RPC_URL)
const foreignNetwork = useNetwork(FOREIGN_RPC_URL) const foreignNetwork = useNetwork(FOREIGN_RPC_URL)
const { homeBridge, foreignBridge, homeBlockConfirmations, foreignBlockConfirmations } = useBridgeContracts({ const { homeBridge, foreignBridge } = useBridgeContracts({
homeWeb3: homeNetwork.web3, homeWeb3: homeNetwork.web3,
foreignWeb3: foreignNetwork.web3 foreignWeb3: foreignNetwork.web3
}) })
@ -62,14 +59,12 @@ export const StateProvider = ({ children }: { children: ReactNode }) => {
bridgeAddress: HOME_BRIDGE_ADDRESS, bridgeAddress: HOME_BRIDGE_ADDRESS,
name: HOME_NETWORK_NAME, name: HOME_NETWORK_NAME,
bridgeContract: homeBridge, bridgeContract: homeBridge,
blockConfirmations: homeBlockConfirmations,
...homeNetwork ...homeNetwork
}, },
foreign: { foreign: {
bridgeAddress: FOREIGN_BRIDGE_ADDRESS, bridgeAddress: FOREIGN_BRIDGE_ADDRESS,
name: FOREIGN_NETWORK_NAME, name: FOREIGN_NETWORK_NAME,
bridgeContract: foreignBridge, bridgeContract: foreignBridge,
blockConfirmations: foreignBlockConfirmations,
...foreignNetwork ...foreignNetwork
}, },
loading: homeNetwork.loading || foreignNetwork.loading loading: homeNetwork.loading || foreignNetwork.loading

@ -1,7 +1,21 @@
import { Contract } from 'web3-eth-contract' import { Contract } from 'web3-eth-contract'
export const getRequiredBlockConfirmations = async (contract: Contract) => { export const getRequiredBlockConfirmations = async (contract: Contract, blockNumber: number) => {
const blockConfirmations = await contract.methods.requiredBlockConfirmations().call() const events = await contract.getPastEvents('RequiredBlockConfirmationChanged', {
fromBlock: 0,
toBlock: blockNumber
})
let blockConfirmations
if (events.length > 0) {
// Use the value from last event before the transaction
const event = events[events.length - 1]
blockConfirmations = event.returnValues.requiredBlockConfirmations
} else {
// This is a special case where RequiredBlockConfirmationChanged was not emitted during initialization in early versions of AMB
// of Sokol - Kovan. In this case the current value is used.
blockConfirmations = await contract.methods.requiredBlockConfirmations().call()
}
return parseInt(blockConfirmations) return parseInt(blockConfirmations)
} }