From 534aefb236ea557c6150a3cf3dd00318e434dce0 Mon Sep 17 00:00:00 2001 From: Nicole O'Brien Date: Thu, 23 May 2024 12:26:59 +0100 Subject: [PATCH 1/3] initial EvmSmartContractAlert --- .../EvmSmartContractAlert.svelte | 38 ++++++++++++++++ .../components/evm-transactions/index.ts | 1 + .../popups/EvmTransactionFromDappPopup.svelte | 44 +++---------------- .../parsed-contract-data.interface.ts | 1 + ...rseSmartContractDataFromTransactionData.ts | 42 +++++++++++++----- 5 files changed, 76 insertions(+), 50 deletions(-) create mode 100644 packages/desktop/components/evm-transactions/EvmSmartContractAlert.svelte diff --git a/packages/desktop/components/evm-transactions/EvmSmartContractAlert.svelte b/packages/desktop/components/evm-transactions/EvmSmartContractAlert.svelte new file mode 100644 index 0000000000..bcfd60d05a --- /dev/null +++ b/packages/desktop/components/evm-transactions/EvmSmartContractAlert.svelte @@ -0,0 +1,38 @@ + + + + {#if parsedSmartContract.parsedMethod} + ({ + key: input.name, + value: String(input.value) ?? localize('general.unknown'), + }))} + /> + {:else} +
+ {/if} + diff --git a/packages/desktop/components/evm-transactions/index.ts b/packages/desktop/components/evm-transactions/index.ts index 80ec42f64a..b500a4327a 100644 --- a/packages/desktop/components/evm-transactions/index.ts +++ b/packages/desktop/components/evm-transactions/index.ts @@ -1,2 +1,3 @@ +export { default as EvmSmartContractAlert } from './EvmSmartContractAlert.svelte' export { default as EvmTokenApprovalAlert } from './EvmTokenApprovalAlert.svelte' export { default as EvmTransactionAlert } from './EvmTransactionAlert.svelte' diff --git a/packages/desktop/components/popup/popups/EvmTransactionFromDappPopup.svelte b/packages/desktop/components/popup/popups/EvmTransactionFromDappPopup.svelte index 7fba01cac5..784fd28641 100644 --- a/packages/desktop/components/popup/popups/EvmTransactionFromDappPopup.svelte +++ b/packages/desktop/components/popup/popups/EvmTransactionFromDappPopup.svelte @@ -2,10 +2,10 @@ import { DappVerification, RpcMethod } from '@auxiliary/wallet-connect/enums' import { IConnectedDapp } from '@auxiliary/wallet-connect/interface' import { CallbackParameters } from '@auxiliary/wallet-connect/types' - import { Table } from '@bloomwalletio/ui' + import { EvmTokenApprovalAlert } from '@components' + import { EvmSmartContractAlert } from '@components/evm-transactions' import { IAccountState } from '@core/account' import { getSelectedAccount, selectedAccount } from '@core/account/stores' - import { openUrlInBrowser } from '@core/app' import { handleError } from '@core/error/handlers' import { localize } from '@core/i18n' import { @@ -14,9 +14,11 @@ getHexEncodedTransaction, parseSmartContractDataFromTransactionData, } from '@core/layer-2' + import { ParsedSmartContractType } from '@core/layer-2/enums/parsed-smart-contract-type.enum' import { EvmTransactionData } from '@core/layer-2/types' + import { ParsedSmartContractData } from '@core/layer-2/types/parsed-smart-contract-data.type' import { LedgerAppName } from '@core/ledger' - import { ExplorerEndpoint, IEvmNetwork, getExplorerUrl } from '@core/network' + import { IEvmNetwork } from '@core/network' import { getNftByIdForAccount } from '@core/nfts/stores' import { checkActiveProfileAuth } from '@core/profile/actions' import { getActiveProfileId } from '@core/profile/stores' @@ -27,12 +29,9 @@ import { PopupId, closePopup, modifyPopupState, openPopup } from '@desktop/auxiliary/popup' import { LegacyTransaction } from '@ethereumjs/tx' import { DappInfo, TransactionAssetSection } from '@ui' - import { EvmTransactionAlert, EvmTokenApprovalAlert } from '@components' import { EvmTransactionDetails } from '@views/dashboard/send-flow/views/components' import { onDestroy, onMount } from 'svelte' import PopupTemplate from '../PopupTemplate.svelte' - import { ParsedSmartContractType } from '@core/layer-2/enums/parsed-smart-contract-type.enum' - import { ParsedSmartContractData } from '@core/layer-2/types/parsed-smart-contract-data.type' export let preparedTransaction: EvmTransactionData export let evmNetwork: IEvmNetwork @@ -185,11 +184,6 @@ closePopup({ callOnCancel: true }) } - function onExplorerClick(contractAddress: string): void { - const url = getExplorerUrl(evmNetwork.id, ExplorerEndpoint.Address, contractAddress) - openUrlInBrowser(url) - } - let intervalId: NodeJS.Timeout onMount(async () => { await setGasPrices() @@ -250,33 +244,7 @@ {:else if parsedData?.type === ParsedSmartContractType.SmartContract}
- -
onExplorerClick(String(preparedTransaction.to)), - }, - { key: localize('general.methodName'), value: parsedData.parsedMethod?.name }, - { - key: localize('general.parameters'), - value: parsedData?.parsedMethod?.inputs.reduce((acc, input) => { - acc[input.name] = input.value - return acc - }, {}), - }, - { key: localize('general.data'), value: String(preparedTransaction.data), copyable: true }, - ]} - /> - + {/if} (ISC_SANDBOX_ABI, network.provider) - const decodedData = iscMagicDecoder.decodeData(data) + const decodedData = iscMagicDecoder.decodeData(rawData) if (!decodedData) { return undefined } - const rawMethod = data.substring(0, 10) + const rawMethod = rawData.substring(0, 10) const parsedMethod: IParsedMethod = { name: decodedData.name, inputs: Object.values(decodedData.inputs), @@ -79,6 +79,7 @@ function parseSmartContractDataWithIscMagicAbi( tokenId: nativeToken.ID.data, rawAmount, parsedMethod, + rawData, rawMethod, recipientAddress: HEX_PREFIX + agentId?.substring(agentId.length - 40), } @@ -88,11 +89,18 @@ function parseSmartContractDataWithIscMagicAbi( standard: NftStandard.Irc27, nftId, parsedMethod, + rawData, rawMethod, recipientAddress: HEX_PREFIX + agentId?.substring(agentId.length - 40), } } else { - return { type: ParsedSmartContractType.SmartContract, recipientAddress, rawMethod, parsedMethod } + return { + type: ParsedSmartContractType.SmartContract, + recipientAddress, + rawData, + rawMethod, + parsedMethod, + } } } case 'send': { @@ -113,6 +121,7 @@ function parseSmartContractDataWithIscMagicAbi( standard: TokenStandard.Irc30, tokenId: nativeToken.ID.data, rawAmount: BigInt(nativeToken.amount), + rawData, rawMethod, parsedMethod, additionalBaseTokenAmount: baseTokenAmount, @@ -124,6 +133,7 @@ function parseSmartContractDataWithIscMagicAbi( type: ParsedSmartContractType.NftTransfer, standard: NftStandard.Irc27, nftId, + rawData, rawMethod, parsedMethod, additionalBaseTokenAmount: baseTokenAmount, @@ -133,32 +143,33 @@ function parseSmartContractDataWithIscMagicAbi( return { type: ParsedSmartContractType.CoinTransfer, rawAmount: network.denormaliseAmount(baseTokenAmount), + rawData, rawMethod, parsedMethod, recipientAddress, // for now, set it to the magic contract address } } - return { type: ParsedSmartContractType.SmartContract, recipientAddress, rawMethod, parsedMethod } + return { type: ParsedSmartContractType.SmartContract, recipientAddress, rawData, rawMethod, parsedMethod } } default: - return { type: ParsedSmartContractType.SmartContract, recipientAddress, rawMethod, parsedMethod } + return { type: ParsedSmartContractType.SmartContract, recipientAddress, rawData, rawMethod, parsedMethod } } } function parseSmartContractDataWithErc20Abi( network: IEvmNetwork, - data: string, + rawData: string, recipientAddress: string ): ParsedSmartContractData | undefined { const erc20Decoder = new AbiDecoder(ERC20_ABI, network.provider) - const decodedData = erc20Decoder.decodeData(data) + const decodedData = erc20Decoder.decodeData(rawData) if (!decodedData) { return undefined } - const rawMethod = data.substring(0, 10) + const rawMethod = rawData.substring(0, 10) const parsedMethod: IParsedMethod = { name: decodedData.name, inputs: Object.values(decodedData.inputs), @@ -171,6 +182,7 @@ function parseSmartContractDataWithErc20Abi( standard: TokenStandard.Erc20, tokenId: recipientAddress, rawAmount: BigInt(decodedData.inputs._value.value), + rawData, rawMethod, parsedMethod, recipientAddress: decodedData.inputs._to.value, @@ -183,6 +195,7 @@ function parseSmartContractDataWithErc20Abi( tokenId: recipientAddress, spender: decodedData.inputs._spender.value, rawAmount: BigInt(decodedData.inputs._value.value), + rawData, rawMethod, parsedMethod, recipientAddress, @@ -191,6 +204,7 @@ function parseSmartContractDataWithErc20Abi( default: { return { type: ParsedSmartContractType.SmartContract, + rawData, rawMethod, parsedMethod, recipientAddress, @@ -201,17 +215,17 @@ function parseSmartContractDataWithErc20Abi( function parseSmartContractDataWithErc721Abi( network: IEvmNetwork, - data: string, + rawData: string, recipientAddress: string ): ParsedSmartContractData | undefined { const erc721Decoder = new AbiDecoder(ERC721_ABI, network.provider) - const decodedData = erc721Decoder.decodeData(data) + const decodedData = erc721Decoder.decodeData(rawData) if (!decodedData) { return undefined } - const rawMethod = data.substring(0, 10) + const rawMethod = rawData.substring(0, 10) const parsedMethod: IParsedMethod = { name: decodedData.name, inputs: Object.values(decodedData.inputs), @@ -226,6 +240,7 @@ function parseSmartContractDataWithErc721Abi( type: ParsedSmartContractType.NftTransfer, standard: NftStandard.Erc721, nftId: `${recipientAddress}:${inputs.tokenId.value}`, + rawData, rawMethod, parsedMethod, recipientAddress: inputs.to.value, @@ -236,6 +251,7 @@ function parseSmartContractDataWithErc721Abi( return { type: ParsedSmartContractType.SmartContract, recipientAddress, + rawData, rawMethod, parsedMethod, } @@ -275,6 +291,7 @@ function parseSmartContractDataWithMethodRegistry( return { type: ParsedSmartContractType.SmartContract, recipientAddress, + rawData, rawMethod: fourBytePrefix, parsedMethod: { name, inputs }, } @@ -282,6 +299,7 @@ function parseSmartContractDataWithMethodRegistry( return { type: ParsedSmartContractType.SmartContract, recipientAddress, + rawData, rawMethod: fourBytePrefix, } } From 4381826dffc829f1aa57b17180161c87cac455e0 Mon Sep 17 00:00:00 2001 From: Nicole O'Brien Date: Thu, 23 May 2024 14:55:01 +0100 Subject: [PATCH 2/3] Add partially verified smart contract alert --- .../EvmSmartContractAlert.svelte | 34 +++++++++++++------ packages/shared/src/locales/en.json | 3 +- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/packages/desktop/components/evm-transactions/EvmSmartContractAlert.svelte b/packages/desktop/components/evm-transactions/EvmSmartContractAlert.svelte index bcfd60d05a..53e37ea77d 100644 --- a/packages/desktop/components/evm-transactions/EvmSmartContractAlert.svelte +++ b/packages/desktop/components/evm-transactions/EvmSmartContractAlert.svelte @@ -7,24 +7,36 @@ export let parsedSmartContract: IParsedSmartContractData export let networkId: EvmNetworkId + + function getMethodSignature(parsedMethod) { + const parameterSignatures = parsedMethod.inputs.map((input) => `${input.name} ${input.type}`) + return `${parsedMethod.name}(${parameterSignatures.join(', ')})` + } - - {#if parsedSmartContract.parsedMethod} +{#if parsedSmartContract.parsedMethod} +
({ key: input.name, value: String(input.value) ?? localize('general.unknown'), }))} /> - {:else} + +{:else} +
- {/if} - + +{/if} diff --git a/packages/shared/src/locales/en.json b/packages/shared/src/locales/en.json index da9a6eae6a..7dbd64d424 100644 --- a/packages/shared/src/locales/en.json +++ b/packages/shared/src/locales/en.json @@ -1108,7 +1108,8 @@ "smartContractCall": { "title": "Smart contract call to {contractAddress}", "unableToVerify": "Bloom is unable to verify the smart contract call. Only proceed with apps you trust.", - "viewSmartContract": "View Smart Contract", + "partiallyVerified": "Bloom has partially verified the smart contract call, proceed with apps you trust.", + "viewSmartContract": "View Contract", "action": "Confirm", "success": "Smart contract call to {recipient}" }, From a571664c2e0889edecf79ad3a3876ce85abd2d79 Mon Sep 17 00:00:00 2001 From: Nicole O'Brien Date: Thu, 23 May 2024 15:47:09 +0100 Subject: [PATCH 3/3] improve wording --- packages/shared/src/locales/en.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/shared/src/locales/en.json b/packages/shared/src/locales/en.json index 7dbd64d424..a475917af7 100644 --- a/packages/shared/src/locales/en.json +++ b/packages/shared/src/locales/en.json @@ -1107,8 +1107,8 @@ }, "smartContractCall": { "title": "Smart contract call to {contractAddress}", - "unableToVerify": "Bloom is unable to verify the smart contract call. Only proceed with apps you trust.", - "partiallyVerified": "Bloom has partially verified the smart contract call, proceed with apps you trust.", + "unableToVerify": "Bloom is unable to parse the smart contract data, only proceed with apps you trust.", + "partiallyVerified": "Bloom has partially parsed the smart contract data, proceed with apps you trust.", "viewSmartContract": "View Contract", "action": "Confirm", "success": "Smart contract call to {recipient}"