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

fix(rfq-relayer): profitability check accounts for offsets #3288

Merged
merged 10 commits into from
Oct 17, 2024

Conversation

dwasse
Copy link
Collaborator

@dwasse dwasse commented Oct 14, 2024

Summary by CodeRabbit

  • New Features

    • Introduced a new method to calculate adjusted amounts for token quotes, enhancing profitability assessments.
    • Improved checks for token pairing and relay amounts to ensure accurate processing.
  • Bug Fixes

    • Enhanced logic for profitability evaluations by integrating adjustments for offsets.
  • Tests

    • Updated test suite to validate new quote offset logic and profitability scenarios.

Copy link
Contributor

coderabbitai bot commented Oct 14, 2024

Walkthrough

The changes in this pull request involve modifications to the quoter.go and quoter_test.go files within the RFQ relayer service. A new method getAmountWithOffset has been added to the Manager struct, enhancing the profitability assessment in the IsProfitable function. The ShouldProcess method has been refined for better checks on token pairing and relay amounts. Corresponding updates have been made to the test suite to accommodate the new logic, including adjustments for quote offsets and profitability calculations.

Changes

File Change Summary
services/rfq/relayer/quoter/quoter.go - Added method getAmountWithOffset to Manager struct.
- Updated IsProfitable to use adjusted amounts.
- Refined ShouldProcess with enhanced checks for token pairing and relay amounts.
- Modified getDestAmount to accept a QuoteInput struct.
services/rfq/relayer/quoter/quoter_test.go - Added setQuoteOffsets method for configuring quote offsets.
- Updated TestIsProfitable to incorporate quote offsets.
- Modified TestGetOriginAmount for new parameters.
- Updated TestGetDestAmount to accept new input structure.

Possibly related PRs

  • feat(rfq-relayer): add MaxBalance param #2917: This PR introduces a new parameter MaxBalance to the RFQ Relayer functionality, which is relevant to the changes in the ShouldProcess method that checks against maximum allowable amounts.
  • feat(rfq-relayer): add MaxRelayAmount #3259: This PR adds MaxQuoteAmount and MaxRelayAmount fields to the TokenConfig struct, which directly relates to the modifications in the ShouldProcess and getOriginAmount methods that involve checking against maximum amounts.

Suggested labels

size/m

Suggested reviewers

  • aureliusbtc
  • trajan0x

🐰 In the meadow, where quotes do play,
Adjustments come to brighten the day.
With offsets set and checks refined,
Profitability's now better aligned.
Hops of joy for the changes made,
In the world of tokens, we won't be swayed! 🌼


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between a306d61 and d682f96.

📒 Files selected for processing (2)
  • services/rfq/relayer/quoter/quoter.go (3 hunks)
  • services/rfq/relayer/quoter/quoter_test.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • services/rfq/relayer/quoter/quoter_test.go
🧰 Additional context used
🔇 Additional comments (6)
services/rfq/relayer/quoter/quoter.go (6)

243-246: Ensure 'originAmountAdj' is not nil to prevent potential runtime panic

After obtaining originAmountAdj, it's important to check if it is not nil before using it in comparisons to avoid a possible nil pointer dereference.


248-251: Ensure 'costAdj' is not nil to prevent potential runtime panic

Similar to originAmountAdj, verify that costAdj is not nil after calling getAmountWithOffset to prevent a possible nil pointer dereference during comparison.


271-274: Avoid unsafe conversion from 'uint32' to 'int' for 'chainID'

Converting chainID from uint32 to int can lead to data loss or overflow if chainID exceeds the maximum value of int. It's safer to use consistent types.


275-275: Fix potential precision loss in 'applyOffset' due to casting 'offsetBps'

In the applyOffset function, converting offsetBps from float64 to int64 loses the fractional part, which can cause incorrect calculations.


Line range hint 611-616: Update function call to match new 'getDestAmount' signature

The getDestAmount function signature has changed to include input as a parameter. Ensure that all calls to this function are updated accordingly.


804-835: Verify correctness of offset calculations in 'getDestAmount'

The getDestAmount method now calculates the totalOffsetBps by summing originOffsetBps, destOffsetBps, and quoteWidthBps. It's crucial to verify that these values are correctly retrieved and that the addition does not introduce any errors due to floating-point precision.

You can run the following script to check if the offsets are correctly defined in the configuration:

Replace YOUR_ORIGIN_CHAIN_ID, YOUR_DEST_CHAIN_ID, and YOUR_TOKEN_NAME with actual values from your configuration to verify the offsets.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added go Pull requests that update Go code size/s labels Oct 14, 2024
Copy link

codecov bot commented Oct 14, 2024

Codecov Report

Attention: Patch coverage is 64.28571% with 15 lines in your changes missing coverage. Please review.

Project coverage is 25.00000%. Comparing base (93f9886) to head (d682f96).
Report is 18 commits behind head on master.

Files with missing lines Patch % Lines
services/rfq/relayer/quoter/quoter.go 64.28571% 10 Missing and 5 partials ⚠️
Additional details and impacted files
@@                 Coverage Diff                 @@
##              master       #3288         +/-   ##
===================================================
- Coverage   25.89782%   25.00000%   -0.89782%     
===================================================
  Files             97         198        +101     
  Lines           3954       13132       +9178     
  Branches          82          82                 
===================================================
+ Hits            1024        3283       +2259     
- Misses          2922        9563       +6641     
- Partials           8         286        +278     
Flag Coverage Δ
opbot 0.48870% <ø> (ø)
promexporter 6.81642% <ø> (ø)
rfq 24.61321% <64.28571%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Outside diff range and nitpick comments (1)
services/rfq/relayer/quoter/quoter.go (1)

266-266: Remove redundant type conversion of 'chainID'

The variable chainID is already of type uint32. Casting it again to uint32 is unnecessary.

Apply this diff to simplify the code:

-tokenName, err := m.config.GetTokenName(uint32(chainID), tokenAddr.Hex())
+tokenName, err := m.config.GetTokenName(chainID, tokenAddr.Hex())
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 93f9886 and c4467f2.

📒 Files selected for processing (2)
  • services/rfq/relayer/quoter/quoter.go (1 hunks)
  • services/rfq/relayer/quoter/quoter_test.go (1 hunks)
🧰 Additional context used
🔇 Additional comments (1)
services/rfq/relayer/quoter/quoter_test.go (1)

175-185: Good use of helper function setQuoteOffsets for configuration adjustments.

Encapsulating the quote offset configuration into the setQuoteOffsets function improves code readability and reduces code duplication.

Comment on lines 188 to 202
// Set dest offset to 20%; we get a token that is more valuable -> still profitable
setQuoteOffsets(0, 2000)
s.True(s.manager.IsProfitable(s.GetTestContext(), quote))

// Set dest offset to -20%; we get a token that is less valuable -> no longer profitable
setQuoteOffsets(0, -2000)
s.False(s.manager.IsProfitable(s.GetTestContext(), quote))

// Set origin offset to 20%; we send a token that is more valuable -> no longer profitable
setQuoteOffsets(2000, 0)
s.False(s.manager.IsProfitable(s.GetTestContext(), quote))

// Set origin offset to -20%; we send a token that is less valuable -> still profitable
setQuoteOffsets(-2000, 0)
s.True(s.manager.IsProfitable(s.GetTestContext(), quote))
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider defining offset values as constants for clarity and maintainability.

Defining the offset values (2000, -2000) as named constants will enhance readability and make it easier to adjust the values in the future.

Here's how you could define the constants:

+	const (
+		positiveOffsetBps = 2000  // +20% offset
+		negativeOffsetBps = -2000 // -20% offset
+	)

And update the function calls:

-	setQuoteOffsets(0, 2000)
+	setQuoteOffsets(0, positiveOffsetBps)

-	setQuoteOffsets(0, -2000)
+	setQuoteOffsets(0, negativeOffsetBps)

-	setQuoteOffsets(2000, 0)
+	setQuoteOffsets(positiveOffsetBps, 0)

-	setQuoteOffsets(-2000, 0)
+	setQuoteOffsets(negativeOffsetBps, 0)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Set dest offset to 20%; we get a token that is more valuable -> still profitable
setQuoteOffsets(0, 2000)
s.True(s.manager.IsProfitable(s.GetTestContext(), quote))
// Set dest offset to -20%; we get a token that is less valuable -> no longer profitable
setQuoteOffsets(0, -2000)
s.False(s.manager.IsProfitable(s.GetTestContext(), quote))
// Set origin offset to 20%; we send a token that is more valuable -> no longer profitable
setQuoteOffsets(2000, 0)
s.False(s.manager.IsProfitable(s.GetTestContext(), quote))
// Set origin offset to -20%; we send a token that is less valuable -> still profitable
setQuoteOffsets(-2000, 0)
s.True(s.manager.IsProfitable(s.GetTestContext(), quote))
const (
positiveOffsetBps = 2000 // +20% offset
negativeOffsetBps = -2000 // -20% offset
)
// Set dest offset to 20%; we get a token that is more valuable -> still profitable
setQuoteOffsets(0, positiveOffsetBps)
s.True(s.manager.IsProfitable(s.GetTestContext(), quote))
// Set dest offset to -20%; we get a token that is less valuable -> no longer profitable
setQuoteOffsets(0, negativeOffsetBps)
s.False(s.manager.IsProfitable(s.GetTestContext(), quote))
// Set origin offset to 20%; we send a token that is more valuable -> no longer profitable
setQuoteOffsets(positiveOffsetBps, 0)
s.False(s.manager.IsProfitable(s.GetTestContext(), quote))
// Set origin offset to -20%; we send a token that is less valuable -> still profitable
setQuoteOffsets(negativeOffsetBps, 0)
s.True(s.manager.IsProfitable(s.GetTestContext(), quote))

Comment on lines +248 to +251
costAdj, err := m.getAmountWithOffset(ctx, quote.Transaction.DestChainId, quote.Transaction.DestToken, cost)
if err != nil {
return false, fmt.Errorf("error getting cost with offset: %w", err)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ensure non-nil 'costAdj' to prevent potential runtime panic

Similar to originAmountAdj, verify that costAdj is not nil after calling getAmountWithOffset to avoid a possible nil pointer dereference during comparison.

Apply this diff to add a nil check:

costAdj, err := m.getAmountWithOffset(ctx, quote.Transaction.DestChainId, quote.Transaction.DestToken, cost)
if err != nil {
    return false, fmt.Errorf("error getting cost with offset: %w", err)
}
+if costAdj == nil {
+    return false, fmt.Errorf("costAdj is nil")
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
costAdj, err := m.getAmountWithOffset(ctx, quote.Transaction.DestChainId, quote.Transaction.DestToken, cost)
if err != nil {
return false, fmt.Errorf("error getting cost with offset: %w", err)
}
costAdj, err := m.getAmountWithOffset(ctx, quote.Transaction.DestChainId, quote.Transaction.DestToken, cost)
if err != nil {
return false, fmt.Errorf("error getting cost with offset: %w", err)
}
if costAdj == nil {
return false, fmt.Errorf("costAdj is nil")
}

return nil, fmt.Errorf("error getting token name: %w", err)
}
// apply offset directly to amount without considering origin/dest
quoteOffsetBps, err := m.config.GetQuoteOffsetBps(int(chainID), tokenName, false)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid unsafe conversion from 'uint32' to 'int' for 'chainID'

Converting chainID from uint32 to int can lead to data loss or overflow if chainID exceeds the maximum value of int. It's safer to use consistent types.

Apply this diff to fix the issue:

-quoteOffsetBps, err := m.config.GetQuoteOffsetBps(int(chainID), tokenName, false)
+quoteOffsetBps, err := m.config.GetQuoteOffsetBps(chainID, tokenName, false)

Ensure the GetQuoteOffsetBps method accepts uint32 for chainID.

Committable suggestion was skipped due to low confidence.

Comment on lines +243 to +246
originAmountAdj, err := m.getAmountWithOffset(ctx, quote.Transaction.OriginChainId, quote.Transaction.OriginToken, quote.Transaction.OriginAmount)
if err != nil {
return false, fmt.Errorf("error getting origin amount with offset: %w", err)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ensure non-nil 'originAmountAdj' to prevent potential runtime panic

After obtaining originAmountAdj, it is important to check if it is not nil before using it in comparisons to avoid a possible nil pointer dereference.

Apply this diff to add a nil check:

originAmountAdj, err := m.getAmountWithOffset(ctx, quote.Transaction.OriginChainId, quote.Transaction.OriginToken, quote.Transaction.OriginAmount)
if err != nil {
    return false, fmt.Errorf("error getting origin amount with offset: %w", err)
}
+if originAmountAdj == nil {
+    return false, fmt.Errorf("originAmountAdj is nil")
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
originAmountAdj, err := m.getAmountWithOffset(ctx, quote.Transaction.OriginChainId, quote.Transaction.OriginToken, quote.Transaction.OriginAmount)
if err != nil {
return false, fmt.Errorf("error getting origin amount with offset: %w", err)
}
originAmountAdj, err := m.getAmountWithOffset(ctx, quote.Transaction.OriginChainId, quote.Transaction.OriginToken, quote.Transaction.OriginAmount)
if err != nil {
return false, fmt.Errorf("error getting origin amount with offset: %w", err)
}
if originAmountAdj == nil {
return false, fmt.Errorf("originAmountAdj is nil")
}

if err != nil {
return nil, fmt.Errorf("error getting quote offset bps: %w", err)
}
amountAdj := m.applyOffset(ctx, quoteOffsetBps, amount)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix potential precision loss in 'applyOffset' due to casting 'offsetBps'

In the applyOffset function, converting offsetBps from float64 to int64 loses the fractional part, which can cause incorrect calculations. This affects the accuracy of amount adjustments.

Modify the applyOffset function to avoid casting offsetBps to int64:

func (m *Manager) applyOffset(parentCtx context.Context, offsetBps float64, target *big.Int) (result *big.Int) {
    _, span := m.metricsHandler.Tracer().Start(parentCtx, "applyOffset", trace.WithAttributes(
        attribute.Float64("offset_bps", offsetBps),
        attribute.String("target", target.String()),
    ))
    defer func() {
        metrics.EndSpan(span)
    }()

-   offsetFraction := new(big.Float).Quo(new(big.Float).SetInt64(int64(offsetBps)), new(big.Float).SetInt64(10000))
-   offsetFactor := new(big.Float).Sub(new(big.Float).SetInt64(1), offsetFraction)
+   offsetFraction := new(big.Float).Quo(big.NewFloat(offsetBps), big.NewFloat(10000))
+   offsetFactor := new(big.Float).Sub(big.NewFloat(1), offsetFraction)

    result, _ = new(big.Float).Mul(new(big.Float).SetInt(target), offsetFactor).Int(nil)
    return result
}

This change preserves the fractional part of offsetBps and ensures accurate calculations.

Committable suggestion was skipped due to low confidence.

Copy link

cloudflare-workers-and-pages bot commented Oct 14, 2024

Deploying sanguine-fe with  Cloudflare Pages  Cloudflare Pages

Latest commit: d682f96
Status: ✅  Deploy successful!
Preview URL: https://1b7e448e.sanguine-fe.pages.dev
Branch Preview URL: https://fix-profitability-check.sanguine-fe.pages.dev

View logs

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (1)
services/rfq/relayer/quoter/quoter.go (1)

Line range hint 837-852: Potential precision loss in offset calculation

While the applyOffset function remains largely unchanged, there's a potential issue with precision loss due to casting offsetBps from float64 to int64. This can affect the accuracy of the offset calculations.

To improve precision, consider modifying the function as follows:

func (m *Manager) applyOffset(parentCtx context.Context, offsetBps float64, target *big.Int) (result *big.Int) {
    _, span := m.metricsHandler.Tracer().Start(parentCtx, "applyOffset", trace.WithAttributes(
        attribute.Float64("offset_bps", offsetBps),
        attribute.String("target", target.String()),
    ))
    defer func() {
        metrics.EndSpan(span)
    }()

-   offsetFraction := new(big.Float).Quo(new(big.Float).SetInt64(int64(offsetBps)), new(big.Float).SetInt64(10000))
-   offsetFactor := new(big.Float).Sub(new(big.Float).SetInt64(1), offsetFraction)
+   offsetFraction := new(big.Float).Quo(big.NewFloat(offsetBps), big.NewFloat(10000))
+   offsetFactor := new(big.Float).Sub(big.NewFloat(1), offsetFraction)

    result, _ = new(big.Float).Mul(new(big.Float).SetInt(target), offsetFactor).Int(nil)
    return result
}

This change preserves the fractional part of offsetBps and ensures more accurate calculations.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 245-246: services/rfq/relayer/quoter/quoter.go#L245-L246
Added lines #L245 - L246 were not covered by tests


[warning] 250-251: services/rfq/relayer/quoter/quoter.go#L250-L251
Added lines #L250 - L251 were not covered by tests


[warning] 268-269: services/rfq/relayer/quoter/quoter.go#L268-L269
Added lines #L268 - L269 were not covered by tests


[warning] 273-274: services/rfq/relayer/quoter/quoter.go#L273-L274
Added lines #L273 - L274 were not covered by tests

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 4c3ee56 and a306d61.

📒 Files selected for processing (3)
  • services/rfq/relayer/quoter/export_test.go (1 hunks)
  • services/rfq/relayer/quoter/quoter.go (3 hunks)
  • services/rfq/relayer/quoter/quoter_test.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • services/rfq/relayer/quoter/quoter_test.go
🧰 Additional context used
🪛 GitHub Check: codecov/patch
services/rfq/relayer/quoter/quoter.go

[warning] 245-246: services/rfq/relayer/quoter/quoter.go#L245-L246
Added lines #L245 - L246 were not covered by tests


[warning] 250-251: services/rfq/relayer/quoter/quoter.go#L250-L251
Added lines #L250 - L251 were not covered by tests


[warning] 268-269: services/rfq/relayer/quoter/quoter.go#L268-L269
Added lines #L268 - L269 were not covered by tests


[warning] 273-274: services/rfq/relayer/quoter/quoter.go#L273-L274
Added lines #L273 - L274 were not covered by tests

🔇 Additional comments (4)
services/rfq/relayer/quoter/export_test.go (1)

21-22: LGTM. Verify usage across the codebase.

The updated function signature looks good. It removes the chainID parameter and introduces a more comprehensive input QuoteInput parameter, which likely provides more flexibility and information for quote generation.

To ensure this change doesn't break existing code, please run the following script to verify all calls to GetDestAmount have been updated:

✅ Verification successful

To ensure that all calls to GetDestAmount have been updated to match the new signature, please run the following script:


Verification Successful.

All calls to GetDestAmount have been updated to match the new signature with the input QuoteInput parameter. No instances of the old signature were found that could cause issues.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all calls to GetDestAmount match the new signature

# Test: Search for function calls to GetDestAmount. 
# Expect: Only occurrences of the new signature (4 parameters, with QuoteInput as the last one).
rg --type go -e 'GetDestAmount\s*\([^)]*\)' -g '!*_test.go'

Length of output: 445


Script:

#!/bin/bash
# Description: Find all calls to GetDestAmount with fewer than 4 parameters

rg --type go -e 'GetDestAmount\s*\(([^,]*,){0,2}[^,]*\)' -g '!*_test.go'

Length of output: 458

services/rfq/relayer/quoter/quoter.go (3)

Line range hint 611-624: Updated quote generation logic

The changes to the generateQuote function correctly incorporate the new getDestAmount method, which now takes additional parameters (destToken and input). This update aligns well with the enhanced quote calculation logic that considers offsets.


804-835: Enhanced destination amount calculation with multiple offsets

The getDestAmount function has been significantly improved:

  1. It now considers origin, destination, and quote width offsets, providing a more accurate calculation of the destination amount.
  2. The use of the QuoteInput struct enhances code readability and maintainability.
  3. Error handling is consistent and appropriate throughout the function.
  4. Span attributes have been updated to include the new offset values, improving observability.

These changes result in a more robust and precise quote calculation process.


242-263: ⚠️ Potential issue

Improved profitability calculation with offset adjustments.

The changes to the IsProfitable function enhance the accuracy of profitability calculations by considering internal offsets for both origin and destination token values. This is a good improvement to the logic.

However, there's a potential issue with nil pointer dereferences. Please add nil checks for originAmountAdj and costAdj before using them in the comparison.

Apply this diff to add nil checks:

originAmountAdj, err := m.getAmountWithOffset(ctx, quote.Transaction.OriginChainId, quote.Transaction.OriginToken, quote.Transaction.OriginAmount)
if err != nil {
    return false, fmt.Errorf("error getting origin amount with offset: %w", err)
}
+if originAmountAdj == nil {
+    return false, fmt.Errorf("originAmountAdj is nil")
+}
// assume that fee is denominated in dest token terms
costAdj, err := m.getAmountWithOffset(ctx, quote.Transaction.DestChainId, quote.Transaction.DestToken, cost)
if err != nil {
    return false, fmt.Errorf("error getting cost with offset: %w", err)
}
+if costAdj == nil {
+    return false, fmt.Errorf("costAdj is nil")
+}
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 245-246: services/rfq/relayer/quoter/quoter.go#L245-L246
Added lines #L245 - L246 were not covered by tests


[warning] 250-251: services/rfq/relayer/quoter/quoter.go#L250-L251
Added lines #L250 - L251 were not covered by tests

Comment on lines 265 to 277
func (m *Manager) getAmountWithOffset(ctx context.Context, chainID uint32, tokenAddr common.Address, amount *big.Int) (*big.Int, error) {
tokenName, err := m.config.GetTokenName(chainID, tokenAddr.Hex())
if err != nil {
return nil, fmt.Errorf("error getting token name: %w", err)
}
// apply offset directly to amount without considering origin/dest
quoteOffsetBps, err := m.config.GetQuoteOffsetBps(int(chainID), tokenName, false)
if err != nil {
return nil, fmt.Errorf("error getting quote offset bps: %w", err)
}
amountAdj := m.applyOffset(ctx, quoteOffsetBps, amount)

return amountAdj, nil
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

New function for offset-adjusted amounts

The getAmountWithOffset function is a good addition that calculates adjusted amounts based on offsets. It improves the accuracy of quote calculations.

However, there are two issues to address:

  1. Unsafe type conversion:

The GetQuoteOffsetBps call involves an unsafe conversion from uint32 to int for chainID. This can lead to data loss or overflow if chainID exceeds the maximum value of int. Apply this diff to fix the issue:

-quoteOffsetBps, err := m.config.GetQuoteOffsetBps(int(chainID), tokenName, false)
+quoteOffsetBps, err := m.config.GetQuoteOffsetBps(chainID, tokenName, false)

Ensure the GetQuoteOffsetBps method accepts uint32 for chainID.

  1. Missing nil check:

Add a nil check after calling applyOffset to handle potential nil returns. Apply this diff:

amountAdj := m.applyOffset(ctx, quoteOffsetBps, amount)
+if amountAdj == nil {
+    return nil, fmt.Errorf("adjusted amount is nil")
+}

return amountAdj, nil

Committable suggestion was skipped due to low confidence.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 268-269: services/rfq/relayer/quoter/quoter.go#L268-L269
Added lines #L268 - L269 were not covered by tests


[warning] 273-274: services/rfq/relayer/quoter/quoter.go#L273-L274
Added lines #L273 - L274 were not covered by tests

@dwasse dwasse merged commit 6880ddd into master Oct 17, 2024
44 checks passed
@dwasse dwasse deleted the fix/profitability-check branch October 17, 2024 16:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
go Pull requests that update Go code needs-go-generate-services/rfq size/s
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant