accounts/abi/bind/backend, internal/ethapi: recap gas limit with balance (#21043)
* accounts/abi/bind/backend, internal/ethapi: recap gas limit with balance * accounts, internal: address comment and fix lint * accounts, internal: extend log message * tiny nits to format hexutil.Big and nil properly Co-authored-by: Péter Szilágyi <peterke@gmail.com>
This commit is contained in:
		| @@ -906,6 +906,11 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNrOrHash | ||||
| 		hi  uint64 | ||||
| 		cap uint64 | ||||
| 	) | ||||
| 	// Use zero address if sender unspecified. | ||||
| 	if args.From == nil { | ||||
| 		args.From = new(common.Address) | ||||
| 	} | ||||
| 	// Determine the highest gas limit can be used during the estimation. | ||||
| 	if args.Gas != nil && uint64(*args.Gas) >= params.TxGas { | ||||
| 		hi = uint64(*args.Gas) | ||||
| 	} else { | ||||
| @@ -916,16 +921,38 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNrOrHash | ||||
| 		} | ||||
| 		hi = block.GasLimit() | ||||
| 	} | ||||
| 	// Recap the highest gas limit with account's available balance. | ||||
| 	if args.GasPrice != nil && args.GasPrice.ToInt().Uint64() != 0 { | ||||
| 		state, _, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) | ||||
| 		if err != nil { | ||||
| 			return 0, err | ||||
| 		} | ||||
| 		balance := state.GetBalance(*args.From) // from can't be nil | ||||
| 		available := new(big.Int).Set(balance) | ||||
| 		if args.Value != nil { | ||||
| 			if args.Value.ToInt().Cmp(available) >= 0 { | ||||
| 				return 0, errors.New("insufficient funds for transfer") | ||||
| 			} | ||||
| 			available.Sub(available, args.Value.ToInt()) | ||||
| 		} | ||||
| 		allowance := new(big.Int).Div(available, args.GasPrice.ToInt()) | ||||
| 		if hi > allowance.Uint64() { | ||||
| 			transfer := args.Value | ||||
| 			if transfer == nil { | ||||
| 				transfer = new(hexutil.Big) | ||||
| 			} | ||||
| 			log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance, | ||||
| 				"sent", transfer.ToInt(), "gasprice", args.GasPrice.ToInt(), "fundable", allowance) | ||||
| 			hi = allowance.Uint64() | ||||
| 		} | ||||
| 	} | ||||
| 	// Recap the highest gas allowance with specified gascap. | ||||
| 	if gasCap != nil && hi > gasCap.Uint64() { | ||||
| 		log.Warn("Caller gas above allowance, capping", "requested", hi, "cap", gasCap) | ||||
| 		hi = gasCap.Uint64() | ||||
| 	} | ||||
| 	cap = hi | ||||
|  | ||||
| 	// Use zero address if sender unspecified. | ||||
| 	if args.From == nil { | ||||
| 		args.From = new(common.Address) | ||||
| 	} | ||||
| 	// Create a helper to check if a gas allowance results in an executable transaction | ||||
| 	executable := func(gas uint64) (bool, *core.ExecutionResult, error) { | ||||
| 		args.Gas = (*hexutil.Uint64)(&gas) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user