diff --git a/packages/suite/src/support/messages.ts b/packages/suite/src/support/messages.ts index ec25117ef232..d33c6586e312 100644 --- a/packages/suite/src/support/messages.ts +++ b/packages/suite/src/support/messages.ts @@ -2131,6 +2131,14 @@ export default defineMessages({ defaultMessage: 'Unable to verify address history. Check that the address is correct.', id: 'TR_ETH_ADDRESS_CANT_VERIFY_HISTORY', }, + TR_ETH_ADDRESS_IS_CONTRACT: { + defaultMessage: 'It is a contract address. Are you sure you want to send to this address?', + id: 'TR_ETH_ADDRESS_IS_CONTRACT', + }, + TR_I_UNDERSTAND_THE_RISK: { + defaultMessage: 'I understand the risk', + id: 'TR_I_UNDERSTAND_THE_RISK', + }, TR_NEEDS_ATTENTION_BOOTLOADER: { defaultMessage: 'Trezor is in Bootloader mode.', id: 'TR_NEEDS_ATTENTION_BOOTLOADER', diff --git a/packages/suite/src/views/wallet/send/Outputs/Address.tsx b/packages/suite/src/views/wallet/send/Outputs/Address.tsx index 9bf1d6b3a0b5..f5e59e33e527 100644 --- a/packages/suite/src/views/wallet/send/Outputs/Address.tsx +++ b/packages/suite/src/views/wallet/send/Outputs/Address.tsx @@ -67,6 +67,7 @@ export const Address = ({ output, outputId, outputsCount }: AddressProps) => { const [addressDeprecatedUrl, setAddressDeprecatedUrl] = useState>(undefined); const [hasAddressChecksummed, setHasAddressChecksummed] = useState(); + let contractAddressWarningDismissed = false; const dispatch = useDispatch(); const { device } = useDevice(); const { @@ -80,6 +81,7 @@ export const Address = ({ output, outputId, outputsCount }: AddressProps) => { metadataEnabled, watch, setDraftSaveRequest, + trigger, } = useSendFormContext(); const { translationString } = useTranslation(); const { descriptor, networkType, symbol } = account; @@ -185,6 +187,14 @@ export const Address = ({ output, outputId, outputsCount }: AddressProps) => { }), text: translationString('TR_CONVERT_TO_LOWERCASE'), }; + case 'contract': + return { + onClick: () => { + contractAddressWarningDismissed = true; + trigger(inputName); + }, + text: translationString('TR_I_UNDERSTAND_THE_RISK'), + }; default: return undefined; } @@ -260,6 +270,24 @@ export const Address = ({ output, outputId, outputsCount }: AddressProps) => { return translationString('TR_ETH_ADDRESS_CANT_VERIFY_HISTORY'); } }, + contract: async (address: string) => { + if (networkType === 'ethereum' && !contractAddressWarningDismissed) { + if (isOnline) { + const params = { + descriptor: address, + coin: symbol, + }; + const result = await TrezorConnect.getAccountInfo(params); + + if (result.success) { + const isContract = result.payload.misc?.contractInfo; + if (isContract) { + return translationString('TR_ETH_ADDRESS_IS_CONTRACT'); + } + } + } + } + }, rippleToSelf: (value: string) => { if (networkType === 'ripple' && value === descriptor) { return translationString('RECIPIENT_CANNOT_SEND_TO_MYSELF');