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 { ExecutionConfirmation } from './ExecutionConfirmation'
import { useValidatorContract } from '../hooks/useValidatorContract'
import { useBlockConfirmations } from '../hooks/useBlockConfirmations'
const StatusLabel = styled.label`
font-weight: bold;
@ -45,13 +46,15 @@ export const ConfirmationsContainer = ({ message, receipt, fromHome, timestamp }
foreign: { name: foreignName }
} = useStateProvider()
const { requiredSignatures, validatorList } = useValidatorContract({ fromHome, receipt })
const { blockConfirmations } = useBlockConfirmations({ fromHome, receipt })
const { confirmations, status, executionData, signatureCollected } = useMessageConfirmations({
message,
receipt,
fromHome,
timestamp,
requiredSignatures,
validatorList
validatorList,
blockConfirmations
})
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 { Contract } from 'web3-eth-contract'
import Web3 from 'web3'
import { getRequiredBlockConfirmations } from '../utils/contract'
export interface useBridgeContractsParams {
homeWeb3: Web3
@ -13,20 +12,11 @@ export interface useBridgeContractsParams {
export const useBridgeContracts = ({ homeWeb3, foreignWeb3 }: useBridgeContractsParams) => {
const [homeBridge, setHomeBridge] = 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(
() => {
if (!homeWeb3) return
const homeContract = new homeWeb3.eth.Contract(HOME_AMB_ABI, HOME_BRIDGE_ADDRESS)
callRequireBlockConfirmations(homeContract, setHomeBlockConfirmations)
setHomeBridge(homeContract)
},
[homeWeb3]
@ -36,7 +26,6 @@ export const useBridgeContracts = ({ homeWeb3, foreignWeb3 }: useBridgeContracts
() => {
if (!foreignWeb3) return
const foreignContract = new foreignWeb3.eth.Contract(FOREIGN_AMB_ABI, FOREIGN_BRIDGE_ADDRESS)
callRequireBlockConfirmations(foreignContract, setForeignBlockConfirmations)
setForeignBridge(foreignContract)
},
[foreignWeb3]
@ -44,8 +33,6 @@ export const useBridgeContracts = ({ homeWeb3, foreignWeb3 }: useBridgeContracts
return {
homeBridge,
foreignBridge,
homeBlockConfirmations,
foreignBlockConfirmations
foreignBridge
}
}

@ -32,6 +32,7 @@ export interface useMessageConfirmationsParams {
timestamp: number
requiredSignatures: number
validatorList: string[]
blockConfirmations: number
}
export interface BasicConfirmationParam {
@ -58,7 +59,8 @@ export const useMessageConfirmations = ({
fromHome,
timestamp,
requiredSignatures,
validatorList
validatorList,
blockConfirmations
}: useMessageConfirmationsParams) => {
const { home, foreign } = useStateProvider()
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
useEffect(
() => {
if (!receipt) return
if (!receipt || !blockConfirmations) return
const subscriptions: Array<number> = []
@ -99,8 +101,7 @@ export const useMessageConfirmations = ({
const web3 = fromHome ? home.web3 : foreign.web3
blockProvider.start(web3)
const requiredBlockConfirmations = fromHome ? home.blockConfirmations : foreign.blockConfirmations
const targetBlock = receipt.blockNumber + requiredBlockConfirmations
const targetBlock = receipt.blockNumber + blockConfirmations
checkSignaturesWaitingForBLocks(
targetBlock,
@ -118,7 +119,7 @@ export const useMessageConfirmations = ({
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
@ -164,7 +165,7 @@ export const useMessageConfirmations = ({
// This is executed if the message is in Home to Foreign direction only
useEffect(
() => {
if (!fromHome || !home.web3 || !receipt || !collectedSignaturesEvent) return
if (!fromHome || !home.web3 || !receipt || !collectedSignaturesEvent || !blockConfirmations) return
const subscriptions: Array<number> = []
@ -175,7 +176,7 @@ export const useMessageConfirmations = ({
}
homeBlockNumberProvider.start(home.web3)
const targetBlock = collectedSignaturesEvent.blockNumber + home.blockConfirmations
const targetBlock = collectedSignaturesEvent.blockNumber + blockConfirmations
checkWaitingBlocksForExecution(
homeBlockNumberProvider,
@ -193,7 +194,7 @@ export const useMessageConfirmations = ({
homeBlockNumberProvider.stop()
}
},
[collectedSignaturesEvent, fromHome, home.blockConfirmations, home.web3, receipt]
[collectedSignaturesEvent, fromHome, blockConfirmations, home.web3, receipt]
)
// Checks if validators verified the message

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

@ -1,7 +1,21 @@
import { Contract } from 'web3-eth-contract'
export const getRequiredBlockConfirmations = async (contract: Contract) => {
const blockConfirmations = await contract.methods.requiredBlockConfirmations().call()
export const getRequiredBlockConfirmations = async (contract: Contract, blockNumber: number) => {
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)
}