Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(rfq-relayer): apply zap fee to dest amount for active quotes [SLT-465] #3395

Merged
merged 5 commits into from
Nov 14, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Feat: add TestGenerateActiveRFQ
  • Loading branch information
dwasse committed Nov 14, 2024
commit 868c213e024a26ba3e7d3f83867823e882f7be36
1 change: 0 additions & 1 deletion services/rfq/api/model/request.go
Original file line number Diff line number Diff line change
@@ -55,7 +55,6 @@ type QuoteData struct {
DestChainID int `json:"dest_chain_id"`
OriginTokenAddr string `json:"origin_token_addr"`
DestTokenAddr string `json:"dest_token_addr"`
OriginAmount string `json:"origin_amount"`
ExpirationWindow int64 `json:"expiration_window"`
ZapData string `json:"zap_data"`
ZapNative string `json:"zap_native"`
4 changes: 4 additions & 0 deletions services/rfq/relayer/quoter/export_test.go
Original file line number Diff line number Diff line change
@@ -22,6 +22,10 @@ func (m *Manager) GetDestAmount(ctx context.Context, quoteAmount *big.Int, token
return m.getDestAmount(ctx, quoteAmount, tokenName, input)
}

func (m *Manager) GenerateActiveRFQ(ctx context.Context, msg *model.ActiveRFQMessage) (resp *model.ActiveRFQMessage, err error) {
return m.generateActiveRFQ(ctx, msg)
}
Comment on lines +25 to +27
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Missing test coverage for zap fee calculations

The test coverage for the addZapFees functionality is incomplete. While there are tests for general fee calculations in fee_pricer_test.go, there are no specific test cases for:

  • Zap data gas estimation (getZapGasEstimate)
  • Zap native token value conversion
  • Combined zap fees with both data and native token components

Required test additions:

  • Test cases in fee_pricer_test.go for addZapFees with various zap data scenarios
  • Test cases for zap native token value calculations
  • Edge cases with zero values and invalid inputs
🔗 Analysis chain

Verify test coverage for the new functionality.

Since this is a test export, ensure that comprehensive tests are implemented for the underlying generateActiveRFQ method, particularly around the new zap fee calculations mentioned in the PR title.


Let me gather more information about the test coverage by checking the actual test implementations.


Let me check for specific test coverage of the zap fee calculations.


Let me check for tests in the pricer package since that's where the zap fee implementation is located.


Let me check the actual content of the fee pricer test files to verify the test coverage.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for test coverage of the generateActiveRFQ functionality
# Look for test files that might contain tests for the new functionality

# Search for test files containing ActiveRFQ tests
echo "Searching for relevant test files..."
rg -l "TestGenerate.*ActiveRFQ|TestManager.*ActiveRFQ" --type go

# Look for actual test implementations of the functionality
echo "Searching for test implementations..."
rg -A 10 "func Test.*ActiveRFQ" --type go

# Check for zap fee related test assertions
echo "Checking for zap fee related tests..."
rg "zap.*fee|zapFee|ZapFee" --type go

Length of output: 950


Script:

#!/bin/bash
# Check the actual test implementations in the identified test file
echo "Checking test implementations in quoter_test.go..."
cat services/rfq/relayer/quoter/quoter_test.go

# Also check the implementation of generateActiveRFQ to understand what should be tested
echo -e "\nChecking the actual implementation..."
rg -A 20 "func.*generateActiveRFQ" services/rfq/relayer/quoter/

Length of output: 29647


Script:

#!/bin/bash
# Look for test files that might contain tests for zap fee calculations
echo "Checking test coverage for zap fee calculations..."
rg -A 10 "TestAdd.*ZapFee|Test.*ZapFee" --type go

# Look for test assertions related to zap fees
echo -e "\nChecking for zap fee related test assertions..."
rg "assert.*[Zz]ap.*[Ff]ee|expect.*[Zz]ap.*[Ff]ee" --type go

# Check the implementation of addZapFees to understand what should be tested
echo -e "\nChecking addZapFees implementation..."
rg -A 20 "func.*addZapFees" services/rfq/relayer/pricer/

Length of output: 2280


Script:

#!/bin/bash
# Check for test files in the pricer package
echo "Checking for test files in pricer package..."
fd ".*_test.go" services/rfq/relayer/pricer/

# Look for test implementations related to fee calculations
echo -e "\nChecking fee calculation test implementations..."
rg -A 10 "func Test.*Fee" services/rfq/relayer/pricer/

# Check for test setup and mocks related to fee calculations
echo -e "\nChecking test setup and mocks..."
rg "type.*Suite.*struct|func.*Suite.*Setup" services/rfq/relayer/pricer/

Length of output: 785


Script:

#!/bin/bash
# Check the content of fee pricer test files
echo "Checking fee_pricer_test.go content..."
cat services/rfq/relayer/pricer/fee_pricer_test.go

echo -e "\nChecking suite_test.go content..."
cat services/rfq/relayer/pricer/suite_test.go

Length of output: 20603


func (m *Manager) SetConfig(cfg relconfig.Config) {
m.config = cfg
}
6 changes: 5 additions & 1 deletion services/rfq/relayer/quoter/quoter.go
Original file line number Diff line number Diff line change
@@ -407,7 +407,11 @@ func (m *Manager) generateActiveRFQ(ctx context.Context, msg *model.ActiveRFQMes
if !ok {
return nil, fmt.Errorf("invalid fixed fee: %s", rawQuote.FixedFee)
}
rawQuote.DestAmount = new(big.Int).Sub(destAmountBigInt, fixedFeeBigInt).String()
destAmountAdj := new(big.Int).Sub(destAmountBigInt, fixedFeeBigInt)
if destAmountAdj.Sign() < 0 {
destAmountAdj = big.NewInt(0)
}
rawQuote.DestAmount = destAmountAdj.String()
span.SetAttributes(attribute.String("dest_amount", rawQuote.DestAmount))

rfqResp := model.WsRFQResponse{
67 changes: 67 additions & 0 deletions services/rfq/relayer/quoter/quoter_test.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package quoter_test

import (
"encoding/json"
"fmt"
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/mock"
"github.com/synapsecns/sanguine/core/metrics"
"github.com/synapsecns/sanguine/core/testsuite"
clientMocks "github.com/synapsecns/sanguine/ethergo/client/mocks"
fetcherMocks "github.com/synapsecns/sanguine/ethergo/submitter/mocks"
"github.com/synapsecns/sanguine/services/rfq/api/model"
"github.com/synapsecns/sanguine/services/rfq/api/rest"
"github.com/synapsecns/sanguine/services/rfq/contracts/fastbridgev2"
inventoryMocks "github.com/synapsecns/sanguine/services/rfq/relayer/inventory/mocks"
"github.com/synapsecns/sanguine/services/rfq/relayer/pricer"
@@ -444,6 +447,70 @@ func (s *QuoterSuite) TestGetOriginAmountActiveQuotes() {
s.Equal(expectedAmount, quoteAmount)
}

func (s *QuoterSuite) TestGenerateActiveRFQ() {
origin := int(s.origin)
dest := int(s.destination)
originAddr := common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
destAddr := common.HexToAddress("0x0b2c639c533813f4aa9d7837caf62653d097ff85")
balance := big.NewInt(100_000_000) // 100 USDC
originAmount := big.NewInt(50_000_000) // 50 USDC

balances := map[int]map[common.Address]*big.Int{
origin: {
originAddr: balance,
},
dest: {
destAddr: balance,
},
}

currentHeader := big.NewInt(100_000_000_000) // 100 gwei
clientFetcher := new(fetcherMocks.ClientFetcher)
clientMock := new(clientMocks.EVM)
clientMock.On(testsuite.GetFunctionName(clientMock.SuggestGasPrice), mock.Anything).Return(currentHeader, nil)
clientFetcher.On(testsuite.GetFunctionName(clientMock.EstimateGas), mock.Anything, mock.Anything).Return(100_000, nil)
clientFetcher.On(testsuite.GetFunctionName(clientFetcher.GetClient), mock.Anything, mock.Anything).Return(clientMock, nil)
priceFetcher := new(priceMocks.CoingeckoPriceFetcher)
priceFetcher.On(testsuite.GetFunctionName(priceFetcher.GetPrice), mock.Anything, mock.Anything).Return(0., fmt.Errorf("not using mocked price"))
feePricer := pricer.NewFeePricer(s.config, clientFetcher, priceFetcher, metrics.NewNullHandler(), common.HexToAddress("0x123"))
inventoryManager := new(inventoryMocks.Manager)
inventoryManager.On(testsuite.GetFunctionName(inventoryManager.HasSufficientGas), mock.Anything, mock.Anything, mock.Anything).Return(true, nil)
inventoryManager.On(testsuite.GetFunctionName(inventoryManager.GetCommittableBalances), mock.Anything, mock.Anything, mock.Anything).Return(balances, nil)
mgr, err := quoter.NewQuoterManager(s.config, metrics.NewNullHandler(), inventoryManager, nil, feePricer, nil)
s.NoError(err)

var ok bool
s.manager, ok = mgr.(*quoter.Manager)
s.True(ok)

req := model.PutRFQRequest{
UserAddress: "0x123",
IntegratorID: "123",
QuoteTypes: []string{"active"},
Data: model.QuoteData{
OriginChainID: origin,
DestChainID: dest,
OriginAmountExact: originAmount.String(),
OriginTokenAddr: originAddr.String(),
DestTokenAddr: destAddr.String(),
},
}
reqBytes, err := json.Marshal(req)
s.NoError(err)
msg := model.ActiveRFQMessage{
Op: rest.RequestQuoteOp,
Content: json.RawMessage(reqBytes),
}

respMsg, err := s.manager.GenerateActiveRFQ(s.GetTestContext(), &msg)
s.NoError(err)
var resp model.PutRFQResponse
err = json.Unmarshal(respMsg.Content, &resp)
s.NoError(err)
s.False(resp.Success)
s.Equal("0", resp.DestAmount)
}

func (s *QuoterSuite) TestGetOriginAmount() {
origin := int(s.origin)
dest := int(s.destination)