ALM: warning for auto-relayed messages (#644)
This commit is contained in:
parent
9c2d2f404c
commit
910c3759c1
@ -121,7 +121,7 @@ export const ConfirmationsContainer = ({
|
||||
/>
|
||||
{signatureCollected && (
|
||||
<ExecutionConfirmation
|
||||
messageData={message.data}
|
||||
message={message}
|
||||
executionData={executionData}
|
||||
isHome={!fromHome}
|
||||
signatureCollected={signatureCollected}
|
||||
|
@ -10,13 +10,14 @@ import { ExplorerTxLink } from './commons/ExplorerTxLink'
|
||||
import { Thead, AgeTd, StatusTd } from './commons/Table'
|
||||
import { ManualExecutionButton } from './ManualExecutionButton'
|
||||
import { useStateProvider } from '../state/StateProvider'
|
||||
import { matchesRule, MessageObject, WarnRule } from '../utils/web3'
|
||||
|
||||
const StyledExecutionConfirmation = styled.div`
|
||||
margin-top: 30px;
|
||||
`
|
||||
|
||||
export interface ExecutionConfirmationParams {
|
||||
messageData: string
|
||||
message: MessageObject
|
||||
executionData: ExecutionData
|
||||
setExecutionData: Function
|
||||
signatureCollected: boolean | string[]
|
||||
@ -26,7 +27,7 @@ export interface ExecutionConfirmationParams {
|
||||
}
|
||||
|
||||
export const ExecutionConfirmation = ({
|
||||
messageData,
|
||||
message,
|
||||
executionData,
|
||||
setExecutionData,
|
||||
signatureCollected,
|
||||
@ -34,7 +35,7 @@ export const ExecutionConfirmation = ({
|
||||
executionEventsFetched,
|
||||
setPendingExecution
|
||||
}: ExecutionConfirmationParams) => {
|
||||
const { foreign } = useStateProvider()
|
||||
const { foreign, setWarning } = useStateProvider()
|
||||
const [safeExecutionAvailable, setSafeExecutionAvailable] = useState(false)
|
||||
const availableManualExecution =
|
||||
!isHome &&
|
||||
@ -67,6 +68,24 @@ export const ExecutionConfirmation = ({
|
||||
[availableManualExecution, foreign.bridgeContract]
|
||||
)
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
if (!message.data || !executionData || !availableManualExecution) return
|
||||
|
||||
try {
|
||||
const fileName = 'warnRules'
|
||||
const rules: WarnRule[] = require(`../snapshots/${fileName}.json`)
|
||||
for (let rule of rules) {
|
||||
if (matchesRule(rule, message)) {
|
||||
setWarning(rule.message)
|
||||
return
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
},
|
||||
[availableManualExecution, executionData, message, message.data, setWarning]
|
||||
)
|
||||
|
||||
const getExecutionStatusElement = (validatorStatus = '') => {
|
||||
switch (validatorStatus) {
|
||||
case VALIDATOR_CONFIRMATION_STATUS.EXECUTION_SUCCESS:
|
||||
@ -125,7 +144,7 @@ export const ExecutionConfirmation = ({
|
||||
<td>
|
||||
<ManualExecutionButton
|
||||
safeExecutionAvailable={safeExecutionAvailable}
|
||||
messageData={messageData}
|
||||
messageData={message.data}
|
||||
setExecutionData={setExecutionData}
|
||||
signatureCollected={signatureCollected as string[]}
|
||||
setPendingExecution={setPendingExecution}
|
||||
|
@ -9,6 +9,7 @@ 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'
|
||||
import { WarningAlert } from './commons/WarningAlert'
|
||||
|
||||
const StyledMainPage = styled.div`
|
||||
text-align: center;
|
||||
@ -52,7 +53,7 @@ export interface FormSubmitParams {
|
||||
|
||||
export const MainPage = () => {
|
||||
const history = useHistory()
|
||||
const { home, foreign, error, setError } = useStateProvider()
|
||||
const { home, foreign, error, setError, warning, setWarning } = useStateProvider()
|
||||
const [networkName, setNetworkName] = useState('')
|
||||
const [receipt, setReceipt] = useState<Maybe<TransactionReceipt>>(null)
|
||||
const [showInfoAlert, setShowInfoAlert] = useState(false)
|
||||
@ -133,6 +134,7 @@ export const MainPage = () => {
|
||||
</InfoAlert>
|
||||
)}
|
||||
{error && <ErrorAlert onClick={() => setError('')} error={error} />}
|
||||
{warning && <WarningAlert onClick={() => setWarning('')} error={warning} />}
|
||||
<Route exact path={['/']} children={<Form onSubmit={onFormSubmit} />} />
|
||||
<Route
|
||||
path={['/:chainId/:txHash/:messageIdParam', '/:chainId/:txHash']}
|
||||
|
34
alm/src/components/commons/WarningAlert.tsx
Normal file
34
alm/src/components/commons/WarningAlert.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
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(--warning-color);
|
||||
border-radius: 4px;
|
||||
margin-bottom: 20px;
|
||||
padding-top: 10px;
|
||||
`
|
||||
|
||||
const CloseIconContainer = styled.div`
|
||||
cursor: pointer;
|
||||
`
|
||||
|
||||
const TextContainer = styled.div`
|
||||
white-space: pre-wrap;
|
||||
flex-direction: column;
|
||||
`
|
||||
|
||||
export const WarningAlert = ({ onClick, error }: { onClick: () => void; error: string }) => {
|
||||
return (
|
||||
<div className="row is-center">
|
||||
<StyledErrorAlert className="col-10 is-vertical-align row">
|
||||
<InfoIcon color="var(--warning-color)" />
|
||||
<TextContainer className="col-10">{error}</TextContainer>
|
||||
<CloseIconContainer className="col-1 is-vertical-align is-center" onClick={onClick}>
|
||||
<CloseIcon color="var(--warning-color)" />
|
||||
</CloseIconContainer>
|
||||
</StyledErrorAlert>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -27,6 +27,8 @@ export interface StateContext {
|
||||
loading: boolean
|
||||
error: string
|
||||
setError: Function
|
||||
warning: string
|
||||
setWarning: Function
|
||||
}
|
||||
|
||||
const initialState = {
|
||||
@ -46,7 +48,9 @@ const initialState = {
|
||||
},
|
||||
loading: true,
|
||||
error: '',
|
||||
setError: () => {}
|
||||
setError: () => {},
|
||||
warning: '',
|
||||
setWarning: () => {}
|
||||
}
|
||||
|
||||
const StateContext = createContext<StateContext>(initialState)
|
||||
@ -59,6 +63,7 @@ export const StateProvider = ({ children }: { children: ReactNode }) => {
|
||||
foreignWeb3: foreignNetwork.web3
|
||||
})
|
||||
const [error, setError] = useState('')
|
||||
const [warning, setWarning] = useState('')
|
||||
|
||||
const value = {
|
||||
home: {
|
||||
@ -75,7 +80,9 @@ export const StateProvider = ({ children }: { children: ReactNode }) => {
|
||||
},
|
||||
loading: homeNetwork.loading || foreignNetwork.loading,
|
||||
error,
|
||||
setError
|
||||
setError,
|
||||
warning,
|
||||
setWarning
|
||||
}
|
||||
|
||||
return <StateContext.Provider value={value}>{children}</StateContext.Provider>
|
||||
|
@ -28,5 +28,7 @@ export const GlobalStyle = createGlobalStyle<{ theme: ThemeType }>`
|
||||
--not-required-bg-color: ${props => props.theme.notRequired.backgroundColor};
|
||||
--failed-color: ${props => props.theme.failed.textColor};
|
||||
--failed-bg-color: ${props => props.theme.failed.backgroundColor};
|
||||
--warning-color: ${props => props.theme.warning.textColor};
|
||||
--warning-bg-color: ${props => props.theme.warning.backgroundColor};
|
||||
}
|
||||
`
|
||||
|
@ -17,6 +17,10 @@ const theme = {
|
||||
failed: {
|
||||
textColor: '#de4437',
|
||||
backgroundColor: 'rgba(222,68,55,.1)'
|
||||
},
|
||||
warning: {
|
||||
textColor: '#ffa758',
|
||||
backgroundColor: 'rgba(222,68,55,.1)'
|
||||
}
|
||||
}
|
||||
export default theme
|
||||
|
@ -10,6 +10,37 @@ import { SnapshotProvider } from '../services/SnapshotProvider'
|
||||
export interface MessageObject {
|
||||
id: string
|
||||
data: string
|
||||
sender?: string
|
||||
executor?: string
|
||||
obToken?: string
|
||||
obReceiver?: string
|
||||
}
|
||||
|
||||
export interface WarnRule {
|
||||
message: string
|
||||
sender?: string
|
||||
executor?: string
|
||||
obToken?: string
|
||||
obReceiver?: string
|
||||
}
|
||||
|
||||
export const matchesRule = (rule: WarnRule, msg: MessageObject) => {
|
||||
if (!msg.executor || !msg.sender) {
|
||||
return false
|
||||
}
|
||||
if (!!rule.executor && rule.executor.toLowerCase() !== msg.executor.toLowerCase()) {
|
||||
return false
|
||||
}
|
||||
if (!!rule.sender && rule.sender.toLowerCase() !== msg.sender.toLowerCase()) {
|
||||
return false
|
||||
}
|
||||
if (!!rule.obToken && (!msg.obToken || rule.obToken.toLowerCase() !== msg.obToken.toLowerCase())) {
|
||||
return false
|
||||
}
|
||||
if (!!rule.obReceiver && (!msg.obReceiver || rule.obReceiver.toLowerCase() !== msg.obReceiver.toLowerCase())) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const rawGetWeb3 = (url: string) => new Web3(new Web3.providers.HttpProvider(url))
|
||||
@ -26,15 +57,33 @@ export const filterEventsByAbi = (
|
||||
const eventHash = web3.eth.abi.encodeEventSignature(eventAbi)
|
||||
const events = txReceipt.logs.filter(e => e.address === bridgeAddress && e.topics[0] === eventHash)
|
||||
|
||||
if (!eventAbi || !eventAbi.inputs || !eventAbi.inputs.length) {
|
||||
return []
|
||||
}
|
||||
const inputs = eventAbi.inputs
|
||||
return events.map(e => {
|
||||
let decodedLogs: { [p: string]: string } = {
|
||||
messageId: '',
|
||||
encodedData: ''
|
||||
const { messageId, encodedData } = web3.eth.abi.decodeLog(inputs, e.data, [e.topics[1]])
|
||||
let sender, executor, obToken, obReceiver
|
||||
if (encodedData.length >= 160) {
|
||||
sender = `0x${encodedData.slice(66, 106)}`
|
||||
executor = `0x${encodedData.slice(106, 146)}`
|
||||
const dataOffset =
|
||||
160 + (parseInt(encodedData.slice(154, 156), 16) + parseInt(encodedData.slice(156, 158), 16)) * 2 + 8
|
||||
if (encodedData.length >= dataOffset + 64) {
|
||||
obToken = `0x${encodedData.slice(dataOffset + 24, dataOffset + 64)}`
|
||||
}
|
||||
if (encodedData.length >= dataOffset + 128) {
|
||||
obReceiver = `0x${encodedData.slice(dataOffset + 88, dataOffset + 128)}`
|
||||
}
|
||||
}
|
||||
if (eventAbi && eventAbi.inputs && eventAbi.inputs.length) {
|
||||
decodedLogs = web3.eth.abi.decodeLog(eventAbi.inputs, e.data, [e.topics[1]])
|
||||
return {
|
||||
id: messageId || '',
|
||||
data: encodedData || '',
|
||||
sender,
|
||||
executor,
|
||||
obToken,
|
||||
obReceiver
|
||||
}
|
||||
return { id: decodedLogs.messageId, data: decodedLogs.encodedData }
|
||||
})
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user