Skip to content

Commit

Permalink
Fetch priorityFee from EVM RPC
Browse files Browse the repository at this point in the history
  • Loading branch information
swift1337 committed Jun 27, 2024
1 parent 87b2f41 commit 9ad5692
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 68 deletions.
38 changes: 36 additions & 2 deletions zetaclient/chains/evm/observer/observer.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ type Observer struct {

// outboundConfirmedTransactions is the map to index confirmed transactions by hash
outboundConfirmedTransactions map[string]*ethtypes.Transaction

priorityGasFee *big.Int
}

// NewObserver returns a new EVM chain observer
Expand Down Expand Up @@ -327,13 +329,19 @@ func (ob *Observer) WatchGasPrice() {
}

func (ob *Observer) PostGasPrice() error {
// issue: https://github.com/zeta-chain/node/issues/1160
ctx := context.Background()

// GAS PRICE
gasPrice, err := ob.evmClient.SuggestGasPrice(context.TODO())
gasPrice, err := ob.evmClient.SuggestGasPrice(ctx)
if err != nil {
ob.Logger().GasPrice.Err(err).Msg("Err SuggestGasPrice:")
return err
}
blockNum, err := ob.evmClient.BlockNumber(context.TODO())

ob.fetchPriorityGasFee(ctx)

blockNum, err := ob.evmClient.BlockNumber(ctx)
if err != nil {
ob.Logger().GasPrice.Err(err).Msg("Err Fetching Most recent Block : ")
return err
Expand All @@ -352,6 +360,32 @@ func (ob *Observer) PostGasPrice() error {
return nil
}

// fetchPriorityGasFee fetches priority gas fee based on RPC response (EIP-1559).
func (ob *Observer) fetchPriorityGasFee(ctx context.Context) {
fee, err := ob.evmClient.SuggestGasTipCap(ctx)
if err != nil {
ob.Logger().GasPrice.
Debug().Err(err).
Msg("Unable to fetch priority gas fee. Signer will fallback to legacy gas logic")

fee = big.NewInt(0)
}

ob.Mu().Lock()
defer ob.Mu().Unlock()

ob.priorityGasFee = fee
}

// GetPriorityGasFee a.k.a. tx.gasTipCap>
func (ob *Observer) GetPriorityGasFee() *big.Int {
if ob.priorityGasFee == nil {
return big.NewInt(0)
}

return ob.priorityGasFee
}

// TransactionByHash query transaction by hash via JSON-RPC
func (ob *Observer) TransactionByHash(txHash string) (*ethrpc.Transaction, bool, error) {
tx, err := ob.evmJSONRPC.EthGetTransactionByHash(txHash)
Expand Down
40 changes: 40 additions & 0 deletions zetaclient/chains/evm/signer/gas.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
"math/big"

"github.com/pkg/errors"
"github.com/rs/zerolog"

"github.com/zeta-chain/zetacore/x/crosschain/types"
)

// Gas represents gas parameters for EVM transactions.
Expand Down Expand Up @@ -45,3 +48,40 @@ func (g Gas) validate() error {
func (g Gas) isLegacy() bool {
return g.PriorityFeePerUnit.Sign() <= 1
}

func determineGas(cctx *types.CrossChainTx, priorityFee *big.Int, logger zerolog.Logger) (Gas, error) {
if priorityFee == nil {
return Gas{}, errors.New("priorityFee is nil")
}

var (
outboundParams = cctx.GetCurrentOutboundParam()
limit = outboundParams.GasLimit
)

switch {
case limit < MinGasLimit:
limit = MinGasLimit
logger.Warn().
Uint64("cctx.initial_gas_limit", outboundParams.GasLimit).
Uint64("cctx.gas_limit", limit).
Msgf("Gas limit is too low. Setting to the minimum (%d)", MinGasLimit)
case limit > MaxGasLimit:
limit = MaxGasLimit
logger.Warn().
Uint64("cctx.initial_gas_limit", outboundParams.GasLimit).
Uint64("cctx.gas_limit", limit).
Msgf("Gas limit is too high; Setting to the maximum (%d)", MaxGasLimit)
}

maxFee, ok := new(big.Int).SetString(outboundParams.GasPrice, 10)
if !ok {
return Gas{}, errors.New("unable to parse gasPrice from " + outboundParams.GasPrice)
}

return Gas{
Limit: limit,
MaxFeePerUnit: maxFee,
PriorityFeePerUnit: priorityFee,
}, nil
}
64 changes: 4 additions & 60 deletions zetaclient/chains/evm/signer/outbound_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,9 @@ type OutboundData struct {
outboundParams *types.OutboundParams
}

// NewOutboundData populates transaction input fields parsed from the cctx and other parameters
// returns
// 1. New NewOutboundData Data struct or nil if an error occurred.
// 2. bool (skipTx) - if the transaction doesn't qualify to be processed the function will return true, meaning that this
// cctx will be skipped and false otherwise.
// 3. error
// NewOutboundData populates tx input fields parsed from the cctx and other parameters
// returns _, true, _ if the transaction doesn't qualify to be processed,
// meaning that cctx should be skipped.
func NewOutboundData(
cctx *types.CrossChainTx,
evmObserver *observer.Observer,
Expand Down Expand Up @@ -93,7 +90,7 @@ func NewOutboundData(
}

// Determine gas fees
gas, err := determineGas(cctx, logger)
gas, err := determineGas(cctx, evmObserver.GetPriorityGasFee(), logger)
if err != nil {
return nil, false, errors.Wrap(err, "failed to determine gas fees")
}
Expand Down Expand Up @@ -197,56 +194,3 @@ func determineDestination(cctx *types.CrossChainTx, logger zerolog.Logger) (ethc

return ethcommon.Address{}, nil, true
}

func determineGas(cctx *types.CrossChainTx, logger zerolog.Logger) (Gas, error) {
var (
outboundParams = cctx.GetCurrentOutboundParam()
limit = outboundParams.GasLimit
)

switch {
case limit < MinGasLimit:
limit = MinGasLimit
logger.Warn().
Uint64("cctx.initial_gas_limit", outboundParams.GasLimit).
Uint64("cctx.gas_limit", limit).
Msgf("Gas limit is too low. Setting to the minimum (%d)", MinGasLimit)
case limit > MaxGasLimit:
limit = MaxGasLimit
logger.Warn().
Uint64("cctx.initial_gas_limit", outboundParams.GasLimit).
Uint64("cctx.gas_limit", limit).
Msgf("Gas limit is too high; Setting to the maximum (%d)", MaxGasLimit)
}

maxFee, ok := new(big.Int).SetString(outboundParams.GasPrice, 10)
if !ok {
return Gas{}, errors.New("unable to parse gasPrice from " + outboundParams.GasPrice)
}

// TODO RELY ONLY ON Gas{} data.
// use dynamic gas price for ethereum chains.
// The code below is a fix for https://github.com/zeta-chain/node/issues/1085
// doesn't close directly the issue because we should determine if we want to keep using SuggestGasPrice if no GasPrice
// we should possibly remove it completely and return an error if no GasPrice is provided because it means no fee is processed on ZetaChain
//specified, ok := new(big.Int).SetString(cctx.GetCurrentOutboundParam().GasPrice, 10)
//if !ok {
// if chains.IsEthereumChain(chain.ChainId) {
// suggested, err := client.SuggestGasPrice(context.Background())
// if err != nil {
// return errors.Join(err, fmt.Errorf("cannot get gas price from chain %s ", chain))
// }
// txData.gasPrice = roundUpToNearestGwei(suggested)
// } else {
// return fmt.Errorf("cannot convert gas price %s ", cctx.GetCurrentOutboundParam().GasPrice)
// }
//} else {
// txData.gasPrice = specified
//}

return Gas{
Limit: limit,
MaxFeePerUnit: maxFee,
PriorityFeePerUnit: big.NewInt(0), // todo!
}, nil
}
1 change: 0 additions & 1 deletion zetaclient/chains/evm/signer/outbound_data_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
)

func TestNewOutboundData(t *testing.T) {
// Setup evm signer
mockObserver, err := getNewEvmChainObserver(t, nil)
require.NoError(t, err)

Expand Down
11 changes: 6 additions & 5 deletions zetaclient/chains/evm/signer/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,12 +399,13 @@ func (s *Signer) TryProcessOutbound(
}

// Setup Transaction input
txData, skipTx, err := NewOutboundData(cctx, evmObserver, height, logger)
if err != nil {
logger.Err(err).Msg("error setting up transaction input fields")
txData, shouldBeSkipped, err := NewOutboundData(cctx, evmObserver, height, logger)
switch {
case err != nil:
logger.Err(err).Msg("Error setting up transaction input fields")
return
}
if skipTx {
case shouldBeSkipped:
logger.Debug().Msg("Skipping outbound")
return
}

Expand Down

0 comments on commit 9ad5692

Please sign in to comment.