From 3e091a29384033f9fd1294d7367ad4d023caa2cc Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Wed, 1 Aug 2018 17:24:11 -0400 Subject: [PATCH] Added Vyper-style gas ABI support. --- src.ts/contracts/contract.ts | 4 ++++ src.ts/contracts/interface.ts | 13 +++++++++++-- src.ts/utils/abi-coder.ts | 19 +++++++++++++++++-- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src.ts/contracts/contract.ts b/src.ts/contracts/contract.ts index 4f8265689..3cdc4f7d8 100644 --- a/src.ts/contracts/contract.ts +++ b/src.ts/contracts/contract.ts @@ -206,6 +206,10 @@ function runMethod(contract: Contract, functionName: string, estimateOnly: boole return contract.provider.estimateGas(tx); } + if (tx.gasLimit == null && method.gas != null) { + tx.gasLimit = method.gas; + } + if (!contract.signer) { errors.throwError('sending a transaction require a signer', errors.UNSUPPORTED_OPERATION, { operation: 'sendTransaction' }) } diff --git a/src.ts/contracts/interface.ts b/src.ts/contracts/interface.ts index d254fc2db..1bf1039f8 100644 --- a/src.ts/contracts/interface.ts +++ b/src.ts/contracts/interface.ts @@ -39,6 +39,7 @@ export interface FunctionDescription { readonly inputs: Array; readonly outputs: Array; readonly payable: boolean; + readonly gas: BigNumber; encode(params: Array): string; decode(data: string): any; } @@ -85,9 +86,13 @@ class Description { for (var key in info) { let value = info[key]; if (value != null && typeof(value) === 'object') { - defineFrozen(this, key, info[key]); + if (BigNumber.isBigNumber(value)) { + defineReadOnly(this, key, value); + } else { + defineFrozen(this, key, value); + } } else { - defineReadOnly(this, key, info[key]); + defineReadOnly(this, key, value); } } } @@ -131,6 +136,8 @@ class _FunctionDescription extends Description implements FunctionDescription { readonly outputs: Array; readonly payable: boolean; + readonly gas: BigNumber; + encode(params: Array): string { errors.checkArgumentCount(params.length, this.inputs.length, 'in interface function ' + this.name); @@ -313,6 +320,8 @@ function addMethod(method: any): void { inputs: method.inputs, outputs: method.outputs, + gas: method.gas, + payable: (method.payable == null || !!method.payable), type: ((method.constant) ? 'call': 'transaction'), diff --git a/src.ts/utils/abi-coder.ts b/src.ts/utils/abi-coder.ts index 6205b14e5..d8d47b09b 100644 --- a/src.ts/utils/abi-coder.ts +++ b/src.ts/utils/abi-coder.ts @@ -3,7 +3,7 @@ // See: https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI import { getAddress } from './address'; -import { bigNumberify, ConstantNegativeOne, ConstantZero, ConstantOne, ConstantMaxUint256 } from './bignumber'; +import { BigNumber, bigNumberify, ConstantNegativeOne, ConstantZero, ConstantOne, ConstantMaxUint256 } from './bignumber'; import { arrayify, concat, hexlify, padZeros } from './bytes'; import { toUtf8Bytes, toUtf8String } from './utf8'; import { defineReadOnly, jsonCopy } from './properties'; @@ -50,6 +50,8 @@ export type FunctionFragment = { payable: boolean, stateMutability: string, + + gas: BigNumber }; /////////////////////////////// @@ -272,6 +274,7 @@ function parseSignatureEvent(fragment: string): EventFragment { function parseSignatureFunction(fragment: string): FunctionFragment { var abi: FunctionFragment = { constant: false, + gas: null, inputs: [], name: '', outputs: [], @@ -280,7 +283,19 @@ function parseSignatureFunction(fragment: string): FunctionFragment { type: 'function' }; - var comps = fragment.split(' returns '); + let comps = fragment.split('@'); + if (comps.length !== 1) { + if (comps.length > 2) { + throw new Error('invalid signature'); + } + if (!comps[1].match(/^[0-9]+$/)) { + throw new Error('invalid signature gas'); + } + abi.gas = bigNumberify(comps[1]); + fragment = comps[0]; + } + + comps = fragment.split(' returns '); var left = comps[0].match(regexParen); if (!left) { throw new Error('invalid signature'); }