Skip to content

Commit

Permalink
Merge pull request #32 from maticnetwork/andrew/enforce-base-fee-min
Browse files Browse the repository at this point in the history
enforce minimum gas price
  • Loading branch information
andrewkmin authored Jun 20, 2022
2 parents 8e10ca8 + 431e349 commit 8e74a8c
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 109 deletions.
7 changes: 3 additions & 4 deletions services/construction/combine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,11 @@ import (
"github.com/coinbase/rosetta-sdk-go/types"
svcError "github.com/maticnetwork/polygon-rosetta/services/errors"
"github.com/stretchr/testify/assert"
)

)

func TestConstructionCombine(t *testing.T) {
unsignedRaw := `{"from":"0x5aCB42b3cfCD734a57AFF800139ba1354b549159","to":"0x3Fa177c2E87Cb24148EC403921dB577d140CC07c","value":"0x3e8","data":"0x","nonce":"0x2","gas_price":"0x0","max_fee_per_gas":"0x59682f15","max_priority_fee_per_gas":"0x59682eff","gas":"0x5208","chain_id":"0x13881"}` // nolint
signedRaw := `{"type":"0x2","nonce":"0x2","gasPrice":null,"maxPriorityFeePerGas":"0x59682eff","maxFeePerGas":"0x59682f15","gas":"0x5208","value":"0x3e8","input":"0x","v":"0x1","r":"0x6afe2f65d311ff2430ca7388335b86e42606ea4728924d91564405df83d2cea5","s":"0x443a04f2d96ea9877ed67f2b45266446ab01de2154c268470f57bb12effa1563","to":"0x3fa177c2e87cb24148ec403921db577d140cc07c","chainId":"0x13881","accessList":[],"hash":"0x554c2edbd04b2be9d1314ef31201e3382eedb24a733f1b15448af2d16252db73"}` // nolint
unsignedRaw := `{"from":"0x5aCB42b3cfCD734a57AFF800139ba1354b549159","to":"0x3Fa177c2E87Cb24148EC403921dB577d140CC07c","value":"0x3e8","data":"0x","nonce":"0x2","gas_price":"0x0","max_fee_per_gas":"0x59682f15","max_priority_fee_per_gas":"0x59682eff","gas":"0x5208","chain_id":"0x13881"}` // nolint
signedRaw := `{"type":"0x2","nonce":"0x2","gasPrice":null,"maxPriorityFeePerGas":"0x59682eff","maxFeePerGas":"0x59682f15","gas":"0x5208","value":"0x3e8","input":"0x","v":"0x1","r":"0x6afe2f65d311ff2430ca7388335b86e42606ea4728924d91564405df83d2cea5","s":"0x443a04f2d96ea9877ed67f2b45266446ab01de2154c268470f57bb12effa1563","to":"0x3fa177c2e87cb24148ec403921db577d140cc07c","chainId":"0x13881","accessList":[],"hash":"0x554c2edbd04b2be9d1314ef31201e3382eedb24a733f1b15448af2d16252db73"}` // nolint
signaturesRaw := `[{"hex_bytes": "6afe2f65d311ff2430ca7388335b86e42606ea4728924d91564405df83d2cea5443a04f2d96ea9877ed67f2b45266446ab01de2154c268470f57bb12effa156301", "public_key": {"hex_bytes": "0405e82ac561143aafc13ba109677a597c8f797b07417d0addd7a346ad35882b3c4a006620e02127b9a32e90979ff93ecad0a2f577db238163a50023e393e354ff", "curve_type": "secp256k1"}, "signing_payload": {"hex_bytes": "15ff43e2bc6aacc7d0f0ed76eb3102aaf9b1292e2ba07575a4e4f3ddb5b54780", "address": "0x5aCB42b3cfCD734a57AFF800139ba1354b549159"}, "signature_type": "ecdsa_recovery"}]` // nolint
var signatures []*types.Signature
_ = json.Unmarshal([]byte(signaturesRaw), &signatures)
Expand Down
143 changes: 90 additions & 53 deletions services/construction/construction_service_test.go

Large diffs are not rendered by default.

18 changes: 13 additions & 5 deletions services/construction/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func (a *APIService) ConstructionMetadata(
}
}

header, err := a.client.BlockHeader(ctx, nil)
header, err := a.client.BlockHeader(ctx, nil)
if err != nil {
return nil, svcErrors.WrapErr(svcErrors.ErrGeth, err)
}
Expand All @@ -120,18 +120,25 @@ func (a *APIService) ConstructionMetadata(
var gasCap *big.Int
if input.GasCap == nil {
// Set default max fee to double the last base fee plus priority tip
// to ensure tx is highly likely to go out in the next block
// to ensure tx is highly likely to go out in the next block.
multiplier := big.NewInt(2)
gasCap = new(big.Int).Add(gasTip, new(big.Int).Mul(header.BaseFee, multiplier))
} else {
gasCap = input.GasCap
}

// Ensure the gas cap is at least 30 gwei, the minimum gas price that the node will accept on mainnet.
// See https://forum.polygon.technology/t/recommended-min-gas-price-setting/7604 for additional context.
minFee := big.NewInt(30000000000) // 30 gwei
if minFee.Cmp(gasCap) == 1 {
gasCap = minFee
}

metadata := &metadata{
Nonce: nonce,
GasLimit: gasLimit,
GasCap: gasCap,
GasTip: gasTip,
GasTip: gasTip,
Data: input.Data,
Value: input.Value,
To: to,
Expand All @@ -144,8 +151,9 @@ func (a *APIService) ConstructionMetadata(
return nil, svcErrors.WrapErr(svcErrors.ErrUnableToParseIntermediateResult, err)
}

// Find suggested gas usage
suggestedFee := (header.BaseFee.Int64() + metadata.GasTip.Int64()) * int64(gasLimit)
// Find suggested gas usage. Note that this figure accounts for the minimum (30 gwei), and
// is potentially doubled the block base fee.
suggestedFee := gasCap.Int64() * int64(gasLimit)

return &types.ConstructionMetadataResponse{
Metadata: metadataMap,
Expand Down
59 changes: 46 additions & 13 deletions services/construction/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ var (
metadataGenericData = "0x095ea7b3000000000000000000000000d10a72cf054650931365cc44d912a4fd7525705800000000000000000000000000000000000000000000000000000000000003e8"
maticTokenContract = "0x0000000000000000000000000000000000001010"
metadataMaticWithdrawData = "0x2e1a7d4d0000000000000000000000000000000000000000000000000000000005f5e100"

)

func TestMetadata_Offline(t *testing.T) {
Expand Down Expand Up @@ -77,12 +76,12 @@ func TestMetadata(t *testing.T) {
"value": transferValueHex,
"nonce": transferNonceHex2,
"gas_limit": transferGasLimitHex,
"gas_cap": transferGasCapHex,
"gas_cap": transferGasCapWithTipHex,
"gas_tip": transferGasTipHex,
},
SuggestedFee: []*types.Amount{
{
Value: fmt.Sprintf("%d", (header.BaseFee.Uint64() + transferGasTip) * transferGasLimit),
Value: fmt.Sprintf("%d", transferGasCapWithTip*transferGasLimit),
Currency: polygon.Currency,
},
},
Expand Down Expand Up @@ -124,17 +123,51 @@ func TestMetadata(t *testing.T) {
"value": transferValueHex,
"nonce": transferNonceHex,
"gas_limit": transferGasLimitHex,
"gas_cap": transferGasCapHex,
"gas_cap": transferGasCapWithTipHex,
"gas_tip": transferGasTipHex,
},
SuggestedFee: []*types.Amount{
{
Value: fmt.Sprintf("%d", (header.BaseFee.Uint64() + transferGasTip) * transferGasLimit),
Value: fmt.Sprintf("%d", transferGasCapWithTip*transferGasLimit),
Currency: polygon.Currency,
},
},
},
},
"happy path: native currency with gas tip set to 30 gwei floor": {
options: map[string]interface{}{
"from": metadataFrom,
"to": metadataTo,
"value": transferValueHex,
"nonce": transferNonceHex2,
},
expectedResponse: &types.ConstructionMetadataResponse{
Metadata: map[string]interface{}{
"to": metadataTo,
"value": transferValueHex,
"nonce": transferNonceHex2,
"gas_limit": transferGasLimitHex,
"gas_cap": minGasCapHex,
"gas_tip": transferGasTipHex,
},
SuggestedFee: []*types.Amount{
{
Value: fmt.Sprintf("%d", (minGasCap.Uint64())*transferGasLimit),
Currency: polygon.Currency,
},
},
},
mocks: func(ctx context.Context, client *mocks.Client) {
var blockNum *big.Int = nil

client.On("BlockHeader", ctx, blockNum).
Return(&headerWithLowBaseFee, nil)

client.On("SuggestGasTipCap", ctx).
Return(big.NewInt(int64(transferGasTip)), nil)

},
},
"happy path: ERC20 currency with nonce": {
options: map[string]interface{}{
"from": metadataFrom,
Expand Down Expand Up @@ -169,13 +202,13 @@ func TestMetadata(t *testing.T) {
"value": "0x0",
"nonce": transferNonceHex2,
"gas_limit": transferGasLimitERC20Hex,
"gas_cap": transferGasCapHex,
"gas_cap": transferGasCapWithTipHex,
"gas_tip": transferGasTipHex,
"data": metadataData,
},
SuggestedFee: []*types.Amount{
{
Value: fmt.Sprintf("%d", (header.BaseFee.Uint64() + transferGasTip) * transferGasLimitERC20),
Value: fmt.Sprintf("%d", transferGasCapWithTip*transferGasLimitERC20),
Currency: polygon.Currency,
},
},
Expand Down Expand Up @@ -217,15 +250,15 @@ func TestMetadata(t *testing.T) {
"value": "0x0",
"nonce": transferNonceHex2,
"gas_limit": transferGasLimitERC20Hex,
"gas_cap": transferGasCapHex,
"gas_tip": transferGasTipHex,
"gas_cap": transferGasCapWithTipHex,
"gas_tip": transferGasTipHex,
"data": metadataGenericData,
"method_signature": "approve(address,uint256)",
"method_args": []interface{}{"0xD10a72Cf054650931365Cc44D912a4FD75257058", "1000"},
},
SuggestedFee: []*types.Amount{
{
Value: fmt.Sprintf("%d", (header.BaseFee.Uint64() + transferGasTip) * transferGasLimitERC20),
Value: fmt.Sprintf("%d", transferGasCapWithTip*transferGasLimitERC20),
Currency: polygon.Currency,
},
},
Expand Down Expand Up @@ -267,15 +300,15 @@ func TestMetadata(t *testing.T) {
"value": "0x5f5e100",
"nonce": transferNonceHex2,
"gas_limit": transferGasLimitERC20Hex,
"gas_cap": transferGasCapHex,
"gas_tip": transferGasTipHex,
"gas_cap": transferGasCapWithTipHex,
"gas_tip": transferGasTipHex,
"data": metadataMaticWithdrawData,
"method_signature": "withdraw(uint256)",
"method_args": []interface{}{"100000000"},
},
SuggestedFee: []*types.Amount{
{
Value: fmt.Sprintf("%d", (header.BaseFee.Uint64() + transferGasTip) * transferGasLimitERC20),
Value: fmt.Sprintf("%d", transferGasCapWithTip*transferGasLimitERC20),
Currency: polygon.Currency,
},
},
Expand Down
30 changes: 15 additions & 15 deletions services/construction/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,28 @@ import (
)

var (
unsignedMaticTransferTx = `{"from":"0x5aCB42b3cfCD734a57AFF800139ba1354b549159","to":"0x3Fa177c2E87Cb24148EC403921dB577d140CC07c","value":"0x3e8","data":"0x","nonce":"0x2","max_fee_per_gas":"0x59682f15","max_priority_fee_per_gas":"0x59682eff","gas":"0x5208","chain_id":"0x13881"}` //nolint:lll
signedMaticTransferTx = `{"type":"0x2","nonce":"0x2","gasPrice":null,"maxPriorityFeePerGas":"0x59682eff","maxFeePerGas":"0x59682f15","gas":"0x5208","value":"0x3e8","input":"0x","v":"0x1","r":"0x6afe2f65d311ff2430ca7388335b86e42606ea4728924d91564405df83d2cea5","s":"0x443a04f2d96ea9877ed67f2b45266446ab01de2154c268470f57bb12effa1563","to":"0x3fa177c2e87cb24148ec403921db577d140cc07c","chainId":"0x13881","accessList":[],"hash":"0x554c2edbd04b2be9d1314ef31201e3382eedb24a733f1b15448af2d16252db73"}` //nolint:lll
unsignedERC20TransferTx = `{"from":"0x5aCB42b3cfCD734a57AFF800139ba1354b549159","to":"0x2d7882beDcbfDDce29Ba99965dd3cdF7fcB10A1e","value":"0x0","data":"0xa9059cbb0000000000000000000000003fa177c2e87cb24148ec403921db577d140cc07c0000000000000000000000000000000000000000000000000000000000000064","nonce":"0x2","max_fee_per_gas":"0x9502f914","max_priority_fee_per_gas":"0x9502f900","gas":"0xb2cb","chain_id":"0x13881"}` //nolint:lll
signedERC20TransferTx = `{"type":"0x2","nonce":"0x2","gasPrice":null,"maxPriorityFeePerGas":"0x9502f900","maxFeePerGas":"0x9502f914","gas":"0xb2cb","value":"0x0","input":"0xa9059cbb0000000000000000000000003fa177c2e87cb24148ec403921db577d140cc07c0000000000000000000000000000000000000000000000000000000000000064","v":"0x1","r":"0x2a8799b115741f62d5da931a53428ad1e3bf3055e9ea8427ce196a44cc590fca","s":"0x4779ab01b496c8b27e19efd24817557609b50da0d7e1a3790c435ca2225b43ae","to":"0x2d7882bedcbfddce29ba99965dd3cdf7fcb10a1e","chainId":"0x13881","accessList":[],"hash":"0xaa0f2056a79315e60a2012aee5f582692817e12153c6e45f57215f848893ec9e"}` //nolint:lll
unsignedERC20TransferTxInvalidData = `"{"from":"0x5aCB42b3cfCD734a57AFF800139ba1354b549159","to":"0x2d7882beDcbfDDce29Ba99965dd3cdF7fcB10A1e","value":"0x0","data":"0xaaaaaaaa000000000000000000000000efd3dc58d60af3295b92ecd484caeb3a2f30b3e7000000000000000000000000000000000000000000000000000000000134653c","nonce":"0x2","max_fee_per_gas":"0x9502f914","max_priority_fee_per_gas":"0x9502f900","gas":"0xb2cb","chain_id":"0x13881"}"` //nolint:lll
unsignedMaticTransferTxInvalidFrom = `{"from":"invalid_from","to":"0x3Fa177c2E87Cb24148EC403921dB577d140CC07c","value":"0x3e8","data":"0x","nonce":"0x2","max_fee_per_gas":"0x59682f15","max_priority_fee_per_gas":"0x59682eff","gas":"0x5208","chain_id":"0x13881"}` //nolint:lll
unsignedMaticTransferTxInvalidTo = `{"from":"0x5aCB42b3cfCD734a57AFF800139ba1354b549159","to":"invalid_to","value":"0x3e8","data":"0x","nonce":"0x2","max_fee_per_gas":"0x59682f15","max_priority_fee_per_gas":"0x59682eff","gas":"0x5208","chain_id":"0x13881"}` //nolint:lll
unsignedMaticTransferTx = `{"from":"0x5aCB42b3cfCD734a57AFF800139ba1354b549159","to":"0x3Fa177c2E87Cb24148EC403921dB577d140CC07c","value":"0x3e8","data":"0x","nonce":"0x2","max_fee_per_gas":"0x59682f15","max_priority_fee_per_gas":"0x59682eff","gas":"0x5208","chain_id":"0x13881"}` //nolint:lll
signedMaticTransferTx = `{"type":"0x2","nonce":"0x2","gasPrice":null,"maxPriorityFeePerGas":"0x59682eff","maxFeePerGas":"0x59682f15","gas":"0x5208","value":"0x3e8","input":"0x","v":"0x1","r":"0x6afe2f65d311ff2430ca7388335b86e42606ea4728924d91564405df83d2cea5","s":"0x443a04f2d96ea9877ed67f2b45266446ab01de2154c268470f57bb12effa1563","to":"0x3fa177c2e87cb24148ec403921db577d140cc07c","chainId":"0x13881","accessList":[],"hash":"0x554c2edbd04b2be9d1314ef31201e3382eedb24a733f1b15448af2d16252db73"}` //nolint:lll
unsignedERC20TransferTx = `{"from":"0x5aCB42b3cfCD734a57AFF800139ba1354b549159","to":"0x2d7882beDcbfDDce29Ba99965dd3cdF7fcB10A1e","value":"0x0","data":"0xa9059cbb0000000000000000000000003fa177c2e87cb24148ec403921db577d140cc07c0000000000000000000000000000000000000000000000000000000000000064","nonce":"0x2","max_fee_per_gas":"0x9502f914","max_priority_fee_per_gas":"0x9502f900","gas":"0xb2cb","chain_id":"0x13881"}` //nolint:lll
signedERC20TransferTx = `{"type":"0x2","nonce":"0x2","gasPrice":null,"maxPriorityFeePerGas":"0x9502f900","maxFeePerGas":"0x9502f914","gas":"0xb2cb","value":"0x0","input":"0xa9059cbb0000000000000000000000003fa177c2e87cb24148ec403921db577d140cc07c0000000000000000000000000000000000000000000000000000000000000064","v":"0x1","r":"0x2a8799b115741f62d5da931a53428ad1e3bf3055e9ea8427ce196a44cc590fca","s":"0x4779ab01b496c8b27e19efd24817557609b50da0d7e1a3790c435ca2225b43ae","to":"0x2d7882bedcbfddce29ba99965dd3cdf7fcb10a1e","chainId":"0x13881","accessList":[],"hash":"0xaa0f2056a79315e60a2012aee5f582692817e12153c6e45f57215f848893ec9e"}` //nolint:lll
unsignedERC20TransferTxInvalidData = `"{"from":"0x5aCB42b3cfCD734a57AFF800139ba1354b549159","to":"0x2d7882beDcbfDDce29Ba99965dd3cdF7fcB10A1e","value":"0x0","data":"0xaaaaaaaa000000000000000000000000efd3dc58d60af3295b92ecd484caeb3a2f30b3e7000000000000000000000000000000000000000000000000000000000134653c","nonce":"0x2","max_fee_per_gas":"0x9502f914","max_priority_fee_per_gas":"0x9502f900","gas":"0xb2cb","chain_id":"0x13881"}"` //nolint:lll
unsignedMaticTransferTxInvalidFrom = `{"from":"invalid_from","to":"0x3Fa177c2E87Cb24148EC403921dB577d140CC07c","value":"0x3e8","data":"0x","nonce":"0x2","max_fee_per_gas":"0x59682f15","max_priority_fee_per_gas":"0x59682eff","gas":"0x5208","chain_id":"0x13881"}` //nolint:lll
unsignedMaticTransferTxInvalidTo = `{"from":"0x5aCB42b3cfCD734a57AFF800139ba1354b549159","to":"invalid_to","value":"0x3e8","data":"0x","nonce":"0x2","max_fee_per_gas":"0x59682f15","max_priority_fee_per_gas":"0x59682eff","gas":"0x5208","chain_id":"0x13881"}` //nolint:lll

parseFromAddress = "0x5aCB42b3cfCD734a57AFF800139ba1354b549159"
parseToAddress = "0x3Fa177c2E87Cb24148EC403921dB577d140CC07c"
parseFromAddress = "0x5aCB42b3cfCD734a57AFF800139ba1354b549159"
parseToAddress = "0x3Fa177c2E87Cb24148EC403921dB577d140CC07c"
parseTokenContractAddress = "0x2d7882beDcbfDDce29Ba99965dd3cdF7fcB10A1e"

gasCapHex = "0x59682f15"
gasTipHex = "0x59682eff"
nonceHex = "0x2"
value = uint64(1000)
gasCapHex = "0x59682f15"
gasTipHex = "0x59682eff"
nonceHex = "0x2"
value = uint64(1000)

gasCapERC20Hex = "0x9502f914"
gasTipERC20Hex = "0x9502f900"
gasLimitERC20Hex = "0xb2cb"
nonceERC20Hex = "0x2"
valueERC20 = uint64(100)
nonceERC20Hex = "0x2"
valueERC20 = uint64(100)
)

func TestParse(t *testing.T) {
Expand Down
Loading

0 comments on commit 8e74a8c

Please sign in to comment.