From ee483a98e40dbd82c08711449c55000bedf7fffc Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 10 Oct 2019 16:47:21 +0400 Subject: [PATCH] refactor tx gas eestimation method to one functions which supports both execution and approval --- src/logic/safe/transactions/gasNew.js | 64 +++++++++---------- .../screens/ReviewCustomTx/index.jsx | 4 +- .../SendModal/screens/ReviewTx/index.jsx | 4 +- .../ChangeThreshold/index.jsx | 4 +- 4 files changed, 36 insertions(+), 40 deletions(-) diff --git a/src/logic/safe/transactions/gasNew.js b/src/logic/safe/transactions/gasNew.js index 05d86336..df804488 100644 --- a/src/logic/safe/transactions/gasNew.js +++ b/src/logic/safe/transactions/gasNew.js @@ -1,57 +1,53 @@ // @flow import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json' import { getWeb3, getAccountFrom } from '~/logic/wallets/getWeb3' -import { type Operation } from '~/logic/safe/transactions' import { calculateGasOf, calculateGasPrice } from '~/logic/wallets/ethTransactions' import { ZERO_ADDRESS } from '~/logic/wallets/ethAddresses' +import { type Transaction } from '~/routes/safe/store/models/transaction' import { CALL } from '.' -export const estimateApprovalTxGasCosts = async (safeAddress: string, to: string, data: string): Promise => { +export const estimateTxGasCosts = async ( + safeAddress: string, + to: string, + data: string, + tx?: Transaction, +): Promise => { try { const web3 = getWeb3() const from = await getAccountFrom(web3) const safeInstance = new web3.eth.Contract(GnosisSafeSol.abi, safeAddress) const nonce = await safeInstance.methods.nonce().call() - const txHash = await safeInstance.methods - .getTransactionHash(to, 0, data, CALL, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, nonce) - .call({ - from, - }) - const approvalData = await safeInstance.methods.approveHash(txHash).encodeABI() - const gas = await calculateGasOf(approvalData, from, safeAddress) - const gasPrice = await calculateGasPrice() + const threshold = await safeInstance.methods.getThreshold().call() - return gas * parseInt(gasPrice, 10) - } catch (err) { - console.error(`Error while estimating approval transaction gas costs: ${err}`) + const isExecution = (tx && tx.confirmations.size) || threshold === '1' - return 1000000000000000 - } -} + let txData + if (isExecution) { + // https://gnosis-safe.readthedocs.io/en/latest/contracts/signatures.html#pre-validated-signatures + const signatures = tx + || `0x000000000000000000000000${from.replace( + '0x', + '', + )}000000000000000000000000000000000000000000000000000000000000000001` + txData = await safeInstance.methods + .execTransaction(to, 0, data, CALL, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, signatures) + .encodeABI() + } else { + const txHash = await safeInstance.methods + .getTransactionHash(to, 0, data, CALL, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, nonce) + .call({ + from, + }) + txData = await safeInstance.methods.approveHash(txHash).encodeABI() + } -export const estimateExecuteTxGasCosts = async ( - safeInstance: any, - to: string, - valueInWei: number | string, - data: string, - operation: Operation, - nonce: string | number, - sender: string, - sigs: string, -): Promise => { - try { - const web3 = getWeb3() - const contract = new web3.eth.Contract(GnosisSafeSol.abi, safeInstance.address) - const executionData = await contract.methods - .execTransaction(to, valueInWei, data, operation, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS) - .encodeABI() - const gas = await calculateGasOf(executionData, sender, safeInstance.address) + const gas = await calculateGasOf(txData, from, safeAddress) const gasPrice = await calculateGasPrice() return gas * parseInt(gasPrice, 10) } catch (err) { console.error(`Error while estimating transaction execution gas costs: ${err}`) - return 0.001 + return 10000 } } diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx index 6c76da31..111e906e 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx @@ -16,7 +16,7 @@ import EtherscanBtn from '~/components/EtherscanBtn' import CopyBtn from '~/components/CopyBtn' import SafeInfo from '~/routes/safe/components/Balances/SendModal/SafeInfo' import { setImageToPlaceholder } from '~/routes/safe/components/Balances/utils' -import { estimateApprovalTxGasCosts } from '~/logic/safe/transactions/gasNew' +import { estimateTxGasCosts } from '~/logic/safe/transactions/gasNew' import { getWeb3 } from '~/logic/wallets/getWeb3' import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' import { getEthAsToken } from '~/logic/tokens/utils/tokenHelpers' @@ -57,7 +57,7 @@ const ReviewCustomTx = ({ const web3 = getWeb3() const { fromWei, toBN } = web3.utils - const estimatedGasCosts = await estimateApprovalTxGasCosts(safeAddress, tx.recipientAddress, tx.data.trim()) + const estimatedGasCosts = await estimateTxGasCosts(safeAddress, tx.recipientAddress, tx.data.trim()) const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') const formattedGasCosts = formatAmount(gasCostsAsEth) if (isCurrent) { diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx index 62452dee..4019fc8c 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx @@ -18,7 +18,7 @@ import Hairline from '~/components/layout/Hairline' import SafeInfo from '~/routes/safe/components/Balances/SendModal/SafeInfo' import { setImageToPlaceholder } from '~/routes/safe/components/Balances/utils' import { getStandardTokenContract, getHumanFriendlyToken } from '~/logic/tokens/store/actions/fetchTokens' -import { estimateApprovalTxGasCosts } from '~/logic/safe/transactions/gasNew' +import { estimateTxGasCosts } from '~/logic/safe/transactions/gasNew' import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' import { formatAmount } from '~/logic/tokens/utils/formatAmount' import { getWeb3 } from '~/logic/wallets/getWeb3' @@ -70,7 +70,7 @@ const ReviewTx = ({ txData = tokenInstance.contract.methods.transfer(tx.recipientAddress, 0).encodeABI() } - const estimatedGasCosts = await estimateApprovalTxGasCosts(safeAddress, txRecipient, txData) + const estimatedGasCosts = await estimateTxGasCosts(safeAddress, txRecipient, txData) const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') const formattedGasCosts = formatAmount(gasCostsAsEth) if (isCurrent) { diff --git a/src/routes/safe/components/Settings/ThresholdSettings/ChangeThreshold/index.jsx b/src/routes/safe/components/Settings/ThresholdSettings/ChangeThreshold/index.jsx index 55554423..37ab5e8f 100644 --- a/src/routes/safe/components/Settings/ThresholdSettings/ChangeThreshold/index.jsx +++ b/src/routes/safe/components/Settings/ThresholdSettings/ChangeThreshold/index.jsx @@ -21,7 +21,7 @@ import type { Owner } from '~/routes/safe/store/models/owner' import { getWeb3 } from '~/logic/wallets/getWeb3' import { formatAmount } from '~/logic/tokens/utils/formatAmount' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' -import { estimateApprovalTxGasCosts } from '~/logic/safe/transactions/gasNew' +import { estimateTxGasCosts } from '~/logic/safe/transactions/gasNew' import { styles } from './style' type Props = { @@ -48,7 +48,7 @@ const ChangeThreshold = ({ const safeInstance = await getGnosisSafeInstanceAt(safeAddress) const txData = safeInstance.contract.methods.changeThreshold('1').encodeABI() - const estimatedGasCosts = await estimateApprovalTxGasCosts(safeAddress, safeAddress, txData) + const estimatedGasCosts = await estimateTxGasCosts(safeAddress, safeAddress, txData) const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') const formattedGasCosts = formatAmount(gasCostsAsEth) if (isCurrent) {