feat: compute a better gas limit for recursive external contract calls
This commit is contained in:
parent
b46258d0bf
commit
03b419e3d4
@ -1 +1 @@
|
||||
608060405234801561001057600080fd5b506105eb806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c8063c755553811610071578063c755553814610198578063cbfc3b58146101c6578063cc6f8faf14610212578063cd5b6c3d14610254578063e2a614731461028c578063fb62b28b146102d8576100a9565b80630919b8be146100ae5780636199074d146100e657806366eef3461461012857806375091b1f14610132578063a63ae81a1461016a575b600080fd5b6100e4600480360360408110156100c457600080fd5b81019080803590602001909291908035906020019092919050505061031a565b005b610126600480360360608110156100fc57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919050505061035d565b005b610130610391565b005b6101686004803603604081101561014857600080fd5b8101908080359060200190929190803590602001909291905050506103bf565b005b6101966004803603602081101561018057600080fd5b81019080803590602001909291905050506103fb565b005b6101c4600480360360208110156101ae57600080fd5b8101908080359060200190929190505050610435565b005b610210600480360360808110156101dc57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919080359060200190929190505050610465565b005b6102526004803603606081101561022857600080fd5b810190808035906020019092919080359060200190929190803590602001909291905050506104ba565b005b61028a6004803603604081101561026a57600080fd5b8101908080359060200190929190803590602001909291905050506104f8565b005b6102d6600480360360808110156102a257600080fd5b810190808035906020019092919080359060200190929190803590602001909291908035906020019092919050505061052a565b005b610318600480360360608110156102ee57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919050505061056a565b005b7f5469c6b769315f5668523937f05ca07d4cc87849432bc5f5907f1d90fa73b9f98282604051808381526020018281526020019250505060405180910390a15050565b8082847fb89dabcdb7ff41f1794c0da92f65ece6c19b6b0caeac5407b2a721efe27c080460405160405180910390a4505050565b7fc3f6f1c76bd4e74ee5782052b0b4f8bd5c50b86c3c5a2f52638e03066e50a91b60405160405180910390a1565b817f6709824ebe5f6e620ca3f4b02a3428e8ce2dc97c550816eaeeb3a342b214bd85826040518082815260200191505060405180910390a25050565b7fc804e53d6048af1b3e6a352e246d5f3864fea9d635ace499e023a58c383b3a88816040518082815260200191505060405180910390a150565b807f44a227a31429ab5eb00daf6611c6422f10571619f2267e0e149e9ebe6d2a5d0560405160405180910390a250565b7f28d45631a87b2a52a9625f8520fa37ff8c4d926cdf17042e241985da5cb7b850848484846040518085815260200184815260200183815260200182815260200194505050505060405180910390a150505050565b81837fcd5fe5fbc1d27b90036997224cea7aa565e3779622867265081f636b3a5ccb08836040518082815260200191505060405180910390a3505050565b80827f232f09cef3babc26e58d1cc1346c0a8bc626ffe600c9605b5d747783eda484a760405160405180910390a35050565b8183857f812e73dbcf7e267f27ecb1383bfc902a6650b41b6e7d03ac265108c369673d95846040518082815260200191505060405180910390a450505050565b7fd4d143faaf60340ad98e1f2c96fc26f5695834c21b5200edad339ee7e9a372cc83838360405180848152602001838152602001828152602001935050505060405180910390a150505056fea265627a7a72315820954561fde80ab925299e0a9f3356b01f64fb1976dd335ac2ebd9367441e29f0564736f6c63430005110032
|
||||
608060405234801561001057600080fd5b506106af806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c8063c755553811610071578063c755553814610128578063cbfc3b5814610144578063cc6f8faf14610160578063cd5b6c3d1461017c578063e2a6147314610198578063fb62b28b146101b4576100a9565b80630919b8be146100ae5780636199074d146100ca57806366eef346146100e657806375091b1f146100f0578063a63ae81a1461010c575b600080fd5b6100c860048036038101906100c39190610483565b6101d0565b005b6100e460048036038101906100df91906104c3565b61020d565b005b6100ee610241565b005b61010a60048036038101906101059190610483565b61026f565b005b61012660048036038101906101219190610516565b6102ab565b005b610142600480360381019061013d9190610516565b6102e5565b005b61015e60048036038101906101599190610543565b610315565b005b61017a600480360381019061017591906104c3565b610358565b005b61019660048036038101906101919190610483565b610396565b005b6101b260048036038101906101ad9190610543565b6103c8565b005b6101ce60048036038101906101c991906104c3565b610408565b005b7f5469c6b769315f5668523937f05ca07d4cc87849432bc5f5907f1d90fa73b9f982826040516102019291906105b9565b60405180910390a15050565b8082847fb89dabcdb7ff41f1794c0da92f65ece6c19b6b0caeac5407b2a721efe27c080460405160405180910390a4505050565b7fc3f6f1c76bd4e74ee5782052b0b4f8bd5c50b86c3c5a2f52638e03066e50a91b60405160405180910390a1565b817f6709824ebe5f6e620ca3f4b02a3428e8ce2dc97c550816eaeeb3a342b214bd858260405161029f91906105e2565b60405180910390a25050565b7fc804e53d6048af1b3e6a352e246d5f3864fea9d635ace499e023a58c383b3a88816040516102da91906105e2565b60405180910390a150565b807f44a227a31429ab5eb00daf6611c6422f10571619f2267e0e149e9ebe6d2a5d0560405160405180910390a250565b7f28d45631a87b2a52a9625f8520fa37ff8c4d926cdf17042e241985da5cb7b8508484848460405161034a94939291906105fd565b60405180910390a150505050565b81837fcd5fe5fbc1d27b90036997224cea7aa565e3779622867265081f636b3a5ccb088360405161038991906105e2565b60405180910390a3505050565b80827f232f09cef3babc26e58d1cc1346c0a8bc626ffe600c9605b5d747783eda484a760405160405180910390a35050565b8183857f812e73dbcf7e267f27ecb1383bfc902a6650b41b6e7d03ac265108c369673d95846040516103fa91906105e2565b60405180910390a450505050565b7fd4d143faaf60340ad98e1f2c96fc26f5695834c21b5200edad339ee7e9a372cc83838360405161043b93929190610642565b60405180910390a1505050565b600080fd5b6000819050919050565b6104608161044d565b811461046b57600080fd5b50565b60008135905061047d81610457565b92915050565b6000806040838503121561049a57610499610448565b5b60006104a88582860161046e565b92505060206104b98582860161046e565b9150509250929050565b6000806000606084860312156104dc576104db610448565b5b60006104ea8682870161046e565b93505060206104fb8682870161046e565b925050604061050c8682870161046e565b9150509250925092565b60006020828403121561052c5761052b610448565b5b600061053a8482850161046e565b91505092915050565b6000806000806080858703121561055d5761055c610448565b5b600061056b8782880161046e565b945050602061057c8782880161046e565b935050604061058d8782880161046e565b925050606061059e8782880161046e565b91505092959194509250565b6105b38161044d565b82525050565b60006040820190506105ce60008301856105aa565b6105db60208301846105aa565b9392505050565b60006020820190506105f760008301846105aa565b92915050565b600060808201905061061260008301876105aa565b61061f60208301866105aa565b61062c60408301856105aa565b61063960608301846105aa565b95945050505050565b600060608201905061065760008301866105aa565b61066460208301856105aa565b61067160408301846105aa565b94935050505056fea26469706673582212201b2f4de851da592b926eb2cd07ccfbbd02270fde6dee2459ba942e5dcf5685d364736f6c63430008110033
|
@ -1,4 +1,5 @@
|
||||
pragma solidity ^0.5.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.5.0;
|
||||
|
||||
contract EventMatrix {
|
||||
event EventZeroData();
|
||||
|
1
itests/contracts/ExternalRecursiveCallSimple.hex
Normal file
1
itests/contracts/ExternalRecursiveCallSimple.hex
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b506101ee806100206000396000f3fe60806040526004361061001e5760003560e01c8063c38e07dd14610023575b600080fd5b61003d600480360381019061003891906100fe565b61003f565b005b60008111156100c0573073ffffffffffffffffffffffffffffffffffffffff1663c38e07dd600183610071919061015a565b6040518263ffffffff1660e01b815260040161008d919061019d565b600060405180830381600087803b1580156100a757600080fd5b505af11580156100bb573d6000803e3d6000fd5b505050505b50565b600080fd5b6000819050919050565b6100db816100c8565b81146100e657600080fd5b50565b6000813590506100f8816100d2565b92915050565b600060208284031215610114576101136100c3565b5b6000610122848285016100e9565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610165826100c8565b9150610170836100c8565b92508282039050818111156101885761018761012b565b5b92915050565b610197816100c8565b82525050565b60006020820190506101b2600083018461018e565b9291505056fea264697066735822122033d012e17f5d7a62bb724021b5c4e0d109aeb28d1cd5b5c0a0b1b801c0b5032164736f6c63430008110033
|
13
itests/contracts/ExternalRecursiveCallSimple.sol
Normal file
13
itests/contracts/ExternalRecursiveCallSimple.sol
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.17;
|
||||
|
||||
contract StackRecCallExp {
|
||||
function exec1(uint256 r) public payable {
|
||||
if(r > 0) {
|
||||
StackRecCallExp(address(this)).exec1(r-1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
"github.com/filecoin-project/go-state-types/manifest"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
"github.com/filecoin-project/lotus/itests/kit"
|
||||
@ -606,3 +607,100 @@ func TestFEVMRecursiveActorCall(t *testing.T) {
|
||||
t.Run("n=0,r=256-fails", testN(0, 256, exitcode.ExitCode(33))) // 33 means transaction reverted
|
||||
t.Run("n=251,r=167-fails", testN(251, 167, exitcode.ExitCode(33)))
|
||||
}
|
||||
|
||||
// TestFEVMRecursiveActorCallEstimate
|
||||
func TestFEVMRecursiveActorCallEstimate(t *testing.T) {
|
||||
ctx, cancel, client := kit.SetupFEVMTest(t)
|
||||
defer cancel()
|
||||
|
||||
//install contract Actor
|
||||
filenameActor := "contracts/ExternalRecursiveCallSimple.hex"
|
||||
_, actorAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor)
|
||||
|
||||
contractAddr, err := ethtypes.EthAddressFromFilecoinAddress(actorAddr)
|
||||
require.NoError(t, err)
|
||||
|
||||
// create a new Ethereum account
|
||||
key, ethAddr, ethFilAddr := client.EVM().NewAccount()
|
||||
kit.SendFunds(ctx, t, client, ethFilAddr, types.FromFil(1000))
|
||||
|
||||
makeParams := func(r int) []byte {
|
||||
funcSignature := "exec1(uint256)"
|
||||
entryPoint := kit.CalcFuncSignature(funcSignature)
|
||||
|
||||
inputData := make([]byte, 32)
|
||||
binary.BigEndian.PutUint64(inputData[24:], uint64(r))
|
||||
|
||||
params := append(entryPoint, inputData...)
|
||||
|
||||
return params
|
||||
}
|
||||
|
||||
testN := func(r int) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
t.Logf("running with %d recursive calls", r)
|
||||
|
||||
params := makeParams(r)
|
||||
gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{
|
||||
From: ðAddr,
|
||||
To: &contractAddr,
|
||||
Data: params,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.LessOrEqual(t, int64(gaslimit), build.BlockGasLimit)
|
||||
|
||||
t.Logf("EthEstimateGas GasLimit=%d", gaslimit)
|
||||
|
||||
maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
nonce, err := client.MpoolGetNonce(ctx, ethFilAddr)
|
||||
require.NoError(t, err)
|
||||
|
||||
tx := ðtypes.EthTxArgs{
|
||||
ChainID: build.Eip155ChainId,
|
||||
To: &contractAddr,
|
||||
Value: big.Zero(),
|
||||
Nonce: int(nonce),
|
||||
MaxFeePerGas: types.NanoFil,
|
||||
MaxPriorityFeePerGas: big.Int(maxPriorityFeePerGas),
|
||||
GasLimit: int(gaslimit),
|
||||
Input: params,
|
||||
V: big.Zero(),
|
||||
R: big.Zero(),
|
||||
S: big.Zero(),
|
||||
}
|
||||
|
||||
client.EVM().SignTransaction(tx, key.PrivateKey)
|
||||
hash := client.EVM().SubmitTransaction(ctx, tx)
|
||||
|
||||
smsg, err := tx.ToSignedMessage()
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = client.StateWaitMsg(ctx, smsg.Cid(), 0, 0, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
receipt, err := client.EthGetTransactionReceipt(ctx, hash)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, receipt)
|
||||
|
||||
t.Logf("Receipt GasUsed=%d", receipt.GasUsed)
|
||||
t.Logf("Ratio %0.2f", float64(receipt.GasUsed)/float64(gaslimit))
|
||||
t.Logf("Overestimate %0.2f", ((float64(gaslimit)/float64(receipt.GasUsed))-1)*100)
|
||||
|
||||
require.EqualValues(t, ethtypes.EthUint64(1), receipt.Status)
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("n=1", testN(1))
|
||||
t.Run("n=2", testN(2))
|
||||
t.Run("n=3", testN(3))
|
||||
t.Run("n=4", testN(4))
|
||||
t.Run("n=5", testN(5))
|
||||
t.Run("n=10", testN(10))
|
||||
t.Run("n=20", testN(20))
|
||||
t.Run("n=30", testN(30))
|
||||
t.Run("n=40", testN(40))
|
||||
t.Run("n=50", testN(50))
|
||||
t.Run("n=100", testN(100))
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/builtin/v10/eam"
|
||||
"github.com/filecoin-project/go-state-types/builtin/v10/evm"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
@ -809,12 +810,137 @@ func (a *EthModule) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (et
|
||||
// gas estimation actually run.
|
||||
msg.GasLimit = 0
|
||||
|
||||
msg, err = a.GasAPI.GasEstimateMessageGas(ctx, msg, nil, types.EmptyTSK)
|
||||
ts := a.Chain.GetHeaviestTipSet()
|
||||
msg, err = a.GasAPI.GasEstimateMessageGas(ctx, msg, nil, ts.Key())
|
||||
if err != nil {
|
||||
return ethtypes.EthUint64(0), err
|
||||
return ethtypes.EthUint64(0), xerrors.Errorf("failed to estimate gas: %w", err)
|
||||
}
|
||||
|
||||
return ethtypes.EthUint64(msg.GasLimit), nil
|
||||
expectedGas, err := ethGasSearch(ctx, a.Chain, a.Stmgr, a.Mpool, msg, ts)
|
||||
if err != nil {
|
||||
log.Errorw("expected gas", "err", err)
|
||||
}
|
||||
|
||||
return ethtypes.EthUint64(expectedGas), nil
|
||||
}
|
||||
|
||||
// gasSearch does an exponential search to find a gas value to execute the
|
||||
// message with. It first finds a high gas limit that allows the message to execute
|
||||
// by doubling the previous gas limit until it succeeds then does a binary
|
||||
// search till it gets within a range of 1%
|
||||
func gasSearch(
|
||||
ctx context.Context,
|
||||
smgr *stmgr.StateManager,
|
||||
msgIn *types.Message,
|
||||
priorMsgs []types.ChainMsg,
|
||||
ts *types.TipSet,
|
||||
) (int64, error) {
|
||||
msg := *msgIn
|
||||
|
||||
high := msg.GasLimit
|
||||
low := msg.GasLimit
|
||||
|
||||
canSucceed := func(limit int64) (bool, error) {
|
||||
msg.GasLimit = limit
|
||||
|
||||
res, err := smgr.CallWithGas(ctx, &msg, priorMsgs, ts)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("CallWithGas failed: %w", err)
|
||||
}
|
||||
|
||||
if res.MsgRct.ExitCode.IsSuccess() {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
for {
|
||||
ok, err := canSucceed(high)
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("searching for high gas limit failed: %w", err)
|
||||
}
|
||||
if ok {
|
||||
break
|
||||
}
|
||||
|
||||
low = high
|
||||
high = high * 2
|
||||
|
||||
if high > build.BlockGasLimit {
|
||||
high = build.BlockGasLimit
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
checkThreshold := high / 100
|
||||
for (high - low) > checkThreshold {
|
||||
median := (low + high) / 2
|
||||
ok, err := canSucceed(median)
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("searching for optimal gas limit failed: %w", err)
|
||||
}
|
||||
|
||||
if ok {
|
||||
high = median
|
||||
} else {
|
||||
low = median
|
||||
}
|
||||
|
||||
checkThreshold = median / 100
|
||||
}
|
||||
|
||||
return high, nil
|
||||
}
|
||||
|
||||
func traceContainsExitCode(et types.ExecutionTrace, ex exitcode.ExitCode) bool {
|
||||
if et.MsgRct.ExitCode == ex {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, et := range et.Subcalls {
|
||||
if traceContainsExitCode(et, ex) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// ethGasSearch executes a message for gas estimation using the previously estimated gas.
|
||||
// If the message fails due to an out of gas error then a gas search is performed.
|
||||
// See gasSearch.
|
||||
func ethGasSearch(
|
||||
ctx context.Context,
|
||||
cstore *store.ChainStore,
|
||||
smgr *stmgr.StateManager,
|
||||
mpool *messagepool.MessagePool,
|
||||
msgIn *types.Message,
|
||||
ts *types.TipSet,
|
||||
) (int64, error) {
|
||||
msg := *msgIn
|
||||
currTs := ts
|
||||
|
||||
res, priorMsgs, ts, err := gasEstimateCallWithGas(ctx, cstore, smgr, mpool, &msg, currTs)
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("gas estimation failed: %w", err)
|
||||
}
|
||||
|
||||
if res.MsgRct.ExitCode.IsSuccess() {
|
||||
return msg.GasLimit, nil
|
||||
}
|
||||
|
||||
if traceContainsExitCode(res.ExecutionTrace, exitcode.SysErrOutOfGas) {
|
||||
ret, err := gasSearch(ctx, smgr, &msg, priorMsgs, ts)
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("gas estimation search failed: %w", err)
|
||||
}
|
||||
|
||||
ret = int64(float64(ret) * mpool.GetConfig().GasLimitOverestimation)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
return -1, xerrors.Errorf("message execution failed: exit %s, reason: %s", res.MsgRct.ExitCode, res.Error)
|
||||
}
|
||||
|
||||
func (a *EthModule) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam string) (ethtypes.EthBytes, error) {
|
||||
|
@ -248,22 +248,23 @@ func (m *GasModule) GasEstimateGasLimit(ctx context.Context, msgIn *types.Messag
|
||||
}
|
||||
return gasEstimateGasLimit(ctx, m.Chain, m.Stmgr, m.Mpool, msgIn, ts)
|
||||
}
|
||||
func gasEstimateGasLimit(
|
||||
|
||||
// gasEstimateCallWithGas invokes a message "msgIn" on the earliest available tipset with pending
|
||||
// messages in the message pool. The function returns the result of the message invocation, the
|
||||
// pending messages, the tipset used for the invocation, and an error if occurred.
|
||||
// The returned information can be used to make subsequent calls to CallWithGas with the same parameters.
|
||||
func gasEstimateCallWithGas(
|
||||
ctx context.Context,
|
||||
cstore *store.ChainStore,
|
||||
smgr *stmgr.StateManager,
|
||||
mpool *messagepool.MessagePool,
|
||||
msgIn *types.Message,
|
||||
currTs *types.TipSet,
|
||||
) (int64, error) {
|
||||
) (*api.InvocResult, []types.ChainMsg, *types.TipSet, error) {
|
||||
msg := *msgIn
|
||||
msg.GasLimit = build.BlockGasLimit
|
||||
msg.GasFeeCap = big.Zero()
|
||||
msg.GasPremium = big.Zero()
|
||||
|
||||
fromA, err := smgr.ResolveToDeterministicAddress(ctx, msgIn.From, currTs)
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("getting key address: %w", err)
|
||||
return nil, []types.ChainMsg{}, nil, xerrors.Errorf("getting key address: %w", err)
|
||||
}
|
||||
|
||||
pending, ts := mpool.PendingFor(ctx, fromA)
|
||||
@ -284,12 +285,34 @@ func gasEstimateGasLimit(
|
||||
}
|
||||
ts, err = cstore.GetTipSetFromKey(ctx, ts.Parents())
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("getting parent tipset: %w", err)
|
||||
return nil, []types.ChainMsg{}, nil, xerrors.Errorf("getting parent tipset: %w", err)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("CallWithGas failed: %w", err)
|
||||
return nil, []types.ChainMsg{}, nil, xerrors.Errorf("CallWithGas failed: %w", err)
|
||||
}
|
||||
|
||||
return res, priorMsgs, ts, nil
|
||||
}
|
||||
|
||||
func gasEstimateGasLimit(
|
||||
ctx context.Context,
|
||||
cstore *store.ChainStore,
|
||||
smgr *stmgr.StateManager,
|
||||
mpool *messagepool.MessagePool,
|
||||
msgIn *types.Message,
|
||||
currTs *types.TipSet,
|
||||
) (int64, error) {
|
||||
msg := *msgIn
|
||||
msg.GasLimit = build.BlockGasLimit
|
||||
msg.GasFeeCap = big.Zero()
|
||||
msg.GasPremium = big.Zero()
|
||||
|
||||
res, _, ts, err := gasEstimateCallWithGas(ctx, cstore, smgr, mpool, &msg, currTs)
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("gas estimation failed: %w", err)
|
||||
}
|
||||
|
||||
if res.MsgRct.ExitCode == exitcode.SysErrOutOfGas {
|
||||
return -1, &api.ErrOutOfGas{}
|
||||
}
|
||||
@ -300,6 +323,8 @@ func gasEstimateGasLimit(
|
||||
|
||||
ret := res.MsgRct.GasUsed
|
||||
|
||||
log.Infow("GasEstimateMessageGas CallWithGas Result", "GasUsed", ret, "ExitCode", res.MsgRct.ExitCode)
|
||||
|
||||
transitionalMulti := 1.0
|
||||
// Overestimate gas around the upgrade
|
||||
if ts.Height() <= build.UpgradeSkyrHeight && (build.UpgradeSkyrHeight-ts.Height() <= 20) {
|
||||
|
Loading…
Reference in New Issue
Block a user