From def22bce370b8ba43da7d3e05687e155790f909e Mon Sep 17 00:00:00 2001 From: Tal Kol Date: Sun, 26 Jul 2020 13:07:41 +0300 Subject: [PATCH] Added proper support for gas limit, changed Web3 HTTP provider to support keepalive --- src/helpers.ts | 6 ++++++ src/write/ethereum-helpers.ts | 20 +++++++++++++++++--- src/write/ethereum.test.ts | 4 ++++ src/write/ethereum.ts | 6 +++++- 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/helpers.ts b/src/helpers.ts index 4538886..0a72489 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -15,6 +15,12 @@ export function getCurrentClockTime() { return Math.round(new Date().getTime() / 1000); } +export function toNumber(val: number | string) { + if (typeof val == 'string') { + return parseInt(val); + } else return val; +} + // eslint-disable-next-line @typescript-eslint/no-explicit-any export type JsonResponse = any; diff --git a/src/write/ethereum-helpers.ts b/src/write/ethereum-helpers.ts index d16470d..59606ed 100644 --- a/src/write/ethereum-helpers.ts +++ b/src/write/ethereum-helpers.ts @@ -1,6 +1,10 @@ import * as Logger from '../logger'; import { State, EthereumTxStatus, GasPriceStrategy } from '../model/state'; -import { getCurrentClockTime, jsonStringifyComplexTypes } from '../helpers'; +import { getCurrentClockTime, jsonStringifyComplexTypes, toNumber } from '../helpers'; +import { TransactionConfig } from 'web3-core'; + +const GAS_LIMIT_ESTIMATE_EXTRA = 100000; +const GAS_LIMIT_HARD_LIMIT = 2000000; export type Type = 'ready-to-sync' | 'ready-for-committee'; @@ -50,14 +54,24 @@ export async function signAndSendTransaction( const nonce = await state.web3.eth.getTransactionCount(senderAddress, 'latest'); // ignore pending pool - const txObject = { + const txObject: TransactionConfig = { from: senderAddress, to: contractAddress, gasPrice: gasPrice, - gas: 10000000, // TODO: fix with real value data: encodedAbi, nonce: nonce, }; + + let gasLimit = toNumber(await state.web3.eth.estimateGas(txObject)); + if (gasLimit <= 0) throw new Error(`Cannot estimate gas for tx with data ${encodedAbi}`); + gasLimit += GAS_LIMIT_ESTIMATE_EXTRA; + if (gasLimit > GAS_LIMIT_HARD_LIMIT) { + throw new Error(`Gas limit estimate ${gasLimit} over hard limit ${GAS_LIMIT_HARD_LIMIT}`); + } + txObject.gas = gasLimit; + + Logger.log(`About to sign and send tx object: ${jsonStringifyComplexTypes(txObject)}.`); + const { rawTransaction, transactionHash } = await state.signer.sign(txObject); if (!rawTransaction || !transactionHash) { throw new Error(`Could not sign tx object: ${jsonStringifyComplexTypes(txObject)}.`); diff --git a/src/write/ethereum.test.ts b/src/write/ethereum.test.ts index 77d8b72..784c9f2 100644 --- a/src/write/ethereum.test.ts +++ b/src/write/ethereum.test.ts @@ -31,6 +31,10 @@ function getMockWeb3Client(behavior: 'success' | 'badsend' | 'pending' | 'revert if (behavior == 'overmax') return '999000000000'; return '40000000000'; }, + estimateGas: async () => { + await sleep(0); + return 500000; + }, sendSignedTransaction: async () => { await sleep(0); if (behavior == 'badsend') throw new Error('send error'); diff --git a/src/write/ethereum.ts b/src/write/ethereum.ts index 449f508..4967f30 100644 --- a/src/write/ethereum.ts +++ b/src/write/ethereum.ts @@ -14,7 +14,11 @@ import { compiledContracts } from '@orbs-network/orbs-ethereum-contracts-v2/rele export function initWeb3Client(ethereumEndpoint: string, electionsContractAddress: string, state: State) { // init web3 - state.web3 = new Web3(ethereumEndpoint); + state.web3 = new Web3( + new Web3.providers.HttpProvider(ethereumEndpoint, { + keepAlive: true, + }) + ); // TODO: state.web3.eth.transactionPollingTimeout = 0.01; // TODO: do we need to disable web3 receipt polling explicitly? // init contracts