From 10f1891f8fff4b2379f4cf8ac5eadbe92931024f Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Thu, 14 Jan 2021 08:36:55 -0300 Subject: [PATCH] (Fix) - Calculates gas for SpendingLimit transactions (#1773) * Bug: Use link tag instead of javascript navigation in apps list (#1770) * Use list instead of programmable navigation * add declaration for styled-components theme * (Fix) - Calculates gas for SpendingLimit transactions (#1773) * Calculates gas for spendingLimit transactions * Adds TransactionFees component inside UpdateSafeModal * Fix send collectible gas calculation Co-authored-by: Mikhail Mikheev --- src/logic/hooks/useEstimateTransactionGas.tsx | 26 +++++--- src/logic/safe/utils/upgradeSafe.ts | 17 +---- .../screens/ReviewCollectible/index.tsx | 2 +- .../SendModal/screens/ReviewTx/index.tsx | 1 + .../components/Settings/SafeDetails/index.tsx | 2 +- .../Settings/UpdateSafeModal/index.tsx | 65 ++++++++++++++++--- .../Settings/UpdateSafeModal/style.ts | 3 +- 7 files changed, 82 insertions(+), 34 deletions(-) diff --git a/src/logic/hooks/useEstimateTransactionGas.tsx b/src/logic/hooks/useEstimateTransactionGas.tsx index 0acb86d8..ba53f610 100644 --- a/src/logic/hooks/useEstimateTransactionGas.tsx +++ b/src/logic/hooks/useEstimateTransactionGas.tsx @@ -21,6 +21,7 @@ import { List } from 'immutable' import { Confirmation } from 'src/logic/safe/store/models/types/confirmation' import { checkIfOffChainSignatureIsPossible } from 'src/logic/safe/safeTxSigner' import { ZERO_ADDRESS } from 'src/logic/wallets/ethAddresses' +import { sameString } from 'src/utils/strings' export enum EstimationStatus { LOADING = 'LOADING', @@ -28,13 +29,19 @@ export enum EstimationStatus { SUCCESS = 'SUCCESS', } -const checkIfTxIsExecution = (threshold: number, preApprovingOwner?: string, txConfirmations?: number): boolean => - txConfirmations === threshold || !!preApprovingOwner || threshold === 1 +const checkIfTxIsExecution = ( + threshold: number, + preApprovingOwner?: string, + txConfirmations?: number, + txType?: string, +): boolean => + txConfirmations === threshold || !!preApprovingOwner || threshold === 1 || sameString(txType, 'spendingLimit') -const checkIfTxIsApproveAndExecution = (threshold: number, txConfirmations: number): boolean => - txConfirmations + 1 === threshold +const checkIfTxIsApproveAndExecution = (threshold: number, txConfirmations: number, txType?: string): boolean => + txConfirmations + 1 === threshold || sameString(txType, 'spendingLimit') -const checkIfTxIsCreation = (txConfirmations: number): boolean => txConfirmations === 0 +const checkIfTxIsCreation = (txConfirmations: number, txType?: string): boolean => + txConfirmations === 0 && !sameString(txType, 'spendingLimit') type TransactionEstimationProps = { txData: string @@ -115,6 +122,7 @@ type UseEstimateTransactionGasProps = { preApprovingOwner?: string operation?: number safeTxGas?: number + txType?: string } type TransactionGasEstimationResult = { @@ -136,6 +144,7 @@ export const useEstimateTransactionGas = ({ preApprovingOwner, operation, safeTxGas, + txType, }: UseEstimateTransactionGasProps): TransactionGasEstimationResult => { const [gasEstimation, setGasEstimation] = useState({ txEstimationExecutionStatus: EstimationStatus.LOADING, @@ -159,9 +168,9 @@ export const useEstimateTransactionGas = ({ return } - const isExecution = checkIfTxIsExecution(Number(threshold), preApprovingOwner, txConfirmations?.size) - const isCreation = checkIfTxIsCreation(txConfirmations?.size || 0) - const approvalAndExecution = checkIfTxIsApproveAndExecution(Number(threshold), txConfirmations?.size || 0) + const isExecution = checkIfTxIsExecution(Number(threshold), preApprovingOwner, txConfirmations?.size, txType) + const isCreation = checkIfTxIsCreation(txConfirmations?.size || 0, txType) + const approvalAndExecution = checkIfTxIsApproveAndExecution(Number(threshold), txConfirmations?.size || 0, txType) try { const isOffChainSignature = checkIfOffChainSignatureIsPossible(isExecution, smartContractWallet, safeVersion) @@ -235,6 +244,7 @@ export const useEstimateTransactionGas = ({ safeVersion, smartContractWallet, safeTxGas, + txType, ]) return gasEstimation diff --git a/src/logic/safe/utils/upgradeSafe.ts b/src/logic/safe/utils/upgradeSafe.ts index 4f3dea18..53caa747 100644 --- a/src/logic/safe/utils/upgradeSafe.ts +++ b/src/logic/safe/utils/upgradeSafe.ts @@ -6,7 +6,6 @@ import { SAFE_MASTER_COPY_ADDRESS, getGnosisSafeInstanceAt, } from 'src/logic/contracts/safeContracts' -import { DELEGATE_CALL } from 'src/logic/safe/transactions' import { getWeb3 } from 'src/logic/wallets/getWeb3' import { MultiSend } from 'src/types/contracts/MultiSend.d' @@ -49,7 +48,7 @@ export const getEncodedMultiSendCallData = (txs: MultiSendTx[], web3: Web3): str return encodedMultiSendCallData } -export const upgradeSafeToLatestVersion = async (safeAddress: string, createTransaction): Promise => { +export const getUpgradeSafeTransactionHash = async (safeAddress: string): Promise => { const safeInstance = await getGnosisSafeInstanceAt(safeAddress) const fallbackHandlerTxData = safeInstance.methods.setFallbackHandler(DEFAULT_FALLBACK_HANDLER_ADDRESS).encodeABI() const updateSafeTxData = safeInstance.methods.changeMasterCopy(SAFE_MASTER_COPY_ADDRESS).encodeABI() @@ -69,17 +68,5 @@ export const upgradeSafeToLatestVersion = async (safeAddress: string, createTran ] const web3 = getWeb3() - const encodeMultiSendCallData = getEncodedMultiSendCallData(txs, web3) - createTransaction({ - safeAddress, - to: MULTI_SEND_ADDRESS, - valueInWei: 0, - txData: encodeMultiSendCallData, - notifiedTransaction: 'STANDARD_TX', - enqueueSnackbar: () => {}, - closeSnackbar: () => {}, - operation: DELEGATE_CALL, - }) - - return + return getEncodedMultiSendCallData(txs, web3) } diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewCollectible/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewCollectible/index.tsx index 63d4c942..a5cf3a00 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewCollectible/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewCollectible/index.tsx @@ -64,7 +64,7 @@ const ReviewCollectible = ({ onClose, onPrev, tx }: Props): React.ReactElement = isCreation, } = useEstimateTransactionGas({ txData: data, - txRecipient: tx.recipientAddress, + txRecipient: tx.assetAddress, }) useEffect(() => { diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.tsx index 8dbb6b3c..f6895a9e 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.tsx @@ -120,6 +120,7 @@ const ReviewTx = ({ onClose, onPrev, tx }: ReviewTxProps): React.ReactElement => } = useEstimateTransactionGas({ txData: data, txRecipient, + txType: tx.txType, }) const submitTx = async () => { diff --git a/src/routes/safe/components/Settings/SafeDetails/index.tsx b/src/routes/safe/components/Settings/SafeDetails/index.tsx index d071c122..cb74ce86 100644 --- a/src/routes/safe/components/Settings/SafeDetails/index.tsx +++ b/src/routes/safe/components/Settings/SafeDetails/index.tsx @@ -19,7 +19,7 @@ import enqueueSnackbar from 'src/logic/notifications/store/actions/enqueueSnackb import { getNotificationsFromTxType, enhanceSnackbarForAction } from 'src/logic/notifications' import { sameAddress } from 'src/logic/wallets/ethAddresses' import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions' -import UpdateSafeModal from 'src/routes/safe/components/Settings/UpdateSafeModal' +import { UpdateSafeModal } from 'src/routes/safe/components/Settings/UpdateSafeModal' import { grantedSelector } from 'src/routes/safe/container/selector' import updateSafe from 'src/logic/safe/store/actions/updateSafe' import Link from 'src/components/layout/Link' diff --git a/src/routes/safe/components/Settings/UpdateSafeModal/index.tsx b/src/routes/safe/components/Settings/UpdateSafeModal/index.tsx index 3d370047..d0023166 100644 --- a/src/routes/safe/components/Settings/UpdateSafeModal/index.tsx +++ b/src/routes/safe/components/Settings/UpdateSafeModal/index.tsx @@ -1,9 +1,7 @@ import IconButton from '@material-ui/core/IconButton' import Close from '@material-ui/icons/Close' -import { withStyles } from '@material-ui/styles' -import React from 'react' +import React, { useEffect, useState } from 'react' import { useDispatch } from 'react-redux' -import { bindActionCreators } from 'redux' import { styles } from './style' @@ -13,17 +11,61 @@ import Button from 'src/components/layout/Button' import Hairline from 'src/components/layout/Hairline' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' -import { upgradeSafeToLatestVersion } from 'src/logic/safe/utils/upgradeSafe' +import { getUpgradeSafeTransactionHash } from 'src/logic/safe/utils/upgradeSafe' import createTransaction from 'src/logic/safe/store/actions/createTransaction' +import { makeStyles } from '@material-ui/core' +import { TransactionFees } from 'src/components/TransactionsFees' +import { useEstimateTransactionGas } from 'src/logic/hooks/useEstimateTransactionGas' +import { MULTI_SEND_ADDRESS } from 'src/logic/contracts/safeContracts' +import { DELEGATE_CALL } from 'src/logic/safe/transactions' +import { EMPTY_DATA } from 'src/logic/wallets/ethTransactions' -const UpdateSafeModal = ({ classes, onClose, safeAddress }) => { +const useStyles = makeStyles(styles) + +type Props = { + onClose: () => void + safeAddress: string +} + +export const UpdateSafeModal = ({ onClose, safeAddress }: Props): React.ReactElement => { + const classes = useStyles() const dispatch = useDispatch() + const [multiSendCallData, setMultiSendCallData] = useState(EMPTY_DATA) + + useEffect(() => { + const calculateUpgradeSafeModal = async () => { + const encodeMultiSendCallData = await getUpgradeSafeTransactionHash(safeAddress) + setMultiSendCallData(encodeMultiSendCallData) + } + calculateUpgradeSafeModal() + }, [safeAddress]) + const handleSubmit = async () => { // Call the update safe method - await upgradeSafeToLatestVersion(safeAddress, bindActionCreators(createTransaction, dispatch)) + dispatch( + createTransaction({ + safeAddress, + to: MULTI_SEND_ADDRESS, + valueInWei: '0', + txData: multiSendCallData, + notifiedTransaction: 'STANDARD_TX', + operation: DELEGATE_CALL, + }), + ) onClose() } + const { + gasCostFormatted, + txEstimationExecutionStatus, + isExecution, + isCreation, + isOffChainSignature, + } = useEstimateTransactionGas({ + txData: multiSendCallData, + txRecipient: safeAddress, + }) + return ( <> @@ -56,6 +98,15 @@ const UpdateSafeModal = ({ classes, onClose, safeAddress }) => { have to confirm the update in case more than one confirmation is required for this Safe. + + + @@ -72,5 +123,3 @@ const UpdateSafeModal = ({ classes, onClose, safeAddress }) => { ) } - -export default withStyles(styles as any)(UpdateSafeModal) diff --git a/src/routes/safe/components/Settings/UpdateSafeModal/style.ts b/src/routes/safe/components/Settings/UpdateSafeModal/style.ts index e0f9c000..e3f31c05 100644 --- a/src/routes/safe/components/Settings/UpdateSafeModal/style.ts +++ b/src/routes/safe/components/Settings/UpdateSafeModal/style.ts @@ -1,6 +1,7 @@ import { lg, md, secondaryText, sm } from 'src/theme/variables' +import { createStyles } from '@material-ui/core' -export const styles = () => ({ +export const styles = createStyles({ heading: { padding: `${sm} ${lg}`, justifyContent: 'space-between',