Skip to content

Commit 44fa016

Browse files
committed
Pass native amount to estimate gas if non-zero
There's an upstream geth bug where gas estimation fails unless a non-zero Value provided as a call arg. This bug doesn't affect Optimism right now, but it will in the future once we upgrade to Bedrock. We pass the Value now in rosetta so we don't regress after the Bedrock upgrade. Providing the Value call arg is a no-op right now. fixes #10
1 parent 73f8b60 commit 44fa016

File tree

2 files changed

+54
-5
lines changed

2 files changed

+54
-5
lines changed

services/construction_service.go

+11-5
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ func (s *ConstructionAPIService) ConstructionMetadata(
259259
to = checkTokenContractAddress
260260

261261
var err *types.Error
262-
gasLimit, err = s.calculateGasLimit(ctx, checkFrom, checkTokenContractAddress, input.Data)
262+
gasLimit, err = s.calculateGasLimit(ctx, checkFrom, checkTokenContractAddress, input.Data, nil)
263263
if err != nil {
264264
return nil, err
265265
}
@@ -278,7 +278,7 @@ func (s *ConstructionAPIService) ConstructionMetadata(
278278
to = checkContractAddress
279279

280280
var err *types.Error
281-
gasLimit, err = s.calculateGasLimit(ctx, checkFrom, checkContractAddress, input.Data)
281+
gasLimit, err = s.calculateGasLimit(ctx, checkFrom, checkContractAddress, input.Data, input.Value)
282282
if err != nil {
283283
return nil, err
284284
}
@@ -602,13 +602,19 @@ func (s *ConstructionAPIService) calculateGasLimit(
602602
from string,
603603
to string,
604604
data []byte,
605+
value *big.Int,
605606
) (uint64, *types.Error) {
606607
fromAddress := common.HexToAddress(from)
607608
toAddress := common.HexToAddress(to)
609+
var v *big.Int
610+
if value != nil && value.Cmp(big.NewInt(0)) != 0 {
611+
v = value
612+
}
608613
gasLimit, err := s.client.EstimateGas(ctx, ethereum.CallMsg{
609-
From: fromAddress,
610-
To: &toAddress,
611-
Data: data,
614+
From: fromAddress,
615+
To: &toAddress,
616+
Data: data,
617+
Value: v,
612618
})
613619

614620
if err != nil {

services/construction_service_test.go

+43
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,49 @@ func TestMetadata(t *testing.T) {
437437
},
438438
},
439439
},
440+
"happy path: Generic contract call with value": {
441+
options: map[string]interface{}{
442+
"from": metadataFrom,
443+
"to": metadataTo,
444+
"value": "0x5f5e100",
445+
"nonce": transferNonceHex2,
446+
"contract_address": tokenContractAddress,
447+
"data": metadataGenericData,
448+
"method_signature": "approve(address,uint256)",
449+
"method_args": []string{"0xD10a72Cf054650931365Cc44D912a4FD75257058", "1000"},
450+
},
451+
mocks: func(ctx context.Context, client *mocks.Client) {
452+
to := common.HexToAddress(tokenContractAddress)
453+
dataBytes, _ := hexutil.Decode(metadataGenericData)
454+
client.On("EstimateGas", ctx, ethereum.CallMsg{
455+
From: common.HexToAddress(metadataFrom),
456+
To: &to,
457+
Data: dataBytes,
458+
Value: big.NewInt(100000000),
459+
}).Return(transferGasLimitERC20, nil)
460+
461+
client.On("SuggestGasPrice", ctx).
462+
Return(big.NewInt(int64(transferGasPrice)), nil)
463+
},
464+
expectedResponse: &types.ConstructionMetadataResponse{
465+
Metadata: map[string]interface{}{
466+
"to": tokenContractAddress,
467+
"value": "0x5f5e100",
468+
"nonce": transferNonceHex2,
469+
"gas_price": transferGasPriceHex,
470+
"gas_limit": transferGasLimitERC20Hex,
471+
"data": metadataGenericData,
472+
"method_signature": "approve(address,uint256)",
473+
"method_args": []interface{}{"0xD10a72Cf054650931365Cc44D912a4FD75257058", "1000"},
474+
},
475+
SuggestedFee: []*types.Amount{
476+
{
477+
Value: fmt.Sprintf("%d", transferGasPrice*transferGasLimitERC20),
478+
Currency: optimism.Currency,
479+
},
480+
},
481+
},
482+
},
440483
"error: missing source address": {
441484
options: map[string]interface{}{
442485
"to": metadataTo,

0 commit comments

Comments
 (0)