@@ -75,56 +75,8 @@ func (args *TransactionArgs) data() []byte {
7575
7676// setDefaults fills in default values for unspecified tx fields.
7777func (args * TransactionArgs ) setDefaults (ctx context.Context , b Backend ) error {
78- if args .GasPrice != nil && (args .MaxFeePerGas != nil || args .MaxPriorityFeePerGas != nil ) {
79- return errors .New ("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified" )
80- }
81- // After london, default to 1559 unless gasPrice is set
82- head := b .CurrentHeader ()
83- // If user specifies both maxPriorityfee and maxFee, then we do not
84- // need to consult the chain for defaults. It's definitely a London tx.
85- if args .MaxPriorityFeePerGas == nil || args .MaxFeePerGas == nil {
86- // In this clause, user left some fields unspecified.
87- if b .ChainConfig ().IsLondon (head .Number ) && args .GasPrice == nil {
88- if args .MaxPriorityFeePerGas == nil {
89- tip , err := b .SuggestGasTipCap (ctx )
90- if err != nil {
91- return err
92- }
93- args .MaxPriorityFeePerGas = (* hexutil .Big )(tip )
94- }
95- if args .MaxFeePerGas == nil {
96- gasFeeCap := new (big.Int ).Add (
97- (* big .Int )(args .MaxPriorityFeePerGas ),
98- new (big.Int ).Mul (head .BaseFee , big .NewInt (2 )),
99- )
100- args .MaxFeePerGas = (* hexutil .Big )(gasFeeCap )
101- }
102- if args .MaxFeePerGas .ToInt ().Cmp (args .MaxPriorityFeePerGas .ToInt ()) < 0 {
103- return fmt .Errorf ("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)" , args .MaxFeePerGas , args .MaxPriorityFeePerGas )
104- }
105- } else {
106- if args .MaxFeePerGas != nil || args .MaxPriorityFeePerGas != nil {
107- return errors .New ("maxFeePerGas or maxPriorityFeePerGas specified but london is not active yet" )
108- }
109- if args .GasPrice == nil {
110- price , err := b .SuggestGasTipCap (ctx )
111- if err != nil {
112- return err
113- }
114- if b .ChainConfig ().IsLondon (head .Number ) {
115- // The legacy tx gas price suggestion should not add 2x base fee
116- // because all fees are consumed, so it would result in a spiral
117- // upwards.
118- price .Add (price , head .BaseFee )
119- }
120- args .GasPrice = (* hexutil .Big )(price )
121- }
122- }
123- } else {
124- // Both maxPriorityfee and maxFee set by caller. Sanity-check their internal relation
125- if args .MaxFeePerGas .ToInt ().Cmp (args .MaxPriorityFeePerGas .ToInt ()) < 0 {
126- return fmt .Errorf ("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)" , args .MaxFeePerGas , args .MaxPriorityFeePerGas )
127- }
78+ if err := args .setFeeDefaults (ctx , b ); err != nil {
79+ return err
12880 }
12981 if args .Value == nil {
13082 args .Value = new (hexutil.Big )
@@ -178,6 +130,72 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
178130 return nil
179131}
180132
133+ // setFeeDefaults fills in default fee values for unspecified tx fields.
134+ func (args * TransactionArgs ) setFeeDefaults (ctx context.Context , b Backend ) error {
135+ // If both gasPrice and at least one of the EIP-1559 fee parameters are specified, error.
136+ if args .GasPrice != nil && (args .MaxFeePerGas != nil || args .MaxPriorityFeePerGas != nil ) {
137+ return errors .New ("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified" )
138+ }
139+ // If the tx has completely specified a fee mechanism, no default is needed. This allows users
140+ // who are not yet synced past London to get defaults for other tx values. See
141+ // https://github.com/ethereum/go-ethereum/pull/23274 for more information.
142+ eip1559ParamsSet := args .MaxFeePerGas != nil && args .MaxPriorityFeePerGas != nil
143+ if (args .GasPrice != nil && ! eip1559ParamsSet ) || (args .GasPrice == nil && eip1559ParamsSet ) {
144+ // Sanity check the EIP-1559 fee parameters if present.
145+ if args .GasPrice == nil && args .MaxFeePerGas .ToInt ().Cmp (args .MaxPriorityFeePerGas .ToInt ()) < 0 {
146+ return fmt .Errorf ("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)" , args .MaxFeePerGas , args .MaxPriorityFeePerGas )
147+ }
148+ return nil
149+ }
150+ // Now attempt to fill in default value depending on whether London is active or not.
151+ head := b .CurrentHeader ()
152+ if b .ChainConfig ().IsLondon (head .Number ) {
153+ // London is active, set maxPriorityFeePerGas and maxFeePerGas.
154+ if err := args .setLondonFeeDefaults (ctx , head , b ); err != nil {
155+ return err
156+ }
157+ } else {
158+ if args .MaxFeePerGas != nil || args .MaxPriorityFeePerGas != nil {
159+ return fmt .Errorf ("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active" )
160+ }
161+ // London not active, set gas price.
162+ price , err := b .SuggestGasTipCap (ctx )
163+ if err != nil {
164+ return err
165+ }
166+ args .GasPrice = (* hexutil .Big )(price )
167+ }
168+ return nil
169+ }
170+
171+ // setLondonFeeDefaults fills in reasonable default fee values for unspecified fields.
172+ func (args * TransactionArgs ) setLondonFeeDefaults (ctx context.Context , head * types.Header , b Backend ) error {
173+ // Set maxPriorityFeePerGas if it is missing.
174+ if args .MaxPriorityFeePerGas == nil {
175+ tip , err := b .SuggestGasTipCap (ctx )
176+ if err != nil {
177+ return err
178+ }
179+ args .MaxPriorityFeePerGas = (* hexutil .Big )(tip )
180+ }
181+ // Set maxFeePerGas if it is missing.
182+ if args .MaxFeePerGas == nil {
183+ // Set the max fee to be 2 times larger than the previous block's base fee.
184+ // The additional slack allows the tx to not become invalidated if the base
185+ // fee is rising.
186+ val := new (big.Int ).Add (
187+ args .MaxPriorityFeePerGas .ToInt (),
188+ new (big.Int ).Mul (head .BaseFee , big .NewInt (2 )),
189+ )
190+ args .MaxFeePerGas = (* hexutil .Big )(val )
191+ }
192+ // Both EIP-1559 fee parameters are now set; sanity check them.
193+ if args .MaxFeePerGas .ToInt ().Cmp (args .MaxPriorityFeePerGas .ToInt ()) < 0 {
194+ return fmt .Errorf ("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)" , args .MaxFeePerGas , args .MaxPriorityFeePerGas )
195+ }
196+ return nil
197+ }
198+
181199// ToMessage converts the transaction arguments to the Message type used by the
182200// core evm. This method is used in calls and traces that do not require a real
183201// live transaction.
0 commit comments