From dfa58b7369ea0394768610aceeb4d993eb4fa68b Mon Sep 17 00:00:00 2001 From: istae <14264581+istae@users.noreply.github.com> Date: Sat, 5 Nov 2022 23:02:08 +0300 Subject: [PATCH 1/9] feat: eip 1559 --- pkg/transaction/transaction.go | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/pkg/transaction/transaction.go b/pkg/transaction/transaction.go index 7e65f36eefe..0a187dc4011 100644 --- a/pkg/transaction/transaction.go +++ b/pkg/transaction/transaction.go @@ -43,6 +43,8 @@ var ( // minGasPrice determines the minimum gas price // threshold (in wei) for the creation of a transaction. +const defaultBoostPercent = 10 + var minGasPrice = big.NewInt(1000) // TxRequest describes a request for a transaction that can be executed. @@ -272,25 +274,28 @@ func (t *transactionService) prepareTransaction(ctx context.Context, request *Tx gasLimit = request.GasLimit } - gasPrice := request.GasPrice - if gasPrice == nil { - gasPriceSuggested, err := t.backend.SuggestGasPrice(ctx) - gasPrice = new(big.Int).Div(new(big.Int).Mul(big.NewInt(int64(boostPercent)+100), gasPriceSuggested), big.NewInt(100)) - if err != nil { - return nil, err - } + // gasPrice := request.GasPrice + gasPriceSuggested, err := t.backend.SuggestGasPrice(ctx) + if err != nil { + return nil, err + } + if boostPercent == 0 { + boostPercent = defaultBoostPercent } + gasPrice := new(big.Int).Div(new(big.Int).Mul(big.NewInt(int64(boostPercent)+100), gasPriceSuggested), big.NewInt(100)) if gasPrice.Cmp(minGasPrice) < 0 { return nil, ErrGasPriceTooLow } - return types.NewTx(&types.LegacyTx{ - Nonce: nonce, - To: request.To, - Value: request.Value, - Gas: gasLimit, - GasPrice: gasPrice, - Data: request.Data, + return types.NewTx(&types.DynamicFeeTx{ + Nonce: nonce, + ChainID: t.chainID, + To: request.To, + Value: request.Value, + Gas: gasLimit, + GasTipCap: gasPrice, + GasFeeCap: gasPrice, + Data: request.Data, }), nil } From 5a374013fe0a3eaec5bb6f23928f8c498a6b0192 Mon Sep 17 00:00:00 2001 From: istae <14264581+istae@users.noreply.github.com> Date: Mon, 7 Nov 2022 15:55:39 +0300 Subject: [PATCH 2/9] feat: dynamic trx --- pkg/postage/postagecontract/contract.go | 4 +- pkg/settlement/swap/chequebook/cashout.go | 2 +- pkg/settlement/swap/chequebook/chequebook.go | 2 +- pkg/settlement/swap/chequebook/factory.go | 2 +- pkg/settlement/swap/erc20/erc20.go | 2 +- pkg/storageincentives/staking/contract.go | 2 +- pkg/transaction/transaction.go | 51 +++++++++++--------- pkg/transaction/transaction_test.go | 2 +- 8 files changed, 35 insertions(+), 32 deletions(-) diff --git a/pkg/postage/postagecontract/contract.go b/pkg/postage/postagecontract/contract.go index c1547ac3385..36e110b0504 100644 --- a/pkg/postage/postagecontract/contract.go +++ b/pkg/postage/postagecontract/contract.go @@ -96,7 +96,7 @@ func (c *postageContract) sendApproveTransaction(ctx context.Context, amount *bi GasLimit: 65000, Value: big.NewInt(0), Description: approveDescription, - }, 0) + }, transaction.DefaultTipPercent) if err != nil { return nil, err } @@ -123,7 +123,7 @@ func (c *postageContract) sendTransaction(ctx context.Context, callData []byte, Description: desc, } - txHash, err := c.transactionService.Send(ctx, request, 0) + txHash, err := c.transactionService.Send(ctx, request, transaction.DefaultTipPercent) if err != nil { return nil, err } diff --git a/pkg/settlement/swap/chequebook/cashout.go b/pkg/settlement/swap/chequebook/cashout.go index a7d00d87f40..46742e5c810 100644 --- a/pkg/settlement/swap/chequebook/cashout.go +++ b/pkg/settlement/swap/chequebook/cashout.go @@ -149,7 +149,7 @@ func (s *cashoutService) CashCheque(ctx context.Context, chequebook, recipient c Description: "cheque cashout", } - txHash, err := s.transactionService.Send(ctx, request, 0) + txHash, err := s.transactionService.Send(ctx, request, transaction.DefaultTipPercent) if err != nil { return common.Hash{}, err } diff --git a/pkg/settlement/swap/chequebook/chequebook.go b/pkg/settlement/swap/chequebook/chequebook.go index 845f9aac201..1c5aee7c8be 100644 --- a/pkg/settlement/swap/chequebook/chequebook.go +++ b/pkg/settlement/swap/chequebook/chequebook.go @@ -334,7 +334,7 @@ func (s *service) Withdraw(ctx context.Context, amount *big.Int) (hash common.Ha Description: fmt.Sprintf("chequebook withdrawal of %d BZZ", amount), } - txHash, err := s.transactionService.Send(ctx, request, 0) + txHash, err := s.transactionService.Send(ctx, request, transaction.DefaultTipPercent) if err != nil { return common.Hash{}, err } diff --git a/pkg/settlement/swap/chequebook/factory.go b/pkg/settlement/swap/chequebook/factory.go index ad890b95491..823fdec4e10 100644 --- a/pkg/settlement/swap/chequebook/factory.go +++ b/pkg/settlement/swap/chequebook/factory.go @@ -87,7 +87,7 @@ func (c *factory) Deploy(ctx context.Context, issuer common.Address, defaultHard Description: "chequebook deployment", } - txHash, err := c.transactionService.Send(ctx, request, 0) + txHash, err := c.transactionService.Send(ctx, request, transaction.DefaultTipPercent) if err != nil { return common.Hash{}, err } diff --git a/pkg/settlement/swap/erc20/erc20.go b/pkg/settlement/swap/erc20/erc20.go index 4866350a81c..b1b20149240 100644 --- a/pkg/settlement/swap/erc20/erc20.go +++ b/pkg/settlement/swap/erc20/erc20.go @@ -83,7 +83,7 @@ func (c *erc20Service) Transfer(ctx context.Context, address common.Address, val Description: "token transfer", } - txHash, err := c.transactionService.Send(ctx, request, 0) + txHash, err := c.transactionService.Send(ctx, request, transaction.DefaultTipPercent) if err != nil { return common.Hash{}, err } diff --git a/pkg/storageincentives/staking/contract.go b/pkg/storageincentives/staking/contract.go index d0df5c44932..394e9a914f2 100644 --- a/pkg/storageincentives/staking/contract.go +++ b/pkg/storageincentives/staking/contract.go @@ -106,7 +106,7 @@ func (s *contract) sendTransaction(ctx context.Context, callData []byte, desc st Description: desc, } - txHash, err := s.transactionService.Send(ctx, request, 0) + txHash, err := s.transactionService.Send(ctx, request, transaction.DefaultTipPercent) if err != nil { return nil, err } diff --git a/pkg/transaction/transaction.go b/pkg/transaction/transaction.go index 0a187dc4011..b4fc2aa9205 100644 --- a/pkg/transaction/transaction.go +++ b/pkg/transaction/transaction.go @@ -43,7 +43,7 @@ var ( // minGasPrice determines the minimum gas price // threshold (in wei) for the creation of a transaction. -const defaultBoostPercent = 10 +const DefaultTipPercent = 10 var minGasPrice = big.NewInt(1000) @@ -256,7 +256,7 @@ func (t *transactionService) StoredTransaction(txHash common.Hash) (*StoredTrans } // prepareTransaction creates a signable transaction based on a request. -func (t *transactionService) prepareTransaction(ctx context.Context, request *TxRequest, nonce uint64, boostPercent int) (tx *types.Transaction, err error) { +func (t *transactionService) prepareTransaction(ctx context.Context, request *TxRequest, nonce uint64, tipPercent int) (tx *types.Transaction, err error) { var gasLimit uint64 if request.GasLimit == 0 { gasLimit, err = t.backend.EstimateGas(ctx, ethereum.CallMsg{ @@ -274,15 +274,14 @@ func (t *transactionService) prepareTransaction(ctx context.Context, request *Tx gasLimit = request.GasLimit } - // gasPrice := request.GasPrice - gasPriceSuggested, err := t.backend.SuggestGasPrice(ctx) - if err != nil { - return nil, err - } - if boostPercent == 0 { - boostPercent = defaultBoostPercent + gasPrice := request.GasPrice + if gasPrice == nil { + gasPrice, err = t.backend.SuggestGasPrice(ctx) + if err != nil { + return nil, err + } } - gasPrice := new(big.Int).Div(new(big.Int).Mul(big.NewInt(int64(boostPercent)+100), gasPriceSuggested), big.NewInt(100)) + gasPrice = new(big.Int).Div(new(big.Int).Mul(big.NewInt(int64(tipPercent)+100), gasPrice), big.NewInt(100)) if gasPrice.Cmp(minGasPrice) < 0 { return nil, ErrGasPriceTooLow } @@ -390,13 +389,15 @@ func (t *transactionService) ResendTransaction(ctx context.Context, txHash commo return err } - tx := types.NewTx(&types.LegacyTx{ - Nonce: storedTransaction.Nonce, - To: storedTransaction.To, - Value: storedTransaction.Value, - Gas: storedTransaction.GasLimit, - GasPrice: storedTransaction.GasPrice, - Data: storedTransaction.Data, + tx := types.NewTx(&types.DynamicFeeTx{ + Nonce: storedTransaction.Nonce, + ChainID: t.chainID, + To: storedTransaction.To, + Value: storedTransaction.Value, + Gas: storedTransaction.GasLimit, + GasTipCap: storedTransaction.GasPrice, + GasFeeCap: storedTransaction.GasPrice, + Data: storedTransaction.Data, }) signedTx, err := t.signer.SignTx(tx, t.chainID) @@ -430,13 +431,15 @@ func (t *transactionService) CancelTransaction(ctx context.Context, originalTxHa return common.Hash{}, ErrGasPriceTooLow } - signedTx, err := t.signer.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: storedTransaction.Nonce, - To: &t.sender, - Value: big.NewInt(0), - Gas: 21000, - GasPrice: gasPrice, - Data: []byte{}, + signedTx, err := t.signer.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: storedTransaction.Nonce, + ChainID: t.chainID, + To: &t.sender, + Value: big.NewInt(0), + Gas: 21000, + GasTipCap: gasPrice, + GasFeeCap: gasPrice, + Data: []byte{}, }), t.chainID) if err != nil { return common.Hash{}, err diff --git a/pkg/transaction/transaction_test.go b/pkg/transaction/transaction_test.go index 12920b02aeb..64adf8e4425 100644 --- a/pkg/transaction/transaction_test.go +++ b/pkg/transaction/transaction_test.go @@ -34,7 +34,7 @@ func signerMockForTransaction(t *testing.T, signedTx *types.Transaction, sender return signermock.New( signermock.WithSignTxFunc(func(transaction *types.Transaction, chainID *big.Int) (*types.Transaction, error) { - if transaction.Type() != 0 { + if transaction.Type() != 2 { t.Fatalf("wrong transaction type. wanted 0, got %d", transaction.Type()) } if signedTx.To() == nil { From 911158e1341128f40bd506c7c874a260ea549001 Mon Sep 17 00:00:00 2001 From: istae <14264581+istae@users.noreply.github.com> Date: Mon, 7 Nov 2022 16:03:17 +0300 Subject: [PATCH 3/9] fix: tests --- pkg/transaction/transaction_test.go | 148 ++++++++++++++++------------ 1 file changed, 85 insertions(+), 63 deletions(-) diff --git a/pkg/transaction/transaction_test.go b/pkg/transaction/transaction_test.go index 64adf8e4425..1ec5dfb30b1 100644 --- a/pkg/transaction/transaction_test.go +++ b/pkg/transaction/transaction_test.go @@ -90,13 +90,15 @@ func TestTransactionSend(t *testing.T) { t.Run("send", func(t *testing.T) { t.Parallel() - signedTx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - To: &recipient, - Value: value, - Gas: estimatedGasLimit, - GasPrice: suggestedGasPrice, - Data: txData, + signedTx := types.NewTx(&types.DynamicFeeTx{ + ChainID: chainID, + Nonce: nonce, + To: &recipient, + Value: value, + Gas: estimatedGasLimit, + GasTipCap: suggestedGasPrice, + GasFeeCap: suggestedGasPrice, + Data: txData, }) request := &transaction.TxRequest{ To: &recipient, @@ -211,13 +213,17 @@ func TestTransactionSend(t *testing.T) { t.Run("sendWithBoost", func(t *testing.T) { t.Parallel() - signedTx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - To: &recipient, - Value: value, - Gas: estimatedGasLimit, - GasPrice: big.NewInt(0).Div(new(big.Int).Mul(suggestedGasPrice, big.NewInt(15)), big.NewInt(10)), - Data: txData, + price := big.NewInt(0).Div(new(big.Int).Mul(suggestedGasPrice, big.NewInt(15)), big.NewInt(10)) + + signedTx := types.NewTx(&types.DynamicFeeTx{ + ChainID: chainID, + Nonce: nonce, + To: &recipient, + Value: value, + Gas: estimatedGasLimit, + GasTipCap: price, + GasFeeCap: price, + Data: txData, }) request := &transaction.TxRequest{ To: &recipient, @@ -331,13 +337,15 @@ func TestTransactionSend(t *testing.T) { t.Run("send_no_nonce", func(t *testing.T) { t.Parallel() - signedTx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - To: &recipient, - Value: value, - Gas: estimatedGasLimit, - GasPrice: suggestedGasPrice, - Data: txData, + signedTx := types.NewTx(&types.DynamicFeeTx{ + ChainID: chainID, + Nonce: nonce, + To: &recipient, + Value: value, + Gas: estimatedGasLimit, + GasTipCap: suggestedGasPrice, + GasFeeCap: suggestedGasPrice, + Data: txData, }) request := &transaction.TxRequest{ To: &recipient, @@ -403,13 +411,15 @@ func TestTransactionSend(t *testing.T) { t.Parallel() nextNonce := nonce + 5 - signedTx := types.NewTx(&types.LegacyTx{ - Nonce: nextNonce, - To: &recipient, - Value: value, - Gas: estimatedGasLimit, - GasPrice: suggestedGasPrice, - Data: txData, + signedTx := types.NewTx(&types.DynamicFeeTx{ + ChainID: chainID, + Nonce: nextNonce, + To: &recipient, + Value: value, + Gas: estimatedGasLimit, + GasTipCap: suggestedGasPrice, + GasFeeCap: suggestedGasPrice, + Data: txData, }) request := &transaction.TxRequest{ To: &recipient, @@ -550,13 +560,15 @@ func TestTransactionResend(t *testing.T) { store := storemock.NewStateStore() defer store.Close() - signedTx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - To: &recipient, - Value: value, - Gas: gasLimit, - GasPrice: gasPrice, - Data: data, + signedTx := types.NewTx(&types.DynamicFeeTx{ + ChainID: chainID, + Nonce: nonce, + To: &recipient, + Value: value, + Gas: gasLimit, + GasTipCap: gasPrice, + GasFeeCap: gasPrice, + Data: data, }) err := store.Put(transaction.StoredTransactionKey(signedTx.Hash()), transaction.StoredTransaction{ @@ -611,13 +623,15 @@ func TestTransactionCancel(t *testing.T) { store := storemock.NewStateStore() t.Cleanup(func() { store.Close() }) - signedTx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - To: &recipient, - Value: value, - Gas: gasLimit, - GasPrice: gasPrice, - Data: data, + signedTx := types.NewTx(&types.DynamicFeeTx{ + ChainID: chainID, + Nonce: nonce, + To: &recipient, + Value: value, + Gas: gasLimit, + GasTipCap: gasPrice, + GasFeeCap: gasPrice, + Data: data, }) err := store.Put(transaction.StoredTransactionKey(signedTx.Hash()), transaction.StoredTransaction{ Nonce: nonce, @@ -634,13 +648,17 @@ func TestTransactionCancel(t *testing.T) { t.Run("ok", func(t *testing.T) { t.Parallel() - cancelTx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - To: &recipient, - Value: big.NewInt(0), - Gas: 21000, - GasPrice: new(big.Int).Add(gasPrice, big.NewInt(1)), - Data: []byte{}, + price := new(big.Int).Add(gasPrice, big.NewInt(1)) + + cancelTx := types.NewTx(&types.DynamicFeeTx{ + ChainID: chainID, + Nonce: nonce, + To: &recipient, + Value: big.NewInt(0), + Gas: 21000, + GasTipCap: price, + GasFeeCap: price, + Data: []byte{}, }) transactionService, err := transaction.NewService(logger, @@ -676,13 +694,15 @@ func TestTransactionCancel(t *testing.T) { t.Parallel() customGasPrice := big.NewInt(5) - cancelTx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - To: &recipient, - Value: big.NewInt(0), - Gas: 21000, - GasPrice: customGasPrice, - Data: []byte{}, + cancelTx := types.NewTx(&types.DynamicFeeTx{ + ChainID: chainID, + Nonce: nonce, + To: &recipient, + Value: big.NewInt(0), + Gas: 21000, + GasTipCap: customGasPrice, + GasFeeCap: customGasPrice, + Data: []byte{}, }) transactionService, err := transaction.NewService(logger, @@ -719,13 +739,15 @@ func TestTransactionCancel(t *testing.T) { t.Parallel() customGasPrice := big.NewInt(0) - cancelTx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - To: &recipient, - Value: big.NewInt(0), - Gas: 21000, - GasPrice: customGasPrice, - Data: []byte{}, + cancelTx := types.NewTx(&types.DynamicFeeTx{ + ChainID: chainID, + Nonce: nonce, + To: &recipient, + Value: big.NewInt(0), + Gas: 21000, + GasTipCap: customGasPrice, + GasFeeCap: customGasPrice, + Data: []byte{}, }) transactionService, err := transaction.NewService(logger, From 7d4d83882943251f3eca6862ea8018fbe4766c37 Mon Sep 17 00:00:00 2001 From: istae <14264581+istae@users.noreply.github.com> Date: Mon, 7 Nov 2022 16:11:23 +0300 Subject: [PATCH 4/9] chore: comments --- pkg/transaction/transaction.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/pkg/transaction/transaction.go b/pkg/transaction/transaction.go index b4fc2aa9205..b94f32b3002 100644 --- a/pkg/transaction/transaction.go +++ b/pkg/transaction/transaction.go @@ -274,6 +274,17 @@ func (t *transactionService) prepareTransaction(ctx context.Context, request *Tx gasLimit = request.GasLimit } + /* Transactions are EIP 1559 dynamic transactions where there are three fee related fields: + 1. base fee is the price that will be burned as part of the transaction. + 2. max fee is the max price we are willing to spend as gas price. + 3. max priority fee is max price want to give to the miner to prioritize the transaction. + as an example: + if base fee is 15, max fee is 20, and max priority is 3, gas price will be 15 + 3 = 18 + if base is 15, max fee is 20, and max priority fee is 10, + gas price will be 15 + 10 = 25, but since 25 > 20, gas price is 20. + notice that gas price does not exceed 20 as defined by max fee. + */ + gasPrice := request.GasPrice if gasPrice == nil { gasPrice, err = t.backend.SuggestGasPrice(ctx) @@ -292,7 +303,7 @@ func (t *transactionService) prepareTransaction(ctx context.Context, request *Tx To: request.To, Value: request.Value, Gas: gasLimit, - GasTipCap: gasPrice, + GasTipCap: gasPrice, // here we can use the same gas price as gas fee cap provides an upperbound GasFeeCap: gasPrice, Data: request.Data, }), nil From 387cef912299c749f709a7e058558d838c3b978a Mon Sep 17 00:00:00 2001 From: istae <14264581+istae@users.noreply.github.com> Date: Mon, 7 Nov 2022 16:15:01 +0300 Subject: [PATCH 5/9] fix: low price error on provided value --- pkg/transaction/transaction.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkg/transaction/transaction.go b/pkg/transaction/transaction.go index b94f32b3002..11a66226484 100644 --- a/pkg/transaction/transaction.go +++ b/pkg/transaction/transaction.go @@ -291,11 +291,10 @@ func (t *transactionService) prepareTransaction(ctx context.Context, request *Tx if err != nil { return nil, err } - } - gasPrice = new(big.Int).Div(new(big.Int).Mul(big.NewInt(int64(tipPercent)+100), gasPrice), big.NewInt(100)) - if gasPrice.Cmp(minGasPrice) < 0 { + } else if gasPrice.Cmp(minGasPrice) < 0 { return nil, ErrGasPriceTooLow } + gasPrice = new(big.Int).Div(new(big.Int).Mul(big.NewInt(int64(tipPercent)+100), gasPrice), big.NewInt(100)) return types.NewTx(&types.DynamicFeeTx{ Nonce: nonce, From 11c0bbca3db66b4db27138f8d7e5ac5d84f355a1 Mon Sep 17 00:00:00 2001 From: istae <14264581+istae@users.noreply.github.com> Date: Mon, 7 Nov 2022 17:37:17 +0300 Subject: [PATCH 6/9] fix: london signer --- pkg/crypto/signer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/crypto/signer.go b/pkg/crypto/signer.go index 4156e697503..6a82101eff0 100644 --- a/pkg/crypto/signer.go +++ b/pkg/crypto/signer.go @@ -90,7 +90,7 @@ func (d *defaultSigner) Sign(data []byte) (signature []byte, err error) { // SignTx signs an ethereum transaction. func (d *defaultSigner) SignTx(transaction *types.Transaction, chainID *big.Int) (*types.Transaction, error) { - txSigner := types.NewEIP155Signer(chainID) + txSigner := types.NewLondonSigner(chainID) hash := txSigner.Hash(transaction).Bytes() // isCompressedKey is false here so we get the expected v value (27 or 28) signature, err := d.sign(hash, false) From d860a8e37ee7b87f670c027ff35706ab7d163661 Mon Sep 17 00:00:00 2001 From: istae <14264581+istae@users.noreply.github.com> Date: Mon, 7 Nov 2022 17:48:43 +0300 Subject: [PATCH 7/9] fix: boost when gas price does not exist in request --- pkg/config/chain.go | 2 +- pkg/transaction/transaction.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/config/chain.go b/pkg/config/chain.go index 0b53875f9d7..88212594065 100644 --- a/pkg/config/chain.go +++ b/pkg/config/chain.go @@ -14,7 +14,7 @@ var ( xdaiChainID = int64(100) // start block // replace this with - goerliStartBlock = uint64(7590423) + goerliStartBlock = uint64(7865424) xdaiStartBlock = uint64(24180961) // factory address goerliContractAddress = common.HexToAddress("0x0c9de531dcb38b758fe8a2c163444a5e54ee0db2") diff --git a/pkg/transaction/transaction.go b/pkg/transaction/transaction.go index 11a66226484..c77a898317d 100644 --- a/pkg/transaction/transaction.go +++ b/pkg/transaction/transaction.go @@ -291,10 +291,10 @@ func (t *transactionService) prepareTransaction(ctx context.Context, request *Tx if err != nil { return nil, err } + gasPrice = new(big.Int).Div(new(big.Int).Mul(big.NewInt(int64(tipPercent)+100), gasPrice), big.NewInt(100)) } else if gasPrice.Cmp(minGasPrice) < 0 { return nil, ErrGasPriceTooLow } - gasPrice = new(big.Int).Div(new(big.Int).Mul(big.NewInt(int64(tipPercent)+100), gasPrice), big.NewInt(100)) return types.NewTx(&types.DynamicFeeTx{ Nonce: nonce, From 9288152265766525205799641028010179125b68 Mon Sep 17 00:00:00 2001 From: istae <14264581+istae@users.noreply.github.com> Date: Mon, 7 Nov 2022 17:49:44 +0300 Subject: [PATCH 8/9] fix: reset start block --- pkg/config/chain.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/config/chain.go b/pkg/config/chain.go index 88212594065..0b53875f9d7 100644 --- a/pkg/config/chain.go +++ b/pkg/config/chain.go @@ -14,7 +14,7 @@ var ( xdaiChainID = int64(100) // start block // replace this with - goerliStartBlock = uint64(7865424) + goerliStartBlock = uint64(7590423) xdaiStartBlock = uint64(24180961) // factory address goerliContractAddress = common.HexToAddress("0x0c9de531dcb38b758fe8a2c163444a5e54ee0db2") From 1b4d1bb3fa5656806f48f01b1f1606d19c29ac2b Mon Sep 17 00:00:00 2001 From: istae <14264581+istae@users.noreply.github.com> Date: Mon, 7 Nov 2022 18:32:22 +0300 Subject: [PATCH 9/9] feat: suggest gas tip cap --- pkg/node/chain.go | 3 ++ pkg/postage/postagecontract/contract.go | 4 +- pkg/settlement/swap/chequebook/cashout.go | 2 +- pkg/settlement/swap/chequebook/chequebook.go | 2 +- pkg/settlement/swap/chequebook/factory.go | 2 +- pkg/settlement/swap/erc20/erc20.go | 2 +- pkg/storageincentives/staking/contract.go | 2 +- pkg/transaction/backend.go | 1 + pkg/transaction/backendmock/backend.go | 10 +++++ pkg/transaction/transaction.go | 44 +++++++++++--------- pkg/transaction/transaction_test.go | 24 ++++++++--- pkg/transaction/wrapped/wrapped.go | 11 +++++ 12 files changed, 75 insertions(+), 32 deletions(-) diff --git a/pkg/node/chain.go b/pkg/node/chain.go index 368a1979310..fe45038f5c1 100644 --- a/pkg/node/chain.go +++ b/pkg/node/chain.go @@ -399,6 +399,9 @@ func (m noOpChainBackend) PendingNonceAt(context.Context, common.Address) (uint6 func (m noOpChainBackend) SuggestGasPrice(context.Context) (*big.Int, error) { panic("chain no op: SuggestGasPrice") } +func (m noOpChainBackend) SuggestGasTipCap(context.Context) (*big.Int, error) { + panic("chain no op: SuggestGasPrice") +} func (m noOpChainBackend) EstimateGas(context.Context, ethereum.CallMsg) (uint64, error) { panic("chain no op: EstimateGas") } diff --git a/pkg/postage/postagecontract/contract.go b/pkg/postage/postagecontract/contract.go index 36e110b0504..37babc52b4d 100644 --- a/pkg/postage/postagecontract/contract.go +++ b/pkg/postage/postagecontract/contract.go @@ -96,7 +96,7 @@ func (c *postageContract) sendApproveTransaction(ctx context.Context, amount *bi GasLimit: 65000, Value: big.NewInt(0), Description: approveDescription, - }, transaction.DefaultTipPercent) + }, transaction.DefaultTipBoostPercent) if err != nil { return nil, err } @@ -123,7 +123,7 @@ func (c *postageContract) sendTransaction(ctx context.Context, callData []byte, Description: desc, } - txHash, err := c.transactionService.Send(ctx, request, transaction.DefaultTipPercent) + txHash, err := c.transactionService.Send(ctx, request, transaction.DefaultTipBoostPercent) if err != nil { return nil, err } diff --git a/pkg/settlement/swap/chequebook/cashout.go b/pkg/settlement/swap/chequebook/cashout.go index 46742e5c810..157af01ad56 100644 --- a/pkg/settlement/swap/chequebook/cashout.go +++ b/pkg/settlement/swap/chequebook/cashout.go @@ -149,7 +149,7 @@ func (s *cashoutService) CashCheque(ctx context.Context, chequebook, recipient c Description: "cheque cashout", } - txHash, err := s.transactionService.Send(ctx, request, transaction.DefaultTipPercent) + txHash, err := s.transactionService.Send(ctx, request, transaction.DefaultTipBoostPercent) if err != nil { return common.Hash{}, err } diff --git a/pkg/settlement/swap/chequebook/chequebook.go b/pkg/settlement/swap/chequebook/chequebook.go index 1c5aee7c8be..347f6a7bfe7 100644 --- a/pkg/settlement/swap/chequebook/chequebook.go +++ b/pkg/settlement/swap/chequebook/chequebook.go @@ -334,7 +334,7 @@ func (s *service) Withdraw(ctx context.Context, amount *big.Int) (hash common.Ha Description: fmt.Sprintf("chequebook withdrawal of %d BZZ", amount), } - txHash, err := s.transactionService.Send(ctx, request, transaction.DefaultTipPercent) + txHash, err := s.transactionService.Send(ctx, request, transaction.DefaultTipBoostPercent) if err != nil { return common.Hash{}, err } diff --git a/pkg/settlement/swap/chequebook/factory.go b/pkg/settlement/swap/chequebook/factory.go index 823fdec4e10..6b4cc106b6f 100644 --- a/pkg/settlement/swap/chequebook/factory.go +++ b/pkg/settlement/swap/chequebook/factory.go @@ -87,7 +87,7 @@ func (c *factory) Deploy(ctx context.Context, issuer common.Address, defaultHard Description: "chequebook deployment", } - txHash, err := c.transactionService.Send(ctx, request, transaction.DefaultTipPercent) + txHash, err := c.transactionService.Send(ctx, request, transaction.DefaultTipBoostPercent) if err != nil { return common.Hash{}, err } diff --git a/pkg/settlement/swap/erc20/erc20.go b/pkg/settlement/swap/erc20/erc20.go index b1b20149240..677ac35b8fb 100644 --- a/pkg/settlement/swap/erc20/erc20.go +++ b/pkg/settlement/swap/erc20/erc20.go @@ -83,7 +83,7 @@ func (c *erc20Service) Transfer(ctx context.Context, address common.Address, val Description: "token transfer", } - txHash, err := c.transactionService.Send(ctx, request, transaction.DefaultTipPercent) + txHash, err := c.transactionService.Send(ctx, request, transaction.DefaultTipBoostPercent) if err != nil { return common.Hash{}, err } diff --git a/pkg/storageincentives/staking/contract.go b/pkg/storageincentives/staking/contract.go index 394e9a914f2..b22fc8d6f3f 100644 --- a/pkg/storageincentives/staking/contract.go +++ b/pkg/storageincentives/staking/contract.go @@ -106,7 +106,7 @@ func (s *contract) sendTransaction(ctx context.Context, callData []byte, desc st Description: desc, } - txHash, err := s.transactionService.Send(ctx, request, transaction.DefaultTipPercent) + txHash, err := s.transactionService.Send(ctx, request, transaction.DefaultTipBoostPercent) if err != nil { return nil, err } diff --git a/pkg/transaction/backend.go b/pkg/transaction/backend.go index d1e8686cb41..c574bebebce 100644 --- a/pkg/transaction/backend.go +++ b/pkg/transaction/backend.go @@ -26,6 +26,7 @@ type Backend interface { HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) SuggestGasPrice(ctx context.Context) (*big.Int, error) + SuggestGasTipCap(ctx context.Context) (*big.Int, error) EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error) SendTransaction(ctx context.Context, tx *types.Transaction) error TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) diff --git a/pkg/transaction/backendmock/backend.go b/pkg/transaction/backendmock/backend.go index aa43f7ef062..8ce38614b6e 100644 --- a/pkg/transaction/backendmock/backend.go +++ b/pkg/transaction/backendmock/backend.go @@ -19,6 +19,7 @@ type backendMock struct { codeAt func(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) sendTransaction func(ctx context.Context, tx *types.Transaction) error suggestGasPrice func(ctx context.Context) (*big.Int, error) + suggestGasTipCap func(ctx context.Context) (*big.Int, error) estimateGas func(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error) transactionReceipt func(ctx context.Context, txHash common.Hash) (*types.Receipt, error) pendingNonceAt func(ctx context.Context, account common.Address) (uint64, error) @@ -130,6 +131,9 @@ func (m *backendMock) NonceAt(ctx context.Context, account common.Address, block } func (m *backendMock) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { + if m.suggestGasPrice != nil { + return m.suggestGasTipCap(ctx) + } return nil, errors.New("not implemented") } @@ -181,6 +185,12 @@ func WithSuggestGasPriceFunc(f func(ctx context.Context) (*big.Int, error)) Opti }) } +func WithSuggestGasTipCapFunc(f func(ctx context.Context) (*big.Int, error)) Option { + return optionFunc(func(s *backendMock) { + s.suggestGasTipCap = f + }) +} + func WithEstimateGasFunc(f func(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error)) Option { return optionFunc(func(s *backendMock) { s.estimateGas = f diff --git a/pkg/transaction/transaction.go b/pkg/transaction/transaction.go index c77a898317d..fb3fa106596 100644 --- a/pkg/transaction/transaction.go +++ b/pkg/transaction/transaction.go @@ -43,9 +43,7 @@ var ( // minGasPrice determines the minimum gas price // threshold (in wei) for the creation of a transaction. -const DefaultTipPercent = 10 - -var minGasPrice = big.NewInt(1000) +const DefaultTipBoostPercent = 20 // TxRequest describes a request for a transaction that can be executed. type TxRequest struct { @@ -73,7 +71,7 @@ type StoredTransaction struct { type Service interface { io.Closer // Send creates a transaction based on the request (with gasprice increased by provided percentage) and sends it. - Send(ctx context.Context, request *TxRequest, priceBoostPercent int) (txHash common.Hash, err error) + Send(ctx context.Context, request *TxRequest, tipCapBoostPercent int) (txHash common.Hash, err error) // Call simulate a transaction based on the request. Call(ctx context.Context, request *TxRequest) (result []byte, err error) // WaitForReceipt waits until either the transaction with the given hash has been mined or the context is cancelled. @@ -142,7 +140,7 @@ func NewService(logger log.Logger, backend Backend, signer crypto.Signer, store } // Send creates and signs a transaction based on the request and sends it. -func (t *transactionService) Send(ctx context.Context, request *TxRequest, priceBoostPercent int) (txHash common.Hash, err error) { +func (t *transactionService) Send(ctx context.Context, request *TxRequest, tipCapBoostPercent int) (txHash common.Hash, err error) { loggerV1 := t.logger.V(1).Register() t.lock.Lock() @@ -153,7 +151,7 @@ func (t *transactionService) Send(ctx context.Context, request *TxRequest, price return common.Hash{}, err } - tx, err := t.prepareTransaction(ctx, request, nonce, priceBoostPercent) + tx, err := t.prepareTransaction(ctx, request, nonce, tipCapBoostPercent) if err != nil { return common.Hash{}, err } @@ -274,15 +272,16 @@ func (t *transactionService) prepareTransaction(ctx context.Context, request *Tx gasLimit = request.GasLimit } - /* Transactions are EIP 1559 dynamic transactions where there are three fee related fields: - 1. base fee is the price that will be burned as part of the transaction. - 2. max fee is the max price we are willing to spend as gas price. - 3. max priority fee is max price want to give to the miner to prioritize the transaction. - as an example: - if base fee is 15, max fee is 20, and max priority is 3, gas price will be 15 + 3 = 18 - if base is 15, max fee is 20, and max priority fee is 10, - gas price will be 15 + 10 = 25, but since 25 > 20, gas price is 20. - notice that gas price does not exceed 20 as defined by max fee. + /* + Transactions are EIP 1559 dynamic transactions where there are three fee related fields: + 1. base fee is the price that will be burned as part of the transaction. + 2. max fee is the max price we are willing to spend as gas price. + 3. max priority fee is max price want to give to the miner to prioritize the transaction. + as an example: + if base fee is 15, max fee is 20, and max priority is 3, gas price will be 15 + 3 = 18 + if base is 15, max fee is 20, and max priority fee is 10, + gas price will be 15 + 10 = 25, but since 25 > 20, gas price is 20. + notice that gas price does not exceed 20 as defined by max fee. */ gasPrice := request.GasPrice @@ -291,19 +290,24 @@ func (t *transactionService) prepareTransaction(ctx context.Context, request *Tx if err != nil { return nil, err } - gasPrice = new(big.Int).Div(new(big.Int).Mul(big.NewInt(int64(tipPercent)+100), gasPrice), big.NewInt(100)) - } else if gasPrice.Cmp(minGasPrice) < 0 { - return nil, ErrGasPriceTooLow } + gasTipCap, err := t.backend.SuggestGasTipCap(ctx) + if err != nil { + return nil, err + } + + gasTipCap = new(big.Int).Div(new(big.Int).Mul(big.NewInt(int64(tipPercent)+100), gasTipCap), big.NewInt(100)) + gasFeeCap := new(big.Int).Add(gasTipCap, gasPrice) + return types.NewTx(&types.DynamicFeeTx{ Nonce: nonce, ChainID: t.chainID, To: request.To, Value: request.Value, Gas: gasLimit, - GasTipCap: gasPrice, // here we can use the same gas price as gas fee cap provides an upperbound - GasFeeCap: gasPrice, + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, Data: request.Data, }), nil } diff --git a/pkg/transaction/transaction_test.go b/pkg/transaction/transaction_test.go index 1ec5dfb30b1..557c5e59d4a 100644 --- a/pkg/transaction/transaction_test.go +++ b/pkg/transaction/transaction_test.go @@ -31,7 +31,6 @@ func nonceKey(sender common.Address) string { func signerMockForTransaction(t *testing.T, signedTx *types.Transaction, sender common.Address, signerChainID *big.Int) crypto.Signer { t.Helper() - return signermock.New( signermock.WithSignTxFunc(func(transaction *types.Transaction, chainID *big.Int) (*types.Transaction, error) { if transaction.Type() != 2 { @@ -135,6 +134,9 @@ func TestTransactionSend(t *testing.T) { backendmock.WithPendingNonceAtFunc(func(ctx context.Context, account common.Address) (uint64, error) { return nonce - 1, nil }), + backendmock.WithSuggestGasTipCapFunc(func(ctx context.Context) (*big.Int, error) { + return big.NewInt(0), nil + }), ), signerMockForTransaction(t, signedTx, sender, chainID), store, @@ -213,7 +215,10 @@ func TestTransactionSend(t *testing.T) { t.Run("sendWithBoost", func(t *testing.T) { t.Parallel() - price := big.NewInt(0).Div(new(big.Int).Mul(suggestedGasPrice, big.NewInt(15)), big.NewInt(10)) + price := big.NewInt(0).Div(new(big.Int).Mul(suggestedGasPrice, big.NewInt(25)), big.NewInt(10)) + + // tip is the same as suggestedGasPrice and boost is 50% + // so final gas price will be 2.5x suggestedGasPrice signedTx := types.NewTx(&types.DynamicFeeTx{ ChainID: chainID, @@ -221,7 +226,7 @@ func TestTransactionSend(t *testing.T) { To: &recipient, Value: value, Gas: estimatedGasLimit, - GasTipCap: price, + GasTipCap: suggestedGasPrice, GasFeeCap: price, Data: txData, }) @@ -259,6 +264,9 @@ func TestTransactionSend(t *testing.T) { backendmock.WithPendingNonceAtFunc(func(ctx context.Context, account common.Address) (uint64, error) { return nonce - 1, nil }), + backendmock.WithSuggestGasTipCapFunc(func(ctx context.Context) (*big.Int, error) { + return suggestedGasPrice, nil + }), ), signerMockForTransaction(t, signedTx, sender, chainID), store, @@ -313,8 +321,8 @@ func TestTransactionSend(t *testing.T) { t.Fatalf("got wrong gas limit in stored transaction. wanted %d, got %d", estimatedGasLimit, storedTransaction.GasLimit) } - if new(big.Int).Div(new(big.Int).Mul(suggestedGasPrice, big.NewInt(15)), big.NewInt(10)).Cmp(storedTransaction.GasPrice) != 0 { - t.Fatalf("got wrong gas price in stored transaction. wanted %d, got %d", suggestedGasPrice, storedTransaction.GasPrice) + if want := new(big.Int).Div(new(big.Int).Mul(suggestedGasPrice, big.NewInt(25)), big.NewInt(10)); want.Cmp(storedTransaction.GasPrice) != 0 { + t.Fatalf("got wrong gas price in stored transaction. wanted %d, got %d", want, storedTransaction.GasPrice) } if storedTransaction.Nonce != nonce { @@ -377,6 +385,9 @@ func TestTransactionSend(t *testing.T) { backendmock.WithPendingNonceAtFunc(func(ctx context.Context, account common.Address) (uint64, error) { return nonce, nil }), + backendmock.WithSuggestGasTipCapFunc(func(ctx context.Context) (*big.Int, error) { + return big.NewInt(0), nil + }), ), signerMockForTransaction(t, signedTx, sender, chainID), store, @@ -455,6 +466,9 @@ func TestTransactionSend(t *testing.T) { backendmock.WithPendingNonceAtFunc(func(ctx context.Context, account common.Address) (uint64, error) { return nextNonce, nil }), + backendmock.WithSuggestGasTipCapFunc(func(ctx context.Context) (*big.Int, error) { + return big.NewInt(0), nil + }), ), signerMockForTransaction(t, signedTx, sender, chainID), store, diff --git a/pkg/transaction/wrapped/wrapped.go b/pkg/transaction/wrapped/wrapped.go index c4e5b82d953..24d8e3d5a0c 100644 --- a/pkg/transaction/wrapped/wrapped.go +++ b/pkg/transaction/wrapped/wrapped.go @@ -147,6 +147,17 @@ func (b *wrappedBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) return gasPrice, nil } +func (b *wrappedBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { + b.metrics.TotalRPCCalls.Inc() + b.metrics.SuggestGasPriceCalls.Inc() + gasTipCap, err := b.backend.SuggestGasTipCap(ctx) + if err != nil { + b.metrics.TotalRPCErrors.Inc() + return nil, err + } + return gasTipCap, nil +} + func (b *wrappedBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error) { b.metrics.TotalRPCCalls.Inc() b.metrics.EstimateGasCalls.Inc()