Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
Gas exception warnings on deployment (#3938)
Browse files Browse the repository at this point in the history
* add deployEstimateGas function

* Render gas warning with Warning component

* estimateGas, display warning on contract deploy

* Update messages

* Removed unused import

* Fix calculated gas usage

* Basic component smoktest

* Only display warning on edit steps
  • Loading branch information
jacogr authored and gavofyork committed Dec 23, 2016
1 parent 9529b6f commit 466f84f
Show file tree
Hide file tree
Showing 8 changed files with 419 additions and 141 deletions.
53 changes: 30 additions & 23 deletions js/src/api/contract/contract.js
Expand Up @@ -89,9 +89,15 @@ export default class Contract {
return this;
}

deploy (options, values, statecb) {
let gas;
deployEstimateGas (options, values) {
return this._api.eth
.estimateGas(this._encodeOptions(this.constructors[0], options, values))
.then((gasEst) => {
return [gasEst, gasEst.mul(1.2)];
});
}

deploy (options, values, statecb) {
const setState = (state) => {
if (!statecb) {
return;
Expand All @@ -102,31 +108,32 @@ export default class Contract {

setState({ state: 'estimateGas' });

return this._api.eth
.estimateGas(this._encodeOptions(this.constructors[0], options, values))
.then((_gas) => {
gas = _gas.mul(1.2);
return this
.deployEstimateGas(options, values)
.then(([gasEst, gas]) => {
options.gas = gas.toFixed(0);

setState({ state: 'postTransaction', gas });
return this._api.parity.postTransaction(this._encodeOptions(this.constructors[0], options, values));
})
.then((requestId) => {
setState({ state: 'checkRequest', requestId });
return this._pollCheckRequest(requestId);
})
.then((txhash) => {
setState({ state: 'getTransactionReceipt', txhash });
return this._pollTransactionReceipt(txhash, gas);
})
.then((receipt) => {
if (receipt.gasUsed.eq(gas)) {
throw new Error(`Contract not deployed, gasUsed == ${gas.toFixed(0)}`);
}

setState({ state: 'hasReceipt', receipt });
this._address = receipt.contractAddress;
return this._address;
return this._api.parity
.postTransaction(this._encodeOptions(this.constructors[0], options, values))
.then((requestId) => {
setState({ state: 'checkRequest', requestId });
return this._pollCheckRequest(requestId);
})
.then((txhash) => {
setState({ state: 'getTransactionReceipt', txhash });
return this._pollTransactionReceipt(txhash, gas);
})
.then((receipt) => {
if (receipt.gasUsed.eq(gas)) {
throw new Error(`Contract not deployed, gasUsed == ${gas.toFixed(0)}`);
}

setState({ state: 'hasReceipt', receipt });
this._address = receipt.contractAddress;
return this._address;
});
})
.then((address) => {
setState({ state: 'getCode' });
Expand Down
93 changes: 70 additions & 23 deletions js/src/modals/DeployContract/DetailsStep/detailsStep.js
Expand Up @@ -15,6 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

import React, { Component, PropTypes } from 'react';
import { FormattedMessage } from 'react-intl';
import { MenuItem } from 'material-ui';

import { AddressSelect, Form, Input, Select } from '~/ui';
Expand Down Expand Up @@ -92,46 +93,86 @@ export default class DetailsStep extends Component {
return (
<Form>
<AddressSelect
label='from account (contract owner)'
hint='the owner account for this contract'
accounts={ accounts }
balances={ balances }
error={ fromAddressError }
hint={
<FormattedMessage
id='deployContract.details.address.hint'
defaultMessage='the owner account for this contract' />
}
label={
<FormattedMessage
id='deployContract.details.address.label'
defaultMessage='from account (contract owner)' />
}
onChange={ this.onFromAddressChange }
value={ fromAddress }
/>

<Input
label='contract name'
hint='a name for the deployed contract'
error={ nameError }
hint={
<FormattedMessage
id='deployContract.details.name.hint'
defaultMessage='a name for the deployed contract' />
}
label={
<FormattedMessage
id='deployContract.details.name.label'
defaultMessage='contract name' />
}
onChange={ this.onNameChange }
value={ name || '' }
/>

<Input
label='contract description (optional)'
hint='a description for the contract'
error={ descriptionError }
hint={
<FormattedMessage
id='deployContract.details.description.hint'
defaultMessage='a description for the contract' />
}
label={
<FormattedMessage
id='deployContract.details.description.label'
defaultMessage='contract description (optional)' />
}
onChange={ this.onDescriptionChange }
value={ description }
/>

{ this.renderContractSelect() }

<Input
label='abi / solc combined-output'
hint='the abi of the contract to deploy or solc combined-output'
error={ abiError }
hint={
<FormattedMessage
id='deployContract.details.abi.hint'
defaultMessage='the abi of the contract to deploy or solc combined-output' />
}
label={
<FormattedMessage
id='deployContract.details.abi.label'
defaultMessage='abi / solc combined-output' />
}
onChange={ this.onSolcChange }
onSubmit={ this.onSolcSubmit }
readOnly={ readOnly }
value={ solcOutput }
/>
<Input
label='code'
hint='the compiled code of the contract to deploy'
error={ codeError }
hint={
<FormattedMessage
id='deployContract.details.code.hint'
defaultMessage='the compiled code of the contract to deploy' />
}
label={
<FormattedMessage
id='deployContract.details.code.label'
defaultMessage='code' />
}
onSubmit={ this.onCodeChange }
readOnly={ readOnly || solc }
value={ code }
Expand All @@ -149,22 +190,26 @@ export default class DetailsStep extends Component {
}

const { selectedContractIndex } = this.state;
const contractsItems = Object.keys(contracts).map((name, index) => (
<MenuItem
key={ index }
label={ name }
value={ index }
>
{ name }
</MenuItem>
));
const contractsItems = Object
.keys(contracts)
.map((name, index) => (
<MenuItem
key={ index }
label={ name }
value={ index }>
{ name }
</MenuItem>
));

return (
<Select
label='select a contract'
label={
<FormattedMessage
id='deployContract.details.contract.label'
defaultMessage='select a contract' />
}
onChange={ this.onContractChange }
value={ selectedContractIndex }
>
value={ selectedContractIndex }>
{ contractsItems }
</Select>
);
Expand All @@ -180,7 +225,9 @@ export default class DetailsStep extends Component {
}

const { abi, bin } = contract;
const code = /^0x/.test(bin) ? bin : `0x${bin}`;
const code = /^0x/.test(bin)
? bin
: `0x${bin}`;

this.setState({ selectedContractIndex: index }, () => {
this.onAbiChange(abi);
Expand Down
16 changes: 10 additions & 6 deletions js/src/modals/DeployContract/ParametersStep/parametersStep.js
Expand Up @@ -30,6 +30,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

import React, { Component, PropTypes } from 'react';
import { FormattedMessage } from 'react-intl';

import { Form, TypedInput } from '~/ui';
import { parseAbiType } from '~/util/abi';
Expand Down Expand Up @@ -77,21 +78,24 @@ export default class ParametersStep extends Component {
return (
<div key={ index } className={ styles.funcparams }>
<TypedInput
label={ label }
value={ value }
error={ error }
accounts={ accounts }
error={ error }
isEth={ false }
label={ label }
onChange={ onChange }
param={ param }
isEth={ false }
/>
value={ value } />
</div>
);
});

return (
<div>
<p>Choose the contract parameters</p>
<p>
<FormattedMessage
id='deployContract.parameters.choose'
defaultMessage='Choose the contract parameters' />
</p>
{ inputsComponents }
</div>
);
Expand Down

0 comments on commit 466f84f

Please sign in to comment.