diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 8f5f291c07..a746b73124 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1075,7 +1075,7 @@ func (context *ChainContext) GetHeader(hash common.Hash, number uint64) *types.H return header } -func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, overrides *StateOverride, blockOverrides *BlockOverrides, timeout time.Duration, globalGasCap uint64, runMode core.MessageRunMode) (*core.ExecutionResult, error) { +func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, overrides *StateOverride, blockOverrides *BlockOverrides, timeout time.Duration, globalGasCap uint64, runMode core.MessageRunMode, blockNrOrHash *rpc.BlockNumberOrHash) (*core.ExecutionResult, error) { if err := overrides.Apply(state); err != nil { return nil, err } @@ -1098,6 +1098,14 @@ func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.S } blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil) + if blockNrOrHash != nil && + blockNrOrHash.BlockNumber != nil && + *blockNrOrHash.BlockNumber == rpc.PendingBlockNumber { + blkTime := uint64(time.Now().Unix()) + if blkTime > blockCtx.Time { + blockCtx.Time = blkTime + } + } if blockOverrides != nil { blockOverrides.Apply(&blockCtx) } @@ -1173,7 +1181,7 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash return nil, err } - return doCall(ctx, b, args, state, header, overrides, blockOverrides, timeout, globalGasCap, runMode) + return doCall(ctx, b, args, state, header, overrides, blockOverrides, timeout, globalGasCap, runMode, &blockNrOrHash) } func newRevertError(result *core.ExecutionResult) *revertError { @@ -1222,8 +1230,8 @@ func (e *revertError) ErrorData() interface{} { // useful to execute and retrieve values. func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides) (hexutil.Bytes, error) { if blockNrOrHash == nil { - latest := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) - blockNrOrHash = &latest + pending := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) + blockNrOrHash = &pending } result, err := DoCall(ctx, s.b, args, *blockNrOrHash, overrides, blockOverrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap(), core.MessageEthcallMode) if err != nil { @@ -1244,9 +1252,9 @@ func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrO // executeEstimate is a helper that executes the transaction under a given gas limit and returns // true if the transaction fails for a reason that might be related to not enough gas. A non-nil // error means execution failed due to reasons unrelated to the gas limit. -func executeEstimate(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, gasCap uint64, gasLimit uint64) (bool, *core.ExecutionResult, error) { +func executeEstimate(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, gasCap uint64, gasLimit uint64, blockNrOrHash *rpc.BlockNumberOrHash) (bool, *core.ExecutionResult, error) { args.Gas = (*hexutil.Uint64)(&gasLimit) - result, err := doCall(ctx, b, args, state, header, nil, nil, 0, gasCap, core.MessageGasEstimationMode) + result, err := doCall(ctx, b, args, state, header, nil, nil, 0, gasCap, core.MessageGasEstimationMode, blockNrOrHash) if err != nil { if errors.Is(err, core.ErrIntrinsicGas) { return true, nil, nil // Special case, raise gas limit @@ -1349,7 +1357,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr // We first execute the transaction at the highest allowable gas limit, since if this fails we // can return error immediately. - failed, result, err := executeEstimate(ctx, b, args, state.Copy(), header, vanillaGasCap, hi) + failed, result, err := executeEstimate(ctx, b, args, state.Copy(), header, vanillaGasCap, hi, &blockNrOrHash) if err != nil { return 0, err } @@ -1377,7 +1385,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr // range here is skewed to favor the low side. mid = lo * 2 } - failed, _, err = executeEstimate(ctx, b, args, state.Copy(), header, gasCap, mid) + failed, _, err = executeEstimate(ctx, b, args, state.Copy(), header, gasCap, mid, &blockNrOrHash) if err != nil { // This should not happen under normal conditions since if we make it this far the // transaction had run without error at least once before. @@ -1399,7 +1407,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr // value is capped by both `args.Gas` (if non-nil & non-zero) and the backend's RPCGasCap // configuration (if non-zero). func (s *BlockChainAPI) EstimateGas(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Uint64, error) { - bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) + bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) if blockNrOrHash != nil { bNrOrHash = *blockNrOrHash }