From ef3d9b4b0fb0b4323a07f515f278cd50215929b7 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 9 Sep 2019 16:24:32 +0400 Subject: [PATCH] calculate gas for deploying a safe --- src/logic/contracts/safeContracts.js | 17 +++++++ src/routes/open/components/Layout.jsx | 4 +- .../components/ReviewInformation/index.jsx | 49 ++++++++++++++----- src/routes/open/container/Open.jsx | 5 +- 4 files changed, 62 insertions(+), 13 deletions(-) diff --git a/src/logic/contracts/safeContracts.js b/src/logic/contracts/safeContracts.js index 32e4e5fc..7c757acf 100644 --- a/src/logic/contracts/safeContracts.js +++ b/src/logic/contracts/safeContracts.js @@ -75,6 +75,23 @@ export const deploySafeContract = async (safeAccounts: string[], numConfirmation return proxyFactoryMaster.createProxy(safeMaster.address, gnosisSafeData, { from: userAccount, gas, gasPrice }) } +export const estimateGasForDeployingSafe = async ( + safeAccounts: string[], + numConfirmations: number, + userAccount: string, +) => { + const gnosisSafeData = await safeMaster.contract.methods + .setup(safeAccounts, numConfirmations, ZERO_ADDRESS, '0x', ZERO_ADDRESS, 0, ZERO_ADDRESS) + .encodeABI() + const proxyFactoryData = proxyFactoryMaster.contract.methods + .createProxy(safeMaster.address, gnosisSafeData) + .encodeABI() + const gas = await calculateGasOf(proxyFactoryData, userAccount, proxyFactoryMaster.address) + const gasPrice = await calculateGasPrice() + + return gas * parseInt(gasPrice, 10) +} + export const getGnosisSafeInstanceAt = async (safeAddress: string) => { const web3 = getWeb3() const GnosisSafe = await getGnosisSafeContract(web3) diff --git a/src/routes/open/components/Layout.jsx b/src/routes/open/components/Layout.jsx index 800c43aa..75fe9fba 100644 --- a/src/routes/open/components/Layout.jsx +++ b/src/routes/open/components/Layout.jsx @@ -69,7 +69,9 @@ const Layout = ({ > {SafeNameField} {SafeOwnersFields} - {Review} + + {Review} + ) : ( diff --git a/src/routes/open/components/ReviewInformation/index.jsx b/src/routes/open/components/ReviewInformation/index.jsx index 056e72c0..fd4157b6 100644 --- a/src/routes/open/components/ReviewInformation/index.jsx +++ b/src/routes/open/components/ReviewInformation/index.jsx @@ -3,6 +3,7 @@ import * as React from 'react' import classNames from 'classnames' import { withStyles } from '@material-ui/core/styles' import OpenInNew from '@material-ui/icons/OpenInNew' +import { estimateGasForDeployingSafe } from '~/logic/contracts/safeContracts' import { getNamesFrom, getAccountsFrom } from '~/routes/open/utils/safeDataExtractor' import Block from '~/components/layout/Block' import Identicon from '~/components/Identicon' @@ -15,9 +16,11 @@ import { sm, md, lg, border, secondary, background, } from '~/theme/variables' import Hairline from '~/components/layout/Hairline' -import { getEtherScanLink } from '~/logic/wallets/getWeb3' +import { getEtherScanLink, getWeb3 } from '~/logic/wallets/getWeb3' import { FIELD_NAME, FIELD_CONFIRMATIONS, getNumOwnersFrom } from '../fields' +const { useEffect, useState } = React + const openIconStyle = { height: '16px', color: secondary, @@ -65,22 +68,42 @@ const styles = () => ({ }, }) -type LayoutProps = { +type Props = { network: string, -} - -type Props = LayoutProps & { values: Object, classes: Object, + userAccount: string, } -const ReviewComponent = ({ values, classes, network }: Props) => { +const ReviewComponent = ({ + values, classes, network, userAccount, +}: Props) => { + const [gasCosts, setGasCosts] = useState('0.00') const names = getNamesFrom(values) const addresses = getAccountsFrom(values) const numOwners = getNumOwnersFrom(values) + useEffect(() => { + let isCurrent = true + const estimateGas = async () => { + const web3 = getWeb3() + const { fromWei, toBN } = web3.utils + const estimatedGasCosts = await estimateGasForDeployingSafe(addresses, numOwners, userAccount) + const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') + if (isCurrent) { + setGasCosts(gasCostsAsEth) + } + } + + estimateGas() + + return () => { + isCurrent = false + } + }, []) + return ( - + <> @@ -148,21 +171,25 @@ const ReviewComponent = ({ values, classes, network }: Props) => { You're about to create a new Safe and will have to confirm a transaction with your currently connected - wallet. Make sure you have ETH in this wallet to fund this transaction. + wallet. Make sure you have + {' '} + {gasCosts} + {' '} +ETH in this wallet to fund this transaction. - + ) } const ReviewPage = withStyles(styles)(ReviewComponent) const Review = ({ network }: LayoutProps) => (controls: React.Node, { values }: Object) => ( - + <> - + ) export default Review diff --git a/src/routes/open/container/Open.jsx b/src/routes/open/container/Open.jsx index 7d65b08f..5f9b6c13 100644 --- a/src/routes/open/container/Open.jsx +++ b/src/routes/open/container/Open.jsx @@ -29,7 +29,6 @@ export const createSafe = async (values: Object, userAccount: string, addSafe: A const name = getSafeNameFrom(values) const owners = getNamesFrom(values) - await initContracts() const safe = await deploySafeContract(accounts, numConfirmations, userAccount) await checkReceiptStatus(safe.tx) @@ -55,6 +54,10 @@ export const createSafe = async (values: Object, userAccount: string, addSafe: A } class Open extends React.Component { + async componentDidMount() { + await initContracts() + } + onCallSafeContractSubmit = async (values) => { try { const { userAccount, addSafe } = this.props