diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Buttons/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Buttons/index.tsx
index 9f0f2b99..3b587995 100644
--- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Buttons/index.tsx
+++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Buttons/index.tsx
@@ -17,8 +17,15 @@ const Buttons = ({ onCallSubmit, onClose }) => {
const {
input: { value: contractAddress },
} = useField('contractAddress', { valid: true } as any)
- const { submitting, valid, validating, values } = useFormState({
- subscription: { submitting: true, valid: true, values: true, validating: true },
+ const { modifiedSinceLastSubmit, submitError, submitting, valid, validating, values } = useFormState({
+ subscription: {
+ modifiedSinceLastSubmit: true,
+ submitError: true,
+ submitting: true,
+ valid: true,
+ values: true,
+ validating: true,
+ },
})
const handleCallSubmit = async () => {
@@ -48,7 +55,13 @@ const Buttons = ({ onCallSubmit, onClose }) => {
className={classes.submitButton}
color="primary"
data-testid="review-tx-btn"
- disabled={submitting || validating || !valid || !method || (method as any).action === 'read'}
+ disabled={
+ submitting ||
+ validating ||
+ ((!valid || !!submitError) && !modifiedSinceLastSubmit) ||
+ !method ||
+ (method as any).action === 'read'
+ }
minWidth={140}
type="submit"
variant="contained"
diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/index.tsx
index 7cceae50..de34ffc0 100644
--- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/index.tsx
+++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/index.tsx
@@ -1,26 +1,23 @@
import { makeStyles } from '@material-ui/core/styles'
+import { FORM_ERROR } from 'final-form'
import React from 'react'
import { styles } from './style'
-
import GnoForm from 'src/components/forms/GnoForm'
import Block from 'src/components/layout/Block'
import Hairline from 'src/components/layout/Hairline'
import SafeInfo from 'src/routes/safe/components/Balances/SendModal/SafeInfo'
-import Buttons from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Buttons'
-import ContractABI from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ContractABI'
-import EthAddressInput from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/EthAddressInput'
-import EthValue from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/EthValue'
-import FormDivisor from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/FormDivisor'
-import Header from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Header'
-import MethodsDropdown from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/MethodsDropdown'
-import RenderInputParams from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/RenderInputParams'
-import RenderOutputParams from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/RenderOutputParams'
-import {
- abiExtractor,
- createTxObject,
- formMutators,
-} from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils'
+import Buttons from './Buttons'
+import ContractABI from './ContractABI'
+import EthAddressInput from './EthAddressInput'
+import EthValue from './EthValue'
+import FormDivisor from './FormDivisor'
+import FormErrorMessage from './FormErrorMessage'
+import Header from './Header'
+import MethodsDropdown from './MethodsDropdown'
+import RenderInputParams from './RenderInputParams'
+import RenderOutputParams from './RenderOutputParams'
+import { abiExtractor, createTxObject, formMutators } from './utils'
const useStyles = makeStyles(styles as any)
@@ -35,8 +32,21 @@ const ContractInteraction = ({ contractAddress, initialValues, onClose, onNext }
const handleSubmit = async ({ contractAddress, selectedMethod, value, ...values }) => {
if (value || (contractAddress && selectedMethod)) {
- const data = await createTxObject(selectedMethod, contractAddress, values).encodeABI()
- onNext({ contractAddress, data, selectedMethod, value, ...values })
+ try {
+ const txObject = createTxObject(selectedMethod, contractAddress, values)
+ const data = txObject.encodeABI()
+ await txObject.estimateGas()
+ onNext({ contractAddress, data, selectedMethod, value, ...values })
+ } catch (e) {
+ for (const key in values) {
+ if (values.hasOwnProperty(key) && values[key] === e.value) {
+ return { [key]: e.reason }
+ }
+ }
+
+ // .estimateGas() failed
+ return { [FORM_ERROR]: e.message }
+ }
}
}
@@ -62,11 +72,12 @@ const ContractInteraction = ({ contractAddress, initialValues, onClose, onNext }
onScannedValue={mutators.setContractAddress}
text="Contract Address*"
/>
-
+
+