Skip to content

Commit 4dc0484

Browse files
committed
ethwallet, ethtxn, ethrpc, ethcoder: minor updates
1 parent 1ae9618 commit 4dc0484

File tree

4 files changed

+54
-6
lines changed

4 files changed

+54
-6
lines changed

ethcoder/hex.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ func MustHexDecode(h string) []byte {
2525
return b
2626
}
2727

28+
func HexToBigInt(h string) (*big.Int, error) {
29+
return hexutil.DecodeBig(h)
30+
}
31+
32+
func BigIntToHex(n *big.Int) string {
33+
return hexutil.EncodeBig(n)
34+
}
35+
36+
func HexEncodeBigInt(n *big.Int) string {
37+
return hexutil.EncodeBig(n)
38+
}
39+
2840
func HexDecodeBytes32(h string) ([32]byte, error) {
2941
slice, err := hexutil.Decode(h)
3042
if err != nil {
@@ -33,7 +45,6 @@ func HexDecodeBytes32(h string) ([32]byte, error) {
3345
if len(slice) != 32 {
3446
return [32]byte{}, errors.New("hex input is not 32 bytes")
3547
}
36-
3748
return BytesToBytes32(slice), nil
3849
}
3950

ethrpc/interface.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ type Interface interface {
123123
NetworkID(ctx context.Context) (*big.Int, error)
124124

125125
// BalanceAt = eth_getBalance
126+
// TODO: rename this to GetBalance and make blockNum optional, as optBlockNum *big.Int
126127
BalanceAt(ctx context.Context, account common.Address, blockNum *big.Int) (*big.Int, error)
127128

128129
// StorageAt = eth_getStorageAt

ethtxn/ethtxn.go

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ func NewTransaction(ctx context.Context, provider *ethrpc.Provider, txnRequest *
5959
return nil, fmt.Errorf("ethtxn: provider is not set")
6060
}
6161

62+
if txnRequest.Nonce == nil && txnRequest.From == (common.Address{}) {
63+
return nil, fmt.Errorf("ethtxn: from address is required when nonce is not set on txnRequest")
64+
}
6265
if txnRequest.Nonce == nil {
6366
nonce, err := provider.PendingNonceAt(ctx, txnRequest.From)
6467
if err != nil {
@@ -76,6 +79,40 @@ func NewTransaction(ctx context.Context, provider *ethrpc.Provider, txnRequest *
7679
txnRequest.GasPrice = gasPrice
7780
}
7881

82+
// If we're constructing a legacy (or access-list) transaction (ie. GasTip is nil) on a
83+
// post-London network, gasPrice MUST be >= baseFee. The node error you saw:
84+
// "max fee per gas less than block base fee" also applies to legacy txs internally
85+
// because the validation unifies the code paths. eth_gasPrice can occasionally return
86+
// a value slightly below the current baseFee if the baseFee just jumped. We defensively
87+
// bump it here. We also (optionally) add a small priority tip using SuggestGasTipCap so
88+
// the tx isn't sent with zero miner incentive (gasPrice == baseFee).
89+
if txnRequest.GasTip == nil { // staying in legacy/access-list mode
90+
if head, err := provider.HeaderByNumber(ctx, nil); err == nil && head != nil && head.BaseFee != nil {
91+
baseFee := head.BaseFee
92+
93+
// Base fee can increase by up to 12.5% per block (EIP-1559). We add headroom so a
94+
// transaction constructed right before a block is sealed doesn't become invalid if
95+
// the next block's baseFee rises. headroomBaseFee = baseFee * 1050/1000 (~+5.0%).
96+
// headroomBaseFee := new(big.Int).Mul(baseFee, big.NewInt(1125)) // 12.5%
97+
headroomBaseFee := new(big.Int).Mul(baseFee, big.NewInt(1050)) // 5%
98+
headroomBaseFee.Div(headroomBaseFee, big.NewInt(1000))
99+
100+
// We treat legacy gasPrice as (baseFee + implicit priority). Ensure gasPrice >= headroomBaseFee.
101+
if txnRequest.GasPrice.Cmp(headroomBaseFee) < 0 {
102+
// Optionally attempt to get a tip suggestion and add it on top of headroom base fee.
103+
if tip, err2 := provider.SuggestGasTipCap(ctx); err2 == nil && tip != nil {
104+
candidate := new(big.Int).Add(headroomBaseFee, tip)
105+
if txnRequest.GasPrice.Cmp(candidate) < 0 {
106+
txnRequest.GasPrice = candidate
107+
}
108+
} else {
109+
// Fallback just headroom base fee
110+
txnRequest.GasPrice = headroomBaseFee
111+
}
112+
}
113+
}
114+
}
115+
79116
if txnRequest.GasLimit == 0 {
80117
callMsg := ethereum.CallMsg{
81118
From: txnRequest.From,
@@ -103,7 +140,6 @@ func NewTransaction(ctx context.Context, provider *ethrpc.Provider, txnRequest *
103140
if err != nil {
104141
return nil, err
105142
}
106-
107143
rawTx = types.NewTx(&types.DynamicFeeTx{
108144
ChainID: chainId,
109145
To: txnRequest.To,
@@ -120,7 +156,6 @@ func NewTransaction(ctx context.Context, provider *ethrpc.Provider, txnRequest *
120156
if err != nil {
121157
return nil, err
122158
}
123-
124159
rawTx = types.NewTx(&types.AccessListTx{
125160
ChainID: chainId,
126161
To: txnRequest.To,
@@ -145,16 +180,16 @@ func NewTransaction(ctx context.Context, provider *ethrpc.Provider, txnRequest *
145180
return rawTx, nil
146181
}
147182

148-
func SendTransaction(ctx context.Context, provider *ethrpc.Provider, signedTx *types.Transaction) (*types.Transaction, WaitReceipt, error) {
183+
func SendTransaction(ctx context.Context, provider *ethrpc.Provider, signedTxn *types.Transaction) (*types.Transaction, WaitReceipt, error) {
149184
if provider == nil {
150185
return nil, nil, fmt.Errorf("ethtxn (SendTransaction): provider is not set")
151186
}
152187

153188
waitFn := func(ctx context.Context) (*types.Receipt, error) {
154-
return ethrpc.WaitForTxnReceipt(ctx, provider, signedTx.Hash())
189+
return ethrpc.WaitForTxnReceipt(ctx, provider, signedTxn.Hash())
155190
}
156191

157-
return signedTx, waitFn, provider.SendTransaction(ctx, signedTx)
192+
return signedTxn, waitFn, provider.SendTransaction(ctx, signedTxn)
158193
}
159194

160195
var zeroBigInt = big.NewInt(0)

ethwallet/ethwallet.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ func (w *Wallet) GetNonce(ctx context.Context) (uint64, error) {
235235
return w.GetProvider().NonceAt(ctx, w.Address(), nil)
236236
}
237237

238+
// TODO: rename this to SignTransaction, but add SignTx for backwards compatibility and add deprecation warning
238239
func (w *Wallet) SignTx(tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
239240
signer := types.LatestSignerForChainID(chainID)
240241
signedTx, err := types.SignTx(tx, signer, w.hdnode.PrivateKey())

0 commit comments

Comments
 (0)