From af941205d6ab78ec2335b1214f4d4bb4e7d62a1a Mon Sep 17 00:00:00 2001 From: Connor Stein Date: Thu, 12 Aug 2021 11:23:28 -0400 Subject: [PATCH] Fallback to max gas limit in estimategas (#4853) Fallback to max gas limit --- core/services/pipeline/runner.go | 1 + core/services/pipeline/task.estimategas.go | 18 +++++++++++++++--- core/services/vrf/integration_v2_test.go | 6 +++--- core/testdata/tomlspecs/vrf-v2-spec.toml | 4 ++-- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/core/services/pipeline/runner.go b/core/services/pipeline/runner.go index 13591a809ee..d008b858ae3 100644 --- a/core/services/pipeline/runner.go +++ b/core/services/pipeline/runner.go @@ -237,6 +237,7 @@ func (r *runner) run( task.(*VRFTaskV2).keyStore = r.vrfKeyStore case TaskTypeEstimateGasLimit: task.(*EstimateGasLimitTask).GasEstimator = r.ethClient + task.(*EstimateGasLimitTask).EvmGasLimit = r.config.EvmGasLimitDefault() case TaskTypeETHTx: task.(*ETHTxTask).db = r.orm.DB() task.(*ETHTxTask).config = r.config diff --git a/core/services/pipeline/task.estimategas.go b/core/services/pipeline/task.estimategas.go index 089ab8f57ba..58a7649e9ff 100644 --- a/core/services/pipeline/task.estimategas.go +++ b/core/services/pipeline/task.estimategas.go @@ -4,6 +4,8 @@ import ( "context" "strconv" + "github.com/smartcontractkit/chainlink/core/logger" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" @@ -22,6 +24,7 @@ type EstimateGasLimitTask struct { Multiplier string `json:"multiplier"` Data string `json:"data"` + EvmGasLimit uint64 GasEstimator GasEstimator } @@ -29,7 +32,9 @@ type GasEstimator interface { EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) } -var _ Task = (*EstimateGasLimitTask)(nil) +var ( + _ Task = (*EstimateGasLimitTask)(nil) +) func (t *EstimateGasLimitTask) Type() TaskType { return TaskTypeEstimateGasLimit @@ -57,7 +62,10 @@ func (t *EstimateGasLimitTask) Run(_ context.Context, vars Vars, inputs []Result Data: data, }) if err != nil { - return Result{Error: err} + // Fallback to the maximum conceivable gas limit + // if we're unable to call estimate gas for whatever reason. + logger.Warnw("EstimateGas: unable to estimate, fallback to configured limit", "err", err, "fallback", t.EvmGasLimit) + return Result{Value: t.EvmGasLimit} } gasLimitDecimal, err := decimal.NewFromString(strconv.FormatUint(gasLimit, 10)) if err != nil { @@ -67,5 +75,9 @@ func (t *EstimateGasLimitTask) Run(_ context.Context, vars Vars, inputs []Result if !gasLimitWithMultiplier.IsUint64() { return Result{Error: errors.New("Invalid multiplier")} } - return Result{Value: gasLimitWithMultiplier.Uint64()} + gasLimitFinal := gasLimitWithMultiplier.Uint64() + if gasLimitFinal > t.EvmGasLimit { + gasLimitFinal = t.EvmGasLimit + } + return Result{Value: gasLimitFinal} } diff --git a/core/services/vrf/integration_v2_test.go b/core/services/vrf/integration_v2_test.go index 5222fd7c4e8..0ab24c60696 100644 --- a/core/services/vrf/integration_v2_test.go +++ b/core/services/vrf/integration_v2_test.go @@ -144,7 +144,7 @@ func TestIntegrationVRFV2(t *testing.T) { defer cleanupDB() key := cltest.MustGenerateRandomKey(t) uni := newVRFCoordinatorV2Universe(t, key) - config.Overrides.EvmGasLimitDefault = null.IntFrom(500000) + config.Overrides.EvmGasLimitDefault = null.IntFrom(2000000) app, cleanup := cltest.NewApplicationWithConfigAndKeyOnSimulatedBlockchain(t, config, uni.backend, key) defer cleanup() @@ -287,11 +287,11 @@ func TestIntegrationVRFV2(t *testing.T) { t.Logf("subscription charged %s with gas prices of %s gwei and %s ETH per LINK\n", linkCharged, gasPrice.Div(gwei), weiPerUnitLink.Div(wei)) expected := decimal.RequireFromString(strconv.Itoa(int(fulfillReceipt.GasUsed))).Mul(gasPrice).Div(weiPerUnitLink) t.Logf("expected sub charge gas use %v %v off by %v", fulfillReceipt.GasUsed, expected, expected.Sub(linkCharged)) - // The expected sub charge should be within 100 gas of the actual gas usage. + // The expected sub charge should be within 200 gas of the actual gas usage. // wei/link * link / wei/gas = wei / (wei/gas) = gas gasDiff := linkCharged.Sub(expected).Mul(weiPerUnitLink).Div(gasPrice).Abs().IntPart() t.Log("gasDiff", gasDiff) - assert.Less(t, gasDiff, int64(100)) + assert.Less(t, gasDiff, int64(200)) // Oracle tries to withdraw move than it was paid should fail _, err = uni.rootContract.OracleWithdraw(uni.nallory, uni.nallory.From, linkWeiCharged.Add(decimal.NewFromInt(1)).BigInt()) diff --git a/core/testdata/tomlspecs/vrf-v2-spec.toml b/core/testdata/tomlspecs/vrf-v2-spec.toml index e46d0e45df8..9947939e379 100644 --- a/core/testdata/tomlspecs/vrf-v2-spec.toml +++ b/core/testdata/tomlspecs/vrf-v2-spec.toml @@ -19,10 +19,10 @@ encode_tx [type=ethabiencode abi="fulfillRandomWords(bytes proof)" data="{\\"proof\\": $(vrf.proof)}"] estimate_gas [type=estimategaslimit - to="%s" + to="0xABA5eDc1a551E55b1A570c0e1f1055e5BE11eca7" multiplier="1.1" data="$(encode_tx)"] -submit_tx [type=ethtx to="%s" +submit_tx [type=ethtx to="0xABA5eDc1a551E55b1A570c0e1f1055e5BE11eca7" data="$(encode_tx)" gasLimit="$(estimate_gas)" txMeta="{\\"requestTxHash\\": $(jobRun.logTxHash),\\"requestID\\": $(vrf.requestID),\\"jobID\\": $(jobSpec.databaseID)}"]