Skip to content

Commit

Permalink
Merge pull request #33 from maticnetwork/andrew/priority-fee-multiplier
Browse files Browse the repository at this point in the history
update metadata implementation to enforce minimum gas tip
  • Loading branch information
andrewkmin authored Jun 24, 2022
2 parents 8e74a8c + c49a162 commit 3e9c8aa
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 81 deletions.
98 changes: 36 additions & 62 deletions services/construction/construction_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"math/big"
"testing"

Expand All @@ -38,19 +39,16 @@ import (
)

var (
//// Network-related variables
networkIdentifier = &types.NetworkIdentifier{
Network: polygon.TestnetNetwork,
Blockchain: polygon.Blockchain,
}

chainID = uint64(80001)
chainIDHex = hexutil.EncodeUint64(chainID)

fromAddress = "0x966fbC4E1F3a938Cf7798695C3244d9C7C190015"
toAddress = "0xefD3dc58D60aF3295B92ecd484CAEB3A2f30b3e7"
tokenContractAddress = "0x2d7882beDcbfDDce29Ba99965dd3cdF7fcB10A1e"

// key is unsafe for use in prod :)
//// Transfer-related variables
// This key is unsafe for use in prod :)
transferAddress = constructionAddress{
privateKey: "00fe21cc72608106f87959c32c27debbbc31ad9a45e8f50021cfdf0c3d8acb1d",
compressedPublicKey: "03df5c7854e2264f641773f12fa3ce186ef1ebb294a7842ae7f3ef46ba502f7bff",
Expand All @@ -61,26 +59,26 @@ var (
constructionFromAddress = transferAddress.address
constructionToAddress = "0x3Fa177c2E87Cb24148EC403921dB577d140CC07c"

transferValue = uint64(20211004)
transferGasLimit = uint64(21000)
transferGasLimitERC20 = uint64(65000)
transferNonce = uint64(67)
transferData = "0xa9059cbb000000000000000000000000efd3dc58d60af3295b92ecd484caeb3a2f30b3e7000000000000000000000000000000000000000000000000000000000134653c" //nolint
transferGasCap = uint64(60000000000) // 60 gwei
transferGasTip = uint64(1500000000) // 1.5 gwei
transferGasCapWithTip = transferGasCap + transferGasTip // 61.5 gwei

transferValue = uint64(20211004)
transferValueHex = hexutil.EncodeUint64(transferValue) // 0x134653C
transferGasLimit = uint64(21000)
transferGasLimitHex = hexutil.EncodeUint64(transferGasLimit) // 0x5208
transferGasLimitERC20 = uint64(65000)
transferGasLimitERC20Hex = hexutil.EncodeUint64(transferGasLimitERC20) // 0xFDE8
transferNonceHex = hexutil.EncodeUint64(transferNonce)
transferNonce = uint64(67)
transferNonceHex = hexutil.EncodeUint64(transferNonce) // 0x43
transferNonceHex2 = "0x22"
transferGasCapHex = hexutil.EncodeUint64(transferGasCap) // 0xdf8475800
transferGasTipHex = hexutil.EncodeUint64(transferGasTip) // 0x59682F00
transferGasCapWithTipHex = hexutil.EncodeUint64(transferGasCapWithTip) // 0xE51AF8700

minGasCap = big.NewInt(30000000000)
minGasCapHex = hexutil.EncodeUint64(minGasCap.Uint64())
transferData = "0xa9059cbb000000000000000000000000efd3dc58d60af3295b92ecd484caeb3a2f30b3e7000000000000000000000000000000000000000000000000000000000134653c" //nolint
transferGasCap = uint64(30000000000) // 30 gwei
// transferGasCapHex = hexutil.EncodeUint64(transferGasCap) // 0x6FC23AC00
transferGasTip = uint64(30000000000) // 30 gwei, accounts for floor
transferGasTipHex = hexutil.EncodeUint64(transferGasTip) // 0x6FC23AC00
transferGasTipEstimate = uint64(3000000000) // 3 gwei
// transferGasTipEstimateHex = hexutil.EncodeUint64(transferGasTip) // 0xB2D05E00
transferGasCapWithTip = transferGasCap + 2*transferGasTip // 90 gwei
transferGasCapWithTipHex = hexutil.EncodeUint64(transferGasCapWithTip) // 0x14F46B0400
minGasCap = big.NewInt(30000000000)
// minGasCapHex = hexutil.EncodeUint64(minGasCap.Uint64())

header = EthTypes.Header{
ParentHash: common.Hash{},
Expand All @@ -98,23 +96,6 @@ var (
Extra: hexutil.Bytes{},
BaseFee: minGasCap, // equivalent to 30 gwei, previously 500000
}

headerWithLowBaseFee = EthTypes.Header{
ParentHash: common.Hash{},
UncleHash: common.Hash{},
Coinbase: common.Address{},
Root: common.Hash{},
TxHash: common.Hash{},
ReceiptHash: common.Hash{},
Bloom: EthTypes.Bloom{},
Difficulty: nil,
Number: nil,
GasLimit: 0,
GasUsed: 0,
Time: 0,
Extra: hexutil.Bytes{},
BaseFee: big.NewInt(10000000000), // equivalent to 10 gwei
}
)

type constructionAddress struct {
Expand Down Expand Up @@ -215,7 +196,7 @@ func TestConstructionFlowWithPendingNonce(t *testing.T) {
"SuggestGasTipCap",
ctx,
).Return(
big.NewInt(int64(transferGasTip)),
big.NewInt(int64(transferGasTipEstimate)), // this value is to be overriden by the 30 gwei min
nil,
).Once()
mockClient.On(
Expand All @@ -235,24 +216,26 @@ func TestConstructionFlowWithPendingNonce(t *testing.T) {
Metadata: forceMarshalMap(t, metadata),
SuggestedFee: []*types.Amount{
{
Value: "1291500000000000",
Value: "1890000000000000",
Currency: polygon.Currency,
},
},
}, metadataResponse)

// Test Payloads
unsignedRaw := `{"from":"0xda75C156Bc4b518ac4b91Ee942BE2B2e2e36e8C1","to":"0x3Fa177c2E87Cb24148EC403921dB577d140CC07c","value":"0x3e8","data":"0x","nonce":"0x0","max_fee_per_gas":"0xe51af8700","max_priority_fee_per_gas":"0x59682f00","gas":"0x5208","chain_id":"0x13881"}`
unsignedRaw := `{"from":"0xda75C156Bc4b518ac4b91Ee942BE2B2e2e36e8C1","to":"0x3Fa177c2E87Cb24148EC403921dB577d140CC07c","value":"0x3e8","data":"0x","nonce":"0x0","max_fee_per_gas":"0x14f46b0400","max_priority_fee_per_gas":"0x6fc23ac00","gas":"0x5208","chain_id":"0x13881"}`
payloadsResponse, err := servicer.ConstructionPayloads(ctx, &types.ConstructionPayloadsRequest{
NetworkIdentifier: networkIdentifier,
Operations: ops,
Metadata: forceMarshalMap(t, metadata),
})
assert.Nil(t, err)

payloadsRaw := `[{"address":"0xda75C156Bc4b518ac4b91Ee942BE2B2e2e36e8C1","hex_bytes":"0206e22e9bded068a76f89a86e0849b7e6ff8f6e8a22e1b679fd87a08635a9f2","account_identifier":{"address":"0xda75C156Bc4b518ac4b91Ee942BE2B2e2e36e8C1"},"signature_type":"ecdsa_recovery"}]`
payloadsRaw := `[{"address":"0xda75C156Bc4b518ac4b91Ee942BE2B2e2e36e8C1","hex_bytes":"bf0f517f63d9361336b5cc7b3a17b90bc0823a8085dc438347c5cbaf8f7520f5","account_identifier":{"address":"0xda75C156Bc4b518ac4b91Ee942BE2B2e2e36e8C1"},"signature_type":"ecdsa_recovery"}]`
var payloads []*types.SigningPayload
assert.NoError(t, json.Unmarshal([]byte(payloadsRaw), &payloads))
fmt.Printf("raw payloads: %x\n", payloads[0].Bytes)
fmt.Printf("raw payloads response: %x\n", payloadsResponse.Payloads[0].Bytes)
assert.Equal(t, &types.ConstructionPayloadsResponse{
UnsignedTransaction: unsignedRaw,
Payloads: payloads,
Expand Down Expand Up @@ -282,10 +265,10 @@ func TestConstructionFlowWithPendingNonce(t *testing.T) {
}, parseUnsignedResponse)

// Test Combine
signaturesRaw := `[{"hex_bytes":"660e6778daed0d34f1c976057ee9742fef962fc67ceef2fd9e291f2558b4bc4d784b2bf12f723a1741fdf76f68dd4704f795d88ac6dc2de0d60892b0391c2d4800","public_key":{"hex_bytes":"df5c7854e2264f641773f12fa3ce186ef1ebb294a7842ae7f3ef46ba502f7bffc990442f989d091ddaac352651de2d6f20fa0e65cc32d5283777177a41f51b7d","curve_type":"secp256k1"},"signing_payload":{"hex_bytes":"0206e22e9bded068a76f89a86e0849b7e6ff8f6e8a22e1b679fd87a08635a9f2","address":"0xda75C156Bc4b518ac4b91Ee942BE2B2e2e36e8C1"},"signature_type":"ecdsa_recovery"}]`
signaturesRaw := `[{"hex_bytes":"e643c47c16458bbde6503e2366257b2dee723cdc64d2de1584d3145bcaa6412e3438b4439b37dbe7894237a20d0e6b21e69c2357c09eab723200dd35fb1f01bf01","public_key":{"hex_bytes":"df5c7854e2264f641773f12fa3ce186ef1ebb294a7842ae7f3ef46ba502f7bffc990442f989d091ddaac352651de2d6f20fa0e65cc32d5283777177a41f51b7d","curve_type":"secp256k1"},"signing_payload":{"hex_bytes":"bf0f517f63d9361336b5cc7b3a17b90bc0823a8085dc438347c5cbaf8f7520f5","address":"0xda75C156Bc4b518ac4b91Ee942BE2B2e2e36e8C1"},"signature_type":"ecdsa_recovery"}]`
var signatures []*types.Signature
assert.NoError(t, json.Unmarshal([]byte(signaturesRaw), &signatures))
signedRaw := `{"type":"0x2","nonce":"0x0","gasPrice":null,"maxPriorityFeePerGas":"0x59682f00","maxFeePerGas":"0xe51af8700","gas":"0x5208","value":"0x3e8","input":"0x","v":"0x0","r":"0x660e6778daed0d34f1c976057ee9742fef962fc67ceef2fd9e291f2558b4bc4d","s":"0x784b2bf12f723a1741fdf76f68dd4704f795d88ac6dc2de0d60892b0391c2d48","to":"0x3fa177c2e87cb24148ec403921db577d140cc07c","chainId":"0x13881","accessList":[],"hash":"0x735e09de7e8b7b660b564068cb85275edcb5a432a07148100d85d05849b3013e"}` //nolint
signedRaw := `{"type":"0x2","nonce":"0x0","gasPrice":null,"maxPriorityFeePerGas":"0x6fc23ac00","maxFeePerGas":"0x14f46b0400","gas":"0x5208","value":"0x3e8","input":"0x","v":"0x1","r":"0xe643c47c16458bbde6503e2366257b2dee723cdc64d2de1584d3145bcaa6412e","s":"0x3438b4439b37dbe7894237a20d0e6b21e69c2357c09eab723200dd35fb1f01bf","to":"0x3fa177c2e87cb24148ec403921db577d140cc07c","chainId":"0x13881","accessList":[],"hash":"0x7edd5ef60a7c66eac3774cfed297517869c66dc92b2dcd1e6346045241b10775"}` //nolint
combineResponse, err := servicer.ConstructionCombine(ctx, &types.ConstructionCombineRequest{
NetworkIdentifier: networkIdentifier,
UnsignedTransaction: unsignedRaw,
Expand Down Expand Up @@ -316,7 +299,7 @@ func TestConstructionFlowWithPendingNonce(t *testing.T) {

// Test Hash
transactionIdentifier := &types.TransactionIdentifier{
Hash: "0x735e09de7e8b7b660b564068cb85275edcb5a432a07148100d85d05849b3013e",
Hash: "0x7edd5ef60a7c66eac3774cfed297517869c66dc92b2dcd1e6346045241b10775",
}
hashResponse, err := servicer.ConstructionHash(ctx, &types.ConstructionHashRequest{
NetworkIdentifier: networkIdentifier,
Expand Down Expand Up @@ -427,7 +410,7 @@ func TestConstructionFlowWithInputNonce(t *testing.T) {
"SuggestGasTipCap",
ctx,
).Return(
big.NewInt(1500000000),
big.NewInt(int64(transferGasTipEstimate)),
nil,
).Once()
metadataResponse, err := servicer.ConstructionMetadata(ctx, &types.ConstructionMetadataRequest{
Expand All @@ -439,21 +422,21 @@ func TestConstructionFlowWithInputNonce(t *testing.T) {
Metadata: forceMarshalMap(t, metadata),
SuggestedFee: []*types.Amount{
{
Value: "1291500000000000",
Value: "1890000000000000",
Currency: polygon.Currency,
},
},
}, metadataResponse)

// Test Payloads
unsignedRaw := `{"from":"0xda75C156Bc4b518ac4b91Ee942BE2B2e2e36e8C1","to":"0x3Fa177c2E87Cb24148EC403921dB577d140CC07c","value":"0x3e8","data":"0x","nonce":"0x1","max_fee_per_gas":"0xe51af8700","max_priority_fee_per_gas":"0x59682f00","gas":"0x5208","chain_id":"0x13881"}`
unsignedRaw := `{"from":"0xda75C156Bc4b518ac4b91Ee942BE2B2e2e36e8C1","to":"0x3Fa177c2E87Cb24148EC403921dB577d140CC07c","value":"0x3e8","data":"0x","nonce":"0x1","max_fee_per_gas":"0x14f46b0400","max_priority_fee_per_gas":"0x6fc23ac00","gas":"0x5208","chain_id":"0x13881"}`
payloadsResponse, err := servicer.ConstructionPayloads(ctx, &types.ConstructionPayloadsRequest{
NetworkIdentifier: networkIdentifier,
Operations: ops,
Metadata: forceMarshalMap(t, metadata),
})
assert.Nil(t, err)
payloadsRaw := `[{"address":"0xda75C156Bc4b518ac4b91Ee942BE2B2e2e36e8C1","hex_bytes":"886c43dac9ea8064a47b2c544617c20c8d2a0e67025d59b6970887ac6cb2f81b","account_identifier":{"address":"0xda75C156Bc4b518ac4b91Ee942BE2B2e2e36e8C1"},"signature_type":"ecdsa_recovery"}]`
payloadsRaw := `[{"address":"0xda75C156Bc4b518ac4b91Ee942BE2B2e2e36e8C1","hex_bytes":"6d7310e879e0db88071aef86a9ae4ccc8459a07fb9b6b9c468dc499453fa4994","account_identifier":{"address":"0xda75C156Bc4b518ac4b91Ee942BE2B2e2e36e8C1"},"signature_type":"ecdsa_recovery"}]`
var payloads []*types.SigningPayload
assert.NoError(t, json.Unmarshal([]byte(payloadsRaw), &payloads))
assert.Equal(t, &types.ConstructionPayloadsResponse{
Expand Down Expand Up @@ -485,10 +468,10 @@ func TestConstructionFlowWithInputNonce(t *testing.T) {
}, parseUnsignedResponse)

// Test Combine
signaturesRaw := `[{"hex_bytes":"e8d0fd97f5f1ce5aaa0c4c2c02d0bb1c65a1a4baa2a970efdc85e77d54f117590d953748115c85ade80806a0e4c8a9365c37b984b0837ffddda4af3397e8090000","public_key":{"hex_bytes":"0405e82ac561143aafc13ba109677a597c8f797b07417d0addd7a346ad35882b3c4a006620e02127b9a32e90979ff93ecad0a2f577db238163a50023e393e354ff","curve_type":"secp256k1"},"signing_payload":{"hex_bytes":"2fbbd3c6a16a992785dbb6d6f3589d26dbc277aa83657b130b960c0da2422670","address":"0xda75C156Bc4b518ac4b91Ee942BE2B2e2e36e8C1"},"signature_type":"ecdsa_recovery"}]`
signaturesRaw := `[{"hex_bytes":"46f411fd39f8cc5be99b67e398c2e35924c8ab185bb04df855e705479907fb7608be2b9afab67499edffeec81a0d35c3abfcb92430da50e2f448b4b95befc20001","public_key":{"hex_bytes":"0405e82ac561143aafc13ba109677a597c8f797b07417d0addd7a346ad35882b3c4a006620e02127b9a32e90979ff93ecad0a2f577db238163a50023e393e354ff","curve_type":"secp256k1"},"signing_payload":{"hex_bytes":"6d7310e879e0db88071aef86a9ae4ccc8459a07fb9b6b9c468dc499453fa4994","address":"0xda75C156Bc4b518ac4b91Ee942BE2B2e2e36e8C1"},"signature_type":"ecdsa_recovery"}]`
var signatures []*types.Signature
assert.NoError(t, json.Unmarshal([]byte(signaturesRaw), &signatures))
signedRaw := `{"type":"0x2","nonce":"0x1","gasPrice":null,"maxPriorityFeePerGas":"0x59682f00","maxFeePerGas":"0xe51af8700","gas":"0x5208","value":"0x3e8","input":"0x","v":"0x0","r":"0xe8d0fd97f5f1ce5aaa0c4c2c02d0bb1c65a1a4baa2a970efdc85e77d54f11759","s":"0xd953748115c85ade80806a0e4c8a9365c37b984b0837ffddda4af3397e80900","to":"0x3fa177c2e87cb24148ec403921db577d140cc07c","chainId":"0x13881","accessList":[],"hash":"0x9c2c6b5e84514c1668ce5c4ae5fe169bb3662812c4042d1be5af00fb0a7168e5"}` // nolint
signedRaw := `{"type":"0x2","nonce":"0x1","gasPrice":null,"maxPriorityFeePerGas":"0x6fc23ac00","maxFeePerGas":"0x14f46b0400","gas":"0x5208","value":"0x3e8","input":"0x","v":"0x1","r":"0x46f411fd39f8cc5be99b67e398c2e35924c8ab185bb04df855e705479907fb76","s":"0x8be2b9afab67499edffeec81a0d35c3abfcb92430da50e2f448b4b95befc200","to":"0x3fa177c2e87cb24148ec403921db577d140cc07c","chainId":"0x13881","accessList":[],"hash":"0xbedd18dd52d029d63cbb87630c6ebaa689fc83cb996f7035c5630dd796ac9f77"}` // nolint
combineResponse, err := servicer.ConstructionCombine(ctx, &types.ConstructionCombineRequest{
NetworkIdentifier: networkIdentifier,
UnsignedTransaction: unsignedRaw,
Expand Down Expand Up @@ -518,7 +501,7 @@ func TestConstructionFlowWithInputNonce(t *testing.T) {

// Test Hash
transactionIdentifier := &types.TransactionIdentifier{
Hash: "0x9c2c6b5e84514c1668ce5c4ae5fe169bb3662812c4042d1be5af00fb0a7168e5",
Hash: "0xbedd18dd52d029d63cbb87630c6ebaa689fc83cb996f7035c5630dd796ac9f77",
}
hashResponse, err := servicer.ConstructionHash(ctx, &types.ConstructionHashRequest{
NetworkIdentifier: networkIdentifier,
Expand Down Expand Up @@ -559,12 +542,3 @@ func templateError(error *types.Error, context string) *types.Error {
},
}
}

func templateOperations(amount uint64, currency *types.Currency) []*types.Operation {
return rosettaOperations(
fromAddress,
toAddress,
big.NewInt(int64(amount)),
currency,
)
}
19 changes: 10 additions & 9 deletions services/construction/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,23 +117,24 @@ func (a *APIService) ConstructionMetadata(
return nil, svcErrors.WrapErr(svcErrors.ErrGeth, err)
}

// Ensure the gas tip is at least 30 gwei. This is the minimum gas price recommended by the Polygon team.
// See https://forum.polygon.technology/t/recommended-min-gas-price-setting/7604 for additional context.
// This minimum must be applied to the tip, not the cap to effectivley mitigate spam (since the tip goes to miners)
minTip := big.NewInt(30000000000) // 30 gwei
if minTip.Cmp(gasTip) == 1 {
gasTip = minTip
}

var gasCap *big.Int
if input.GasCap == nil {
// Set default max fee to double the last base fee plus priority tip
// Set default max fee to double the last base fee plus multiplied priority tip
// 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,
Expand All @@ -152,7 +153,7 @@ func (a *APIService) ConstructionMetadata(
}

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

return &types.ConstructionMetadataResponse{
Expand Down
10 changes: 5 additions & 5 deletions services/construction/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func TestMetadata(t *testing.T) {
},
},
},
"happy path: native currency with gas tip set to 30 gwei floor": {
"happy path: native currency with low estimated gas tip overriden to 30 gwei": {
options: map[string]interface{}{
"from": metadataFrom,
"to": metadataTo,
Expand All @@ -147,12 +147,12 @@ func TestMetadata(t *testing.T) {
"value": transferValueHex,
"nonce": transferNonceHex2,
"gas_limit": transferGasLimitHex,
"gas_cap": minGasCapHex,
"gas_cap": transferGasCapWithTipHex,
"gas_tip": transferGasTipHex,
},
SuggestedFee: []*types.Amount{
{
Value: fmt.Sprintf("%d", (minGasCap.Uint64())*transferGasLimit),
Value: fmt.Sprintf("%d", transferGasCapWithTip*transferGasLimit),
Currency: polygon.Currency,
},
},
Expand All @@ -161,10 +161,10 @@ func TestMetadata(t *testing.T) {
var blockNum *big.Int = nil

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

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

},
},
Expand Down
21 changes: 16 additions & 5 deletions services/construction/payloads_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ import (
)

var (
invalidTransferData = "0xaaaaaaaa000000000000000000000000efd3dc58d60af3295b92ecd484caeb3a2f30b3e70000000000000000000000000000000000000000000000000000000000000001" // nolint

invalidTransferData = "0xaaaaaaaa000000000000000000000000efd3dc58d60af3295b92ecd484caeb3a2f30b3e70000000000000000000000000000000000000000000000000000000000000001" // nolint
fromAddress = "0x966fbC4E1F3a938Cf7798695C3244d9C7C190015"
toAddress = "0xefD3dc58D60aF3295B92ecd484CAEB3A2f30b3e7"
tokenContractAddress = "0x2d7882beDcbfDDce29Ba99965dd3cdF7fcB10A1e"
)

func TestPayloads(t *testing.T) {
Expand All @@ -49,7 +51,7 @@ func TestPayloads(t *testing.T) {
),
expectedResponse: templateConstructionPayloadsResponse(
templateNativeCurrencyUnsigned(),
"0x3caf34daaaf7bfd3a8fb58a7a351b354df0945bba7723f70d1bbff5bcf4b83a5",
"0x9e938823ecaa9195688dab7791d982c215625650bfcb91ef7d36c606dbfd7577",
),
},
"happy path: ERC20 currency": {
Expand All @@ -65,7 +67,7 @@ func TestPayloads(t *testing.T) {
),
expectedResponse: templateConstructionPayloadsResponse(
templateERC20CurrencyUnsigned(),
"0xc3ded208fa7991852eab06cae487e5fa193bffe8358fe3a5b6a3a3cce8c7e74b",
"0x0cdff6dd3c864bbf152c52b538f2e75fccc09dc2ae919d0c346ad22c19288e02",
),
},
"happy path: Generic contract call": {
Expand All @@ -81,7 +83,7 @@ func TestPayloads(t *testing.T) {
),
expectedResponse: templateConstructionPayloadsResponse(
templateGenericContractCallUnsigned(),
"0xaf70e3931747fca4b94ef94445ffd8e20af420c83eeec7a6fe5156e7733fb242",
"0x19edd34647a14135f3ac175b8c4a4f1bb540b554a3d2b47a96bb8a3c131ede95",
),
},
"error: bad request: native currency mismatch destination address": {
Expand Down Expand Up @@ -271,3 +273,12 @@ func templateGenericContractCallUnsigned() string {
chainIDHex,
)
}

func templateOperations(amount uint64, currency *types.Currency) []*types.Operation {
return rosettaOperations(
fromAddress,
toAddress,
big.NewInt(int64(amount)),
currency,
)
}

0 comments on commit 3e9c8aa

Please sign in to comment.