go-ethereum SimulatedBackend报max fee per gas低于block base fee错误如何解决
问题根因
- 报错确实和以太坊伦敦升级引入的EIP1559机制相关:新版本的go-ethereum SimulatedBackend默认启用了base fee规则,所有交易的
maxFeePerGas必须大于等于当前区块的base fee才能被打包。 - 你设置
auth.GasFeeCap不生效的核心原因是:你没有使用auth对象构造交易,而是手动调用types.NewTransaction创建了legacy类型的交易,auth的配置完全没有被用到。 - 当前你构造的legacy交易中,
gasPrice仅为1 wei,远低于区块的base fee(875000000 wei),所以触发panic。
修复方案
这里给出两种可正常运行的实现方式:
方式1:直接使用TransactOpts发送交易(更简便)
不用手动构造交易,直接用bind包的TransactOpts相关逻辑,配置会自动生效:
package eth import ( "context" "math/big" "testing" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/crypto" ) func TestSimulatedBackend(t *testing.T) { privateKey, err := crypto.GenerateKey() if err != nil { t.Fatalf("failed to generate key: %v", err) } auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1337)) if err != nil { t.Fatalf("failed to generate transactor: %v", err) } // 这里配置的GasFeeCap才会生效 auth.GasFeeCap = big.NewInt(1000000000) // 1gwei,高于base fee即可 auth.GasTipCap = big.NewInt(1000000000) auth.GasLimit = 21000 balance := new(big.Int) balance.SetString("10000000000000000000", 10) // 10 eth in wei address := auth.From genesisAlloc := map[common.Address]core.GenesisAccount{ address: { Balance: balance, }, } blockGasLimit := uint64(4712388) client := backends.NewSimulatedBackend(genesisAlloc, blockGasLimit) toAddress := common.HexToAddress("0x4592d8f8d7b001e72cb26a73e4fa1806a51ac79d") // 直接用TransactOpts构造转账交易 tx, err := bind.SendEther(auth, client, toAddress, big.NewInt(1000000000000000000), nil) if err != nil { t.Fatalf("failed to send transaction: %v", err) } t.Logf("tx sent: %s\n", tx.Hash().Hex()) client.Commit() receipt, err := client.TransactionReceipt(context.Background(), tx.Hash()) if err != nil { t.Fatalf("failed to get transaction receipt: %v", err) } if receipt == nil { t.Fatal("receipt is empty") } t.Logf("status: %v\n", receipt.Status) // status: 1 }
方式2:手动构造EIP1559类型交易
如果你需要手动构造交易,改用DynamicFeeTx类型即可,只需要替换原有交易构造部分的代码:
nonce, err := client.PendingNonceAt(context.Background(), fromAddress) if err != nil { t.Fatalf("failed to get nonce: %v", err) } value := big.NewInt(1000000000000000000) // 1 eth gasLimit := uint64(21000) toAddress := common.HexToAddress("0x4592d8f8d7b001e72cb26a73e4fa1806a51ac79d") // 构造EIP1559交易参数 tx := types.NewTx(&types.DynamicFeeTx{ ChainID: big.NewInt(1337), Nonce: nonce, GasTipCap: big.NewInt(1000000000), // 优先级费 GasFeeCap: big.NewInt(1000000000), // 最高付费,高于base fee即可 Gas: gasLimit, To: &toAddress, Value: value, Data: nil, }) // 签名使用LondonSigner即可 signedTx, err := types.SignTx(tx, types.NewLondonSigner(big.NewInt(1337)), privateKey) if err != nil { t.Fatalf("failed to sign transaction: %v", err) }
内容的提问来源于stack exchange,提问作者Arjan van Eersel
相关产品推荐
相关产品推荐

