Add safe-execute button in ALM (#580)
This commit is contained in:
parent
8b1a97e673
commit
92e1b597c4
@ -123,6 +123,24 @@ const abi: AbiItem[] = [
|
|||||||
stateMutability: 'nonpayable',
|
stateMutability: 'nonpayable',
|
||||||
type: 'function'
|
type: 'function'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
constant: false,
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
name: '_data',
|
||||||
|
type: 'bytes'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '_signatures',
|
||||||
|
type: 'bytes'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: 'safeExecuteSignaturesWithAutoGasLimit',
|
||||||
|
outputs: [],
|
||||||
|
payable: false,
|
||||||
|
stateMutability: 'nonpayable',
|
||||||
|
type: 'function'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
constant: true,
|
constant: true,
|
||||||
inputs: [
|
inputs: [
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { formatTimestamp, formatTxHash, getExplorerTxUrl } from '../utils/networks'
|
import { formatTimestamp, formatTxHash, getExplorerTxUrl } from '../utils/networks'
|
||||||
import { useWindowWidth } from '@react-hook/window-size'
|
import { useWindowWidth } from '@react-hook/window-size'
|
||||||
import { SEARCHING_TX, VALIDATOR_CONFIRMATION_STATUS, ALM_HOME_TO_FOREIGN_MANUAL_EXECUTION } from '../config/constants'
|
import { SEARCHING_TX, VALIDATOR_CONFIRMATION_STATUS, ALM_HOME_TO_FOREIGN_MANUAL_EXECUTION } from '../config/constants'
|
||||||
@ -9,6 +9,7 @@ import { GreyLabel, RedLabel, SuccessLabel } from './commons/Labels'
|
|||||||
import { ExplorerTxLink } from './commons/ExplorerTxLink'
|
import { ExplorerTxLink } from './commons/ExplorerTxLink'
|
||||||
import { Thead, AgeTd, StatusTd } from './commons/Table'
|
import { Thead, AgeTd, StatusTd } from './commons/Table'
|
||||||
import { ManualExecutionButton } from './ManualExecutionButton'
|
import { ManualExecutionButton } from './ManualExecutionButton'
|
||||||
|
import { useStateProvider } from '../state/StateProvider'
|
||||||
|
|
||||||
const StyledExecutionConfirmation = styled.div`
|
const StyledExecutionConfirmation = styled.div`
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
@ -33,6 +34,8 @@ export const ExecutionConfirmation = ({
|
|||||||
executionEventsFetched,
|
executionEventsFetched,
|
||||||
setPendingExecution
|
setPendingExecution
|
||||||
}: ExecutionConfirmationParams) => {
|
}: ExecutionConfirmationParams) => {
|
||||||
|
const { foreign } = useStateProvider()
|
||||||
|
const [safeExecutionAvailable, setSafeExecutionAvailable] = useState(false)
|
||||||
const availableManualExecution =
|
const availableManualExecution =
|
||||||
!isHome &&
|
!isHome &&
|
||||||
(executionData.status === VALIDATOR_CONFIRMATION_STATUS.WAITING ||
|
(executionData.status === VALIDATOR_CONFIRMATION_STATUS.WAITING ||
|
||||||
@ -48,6 +51,22 @@ export const ExecutionConfirmation = ({
|
|||||||
const formattedValidator =
|
const formattedValidator =
|
||||||
windowWidth < 850 && executionData.validator ? formatTxHash(executionData.validator) : executionData.validator
|
windowWidth < 850 && executionData.validator ? formatTxHash(executionData.validator) : executionData.validator
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
() => {
|
||||||
|
if (!availableManualExecution || !foreign.bridgeContract) return
|
||||||
|
|
||||||
|
const p = foreign.bridgeContract.methods.getBridgeInterfacesVersion().call()
|
||||||
|
p.then(({ major, minor }: any) => {
|
||||||
|
major = parseInt(major, 10)
|
||||||
|
minor = parseInt(minor, 10)
|
||||||
|
if (major < 5 || (major === 5 && minor < 7)) return
|
||||||
|
|
||||||
|
setSafeExecutionAvailable(true)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
[availableManualExecution, foreign.bridgeContract]
|
||||||
|
)
|
||||||
|
|
||||||
const getExecutionStatusElement = (validatorStatus = '') => {
|
const getExecutionStatusElement = (validatorStatus = '') => {
|
||||||
switch (validatorStatus) {
|
switch (validatorStatus) {
|
||||||
case VALIDATOR_CONFIRMATION_STATUS.SUCCESS:
|
case VALIDATOR_CONFIRMATION_STATUS.SUCCESS:
|
||||||
@ -105,6 +124,7 @@ export const ExecutionConfirmation = ({
|
|||||||
{availableManualExecution && (
|
{availableManualExecution && (
|
||||||
<td>
|
<td>
|
||||||
<ManualExecutionButton
|
<ManualExecutionButton
|
||||||
|
safeExecutionAvailable={safeExecutionAvailable}
|
||||||
messageData={messageData}
|
messageData={messageData}
|
||||||
setExecutionData={setExecutionData}
|
setExecutionData={setExecutionData}
|
||||||
signatureCollected={signatureCollected as string[]}
|
signatureCollected={signatureCollected as string[]}
|
||||||
|
@ -15,16 +15,19 @@ import { signatureToVRS, packSignatures } from '../utils/signatures'
|
|||||||
import { getSuccessExecutionData } from '../utils/getFinalizationEvent'
|
import { getSuccessExecutionData } from '../utils/getFinalizationEvent'
|
||||||
import { TransactionReceipt } from 'web3-eth'
|
import { TransactionReceipt } from 'web3-eth'
|
||||||
|
|
||||||
const StyledButton = styled.button`
|
const ActionButton = styled.button`
|
||||||
color: var(--button-color);
|
color: var(--button-color);
|
||||||
border-color: var(--font-color);
|
border-color: var(--font-color);
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
|
min-width: 120px;
|
||||||
|
padding: 1rem;
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: var(--button-color);
|
outline: var(--button-color);
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
interface ManualExecutionButtonParams {
|
interface ManualExecutionButtonParams {
|
||||||
|
safeExecutionAvailable: boolean
|
||||||
messageData: string
|
messageData: string
|
||||||
setExecutionData: Function
|
setExecutionData: Function
|
||||||
signatureCollected: string[]
|
signatureCollected: string[]
|
||||||
@ -32,6 +35,7 @@ interface ManualExecutionButtonParams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const ManualExecutionButton = ({
|
export const ManualExecutionButton = ({
|
||||||
|
safeExecutionAvailable,
|
||||||
messageData,
|
messageData,
|
||||||
setExecutionData,
|
setExecutionData,
|
||||||
signatureCollected,
|
signatureCollected,
|
||||||
@ -40,6 +44,7 @@ export const ManualExecutionButton = ({
|
|||||||
const { foreign, setError } = useStateProvider()
|
const { foreign, setError } = useStateProvider()
|
||||||
const { library, activate, account, active } = useWeb3React()
|
const { library, activate, account, active } = useWeb3React()
|
||||||
const [manualExecution, setManualExecution] = useState(false)
|
const [manualExecution, setManualExecution] = useState(false)
|
||||||
|
const [allowFailures, setAllowFailures] = useState(false)
|
||||||
|
|
||||||
useEffect(
|
useEffect(
|
||||||
() => {
|
() => {
|
||||||
@ -72,7 +77,11 @@ export const ManualExecutionButton = ({
|
|||||||
const signatures = packSignatures(signatureCollected.map(signatureToVRS))
|
const signatures = packSignatures(signatureCollected.map(signatureToVRS))
|
||||||
const messageId = messageData.slice(0, 66)
|
const messageId = messageData.slice(0, 66)
|
||||||
const bridge = foreign.bridgeContract
|
const bridge = foreign.bridgeContract
|
||||||
const data = bridge.methods.executeSignatures(messageData, signatures).encodeABI()
|
const executeMethod =
|
||||||
|
safeExecutionAvailable && !allowFailures
|
||||||
|
? bridge.methods.safeExecuteSignaturesWithAutoGasLimit
|
||||||
|
: bridge.methods.executeSignatures
|
||||||
|
const data = executeMethod(messageData, signatures).encodeABI()
|
||||||
setManualExecution(false)
|
setManualExecution(false)
|
||||||
|
|
||||||
library.eth
|
library.eth
|
||||||
@ -132,15 +141,35 @@ export const ManualExecutionButton = ({
|
|||||||
messageData,
|
messageData,
|
||||||
signatureCollected,
|
signatureCollected,
|
||||||
setExecutionData,
|
setExecutionData,
|
||||||
setPendingExecution
|
setPendingExecution,
|
||||||
|
safeExecutionAvailable,
|
||||||
|
allowFailures
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="is-center">
|
<div>
|
||||||
<StyledButton className="button outline" onClick={() => setManualExecution(true)}>
|
<div className="is-center">
|
||||||
Execute
|
<ActionButton className="button outline" onClick={() => setManualExecution(true)}>
|
||||||
</StyledButton>
|
Execute
|
||||||
|
</ActionButton>
|
||||||
|
</div>
|
||||||
|
{safeExecutionAvailable && (
|
||||||
|
<div
|
||||||
|
title="Allow executed message to fail and record its failure on-chain without reverting the whole transaction.
|
||||||
|
Use fixed gas limit for execution."
|
||||||
|
className="is-center"
|
||||||
|
style={{ paddingTop: 10 }}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="allow-failures"
|
||||||
|
checked={allowFailures}
|
||||||
|
onChange={e => setAllowFailures(e.target.checked)}
|
||||||
|
/>
|
||||||
|
<label htmlFor="allow-failures">Unsafe mode</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user