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

Add native ETH support to relayer #1840

Merged
merged 67 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
eb4c98e
WIP: initial relayer api
dwasse Jan 8, 2024
0129b41
WIP: use ByTxID naming
dwasse Jan 8, 2024
c740fbf
Feat: add GetQuoteRequestStatusByTxHash
dwasse Jan 8, 2024
571e865
WIP: initial impl for PUT /tx/retry
dwasse Jan 8, 2024
521e7fa
Cleanup: comments
dwasse Jan 8, 2024
2e2eba3
Feat: add OriginTxHash to QuoteRequest, RequestForQuote models
dwasse Jan 8, 2024
de99481
Merge branch 'feat/rfq-origin-tx-hash' into feat/rfq-status
dwasse Jan 8, 2024
20123b6
Feat: fetch request by origin tx hash instead of dest
dwasse Jan 8, 2024
29a27d7
WIP: initial relayer api suite
dwasse Jan 8, 2024
90d1f5f
Feat: add /health endpoint
dwasse Jan 8, 2024
8645575
Feat: add TestGetQuoteRequestByTxHash
dwasse Jan 8, 2024
902f4aa
Fix: use /health in TestNewAPIServer
dwasse Jan 8, 2024
86d01e7
Feat: add TestGetQuoteRequestByTxID
dwasse Jan 8, 2024
8689d37
Cleanup: reorder funcs
dwasse Jan 8, 2024
a7a9cf2
WIP: add TestPutTxRetry
dwasse Jan 8, 2024
165f46f
Feat: PutTxRetry -> GetTxRetry, remove auth
dwasse Jan 8, 2024
c352481
WIP: set chain IDs on test request
dwasse Jan 8, 2024
5e3f0a7
Fix: set transaction submitter in suite
dwasse Jan 8, 2024
ee218b2
Feat: check for submitted tx in TestGetTxRetry
dwasse Jan 8, 2024
a5b254f
Cleanup: add SubmitRelay func to deduplicate code
dwasse Jan 8, 2024
b99e4fa
Cleanup: lints
dwasse Jan 9, 2024
27b7998
Cleanup: lints
dwasse Jan 9, 2024
d75654b
Merge branch 'master' into feat/rfq-status update w/ working test [go…
trajan0x Jan 9, 2024
32db813
Fix: bump server start timeout
dwasse Jan 9, 2024
833fca4
Lint: disable depguard
dwasse Jan 9, 2024
acd3f44
Fix: check nil tx in TestListenForEvents
dwasse Jan 9, 2024
aa743d2
Cleanup: use itoa instead of sprintf
dwasse Jan 9, 2024
831c50d
[goreleaser] Bump timeout on server startup
dwasse Jan 9, 2024
1cca179
Fix: server_test
dwasse Jan 9, 2024
5ca7680
Merge branch 'master' into feat/rfq-status
dwasse Jan 9, 2024
f42f2ce
[goreleaser] Cleanup: lint
dwasse Jan 9, 2024
dbed1e3
WIP: add relayer api config
dwasse Jan 9, 2024
2c57477
WIP: add new chain pkg, add APIConfig section for relayer api
dwasse Jan 9, 2024
0d0615c
Cleanup: lint
dwasse Jan 10, 2024
4e4e4d4
Cleanup: APIConfig -> RelayerAPIConfig
dwasse Jan 10, 2024
9abe98c
Cleanup: APIServer -> QuoterAPIServer
dwasse Jan 10, 2024
49b6ce4
Fix: build
dwasse Jan 10, 2024
98dcf6b
Merge branch 'master' into feat/rfq-status
dwasse Jan 10, 2024
83aa7d9
Cleanup: lint
dwasse Jan 10, 2024
51f719d
Fix: build
dwasse Jan 10, 2024
497bdff
Cleanup: lint
dwasse Jan 10, 2024
6a297fb
[goreleaser] Merge branch 'master' into feat/rfq-status
dwasse Jan 10, 2024
5dbd12e
Cleanup: lint
dwasse Jan 10, 2024
5fa3598
[goreleaser] Remove redundant RelayerAPIConfig section
dwasse Jan 10, 2024
6beb0f7
Merge branch 'master' into feat/rfq-status [goreleaser]
trajan0x Jan 11, 2024
070766c
Feat: add MinGasToken to relayer config
dwasse Jan 11, 2024
ae13600
WIP: initial gas token bridging logic
dwasse Jan 11, 2024
5f08473
Merge branch 'master' into feat/rfq-eth
dwasse Jan 16, 2024
4fe8a8a
Feat: add TestGenerateQuotesForNativeToken
dwasse Jan 16, 2024
48eef61
Fix: GetMinGasToken doesn't error on unset val
dwasse Jan 16, 2024
98a1b9f
Feat: inventory manager registers native token metadata
dwasse Jan 16, 2024
78755ae
Feat: add TestETHtoETH integration test
dwasse Jan 16, 2024
ae965b4
Fix: TestUSDCtoUSDC
dwasse Jan 17, 2024
ee72578
Cleanup: lint
dwasse Jan 17, 2024
1fd187b
Cleanup: isNative -> isGasToken, remove unnecessary lines
dwasse Jan 17, 2024
fb09c14
Merge branch 'master' into feat/rfq-eth
dwasse Jan 27, 2024
883fbe1
Add `hasSufficientGas` check in quote processing (#1939)
dwasse Jan 27, 2024
c7425b6
[goreleaser]
dwasse Jan 27, 2024
df3cfb3
Fix: eth to eth integration test
dwasse Jan 29, 2024
baa8aef
[goreleaser] fix panic
trajan0x Jan 30, 2024
23429f9
update quoter/generated files
trajan0x Jan 30, 2024
059a279
Merge branch 'master' into feat/rfq-eth
trajan0x Jan 30, 2024
3460b8a
fix err assertion
trajan0x Jan 30, 2024
f687e5d
CI: lower individual timeout to 5m, increase retries
dwasse Jan 30, 2024
f78c023
Revert "CI: lower individual timeout to 5m, increase retries"
dwasse Jan 30, 2024
3a68063
Fix: Skip TestETHtoETH for now pending anvil fix
dwasse Jan 31, 2024
644d58c
Fix: check CI env var to run integration tests
dwasse Feb 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
117 changes: 114 additions & 3 deletions services/rfq/e2e/rfq_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
omnirpcClient "github.com/synapsecns/sanguine/services/omnirpc/client"
"github.com/synapsecns/sanguine/services/rfq/api/client"
"github.com/synapsecns/sanguine/services/rfq/contracts/fastbridge"
"github.com/synapsecns/sanguine/services/rfq/relayer/chain"
"github.com/synapsecns/sanguine/services/rfq/relayer/service"
"github.com/synapsecns/sanguine/services/rfq/testutil"
)
Expand Down Expand Up @@ -61,6 +62,11 @@ const (
func (i *IntegrationSuite) SetupTest() {
i.TestSuite.SetupTest()

// TODO: no need for this when anvil CI issues are fixed
if core.GetEnvBool("CI", false) {
return
}
Comment on lines +66 to +68
Copy link
Contributor

Choose a reason for hiding this comment

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

The conditional check to return early from SetupTest when running in a CI environment is a temporary workaround. Ensure that the underlying issues with Anvil in CI are resolved promptly to avoid skipping important setup steps in tests.


i.manager = testutil.NewDeployManager(i.T())
// TODO: consider jaeger
i.metrics = metrics.NewNullHandler()
Expand All @@ -70,7 +76,6 @@ func (i *IntegrationSuite) SetupTest() {
// setup the api server
i.setupQuoterAPI()
i.setupRelayer()

}

// getOtherBackend gets the backend that is not the current one. This is a helper
Expand All @@ -84,8 +89,10 @@ func (i *IntegrationSuite) getOtherBackend(backend backends.SimulatedTestBackend
return nil
}

// TODO:
func (i *IntegrationSuite) TestUSDCtoUSDC() {
if core.GetEnvBool("CI", false) {
i.T().Skip("skipping until anvil issues are fixed in CI")
}
Comment on lines +93 to +95
Copy link
Contributor

Choose a reason for hiding this comment

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

Skipping the TestUSDCtoUSDC test in CI environments due to Anvil issues is a temporary measure. It's crucial to address these issues to ensure comprehensive testing in CI pipelines.

// Before we do anything, we're going to mint ourselves some USDC on the destination chain.
// 100k should do.
i.manager.MintToAddress(i.GetTestContext(), i.destBackend, testutil.USDCType, i.relayerWallet.Address(), big.NewInt(100000))
Expand Down Expand Up @@ -136,7 +143,7 @@ func (i *IntegrationSuite) TestUSDCtoUSDC() {
SendChainGas: true,
DestToken: destUSDC.Address(),
OriginAmount: realWantAmount,
DestAmount: new(big.Int).Sub(realWantAmount, big.NewInt(1000)),
DestAmount: new(big.Int).Sub(realWantAmount, big.NewInt(10_000_000)),
Deadline: new(big.Int).SetInt64(time.Now().Add(time.Hour * 24).Unix()),
})
i.NoError(err)
Expand Down Expand Up @@ -191,3 +198,107 @@ func (i *IntegrationSuite) TestUSDCtoUSDC() {
return false
})
}

func (i *IntegrationSuite) TestETHtoETH() {
if core.GetEnvBool("CI", false) {
i.T().Skip("skipping until anvil issues are fixed in CI")
}
Comment on lines +203 to +205
Copy link
Contributor

Choose a reason for hiding this comment

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

Similarly, skipping the TestETHtoETH test in CI environments is not ideal. Work towards resolving the Anvil CI issues to enable full test coverage.

// Send ETH to the relayer on destination
const initialBalance = 10
i.destBackend.FundAccount(i.GetTestContext(), i.relayerWallet.Address(), *big.NewInt(initialBalance))

// let's give the user some money as well
const userWantAmount = 1
i.originBackend.FundAccount(i.GetTestContext(), i.userWallet.Address(), *big.NewInt(userWantAmount))

// non decimal adjusted user want amount
realWantAmount := new(big.Int).Mul(big.NewInt(userWantAmount), big.NewInt(1e18))

// now our friendly user is going to check the quote and send us some ETH on the origin chain.
i.Eventually(func() bool {
// first he's gonna check the quotes.
userAPIClient, err := client.NewAuthenticatedClient(metrics.Get(), i.apiServer, localsigner.NewSigner(i.userWallet.PrivateKey()))
i.NoError(err)

allQuotes, err := userAPIClient.GetAllQuotes()
i.NoError(err)

// let's figure out the amount of ETH we need
for _, quote := range allQuotes {
if common.HexToAddress(quote.DestTokenAddr) == chain.EthAddress {
destAmountBigInt, _ := new(big.Int).SetString(quote.DestAmount, 10)
if destAmountBigInt.Cmp(realWantAmount) > 0 {
// we found our quote!
// now we can move on
return true
}
}
}
return false
})

// now we can send the money
_, originFastBridge := i.manager.GetFastBridge(i.GetTestContext(), i.originBackend)
auth := i.originBackend.GetTxContext(i.GetTestContext(), i.userWallet.AddressPtr())
auth.TransactOpts.Value = realWantAmount
// we want 499 ETH for 500 requested within a day
tx, err := originFastBridge.Bridge(auth.TransactOpts, fastbridge.IFastBridgeBridgeParams{
DstChainId: uint32(i.destBackend.GetChainID()),
To: i.userWallet.Address(),
OriginToken: chain.EthAddress,
SendChainGas: true,
DestToken: chain.EthAddress,
OriginAmount: realWantAmount,
DestAmount: new(big.Int).Sub(realWantAmount, big.NewInt(1e17)),
Deadline: new(big.Int).SetInt64(time.Now().Add(time.Hour * 24).Unix()),
})
i.NoError(err)
i.originBackend.WaitForConfirmation(i.GetTestContext(), tx)

// TODO: this, but cleaner
anvilClient, err := anvil.Dial(i.GetTestContext(), i.originBackend.RPCAddress())
i.NoError(err)

go func() {
for {
select {
case <-i.GetTestContext().Done():
return
case <-time.After(time.Second * 4):
// increase time by 30 mintutes every second, should be enough to get us a fastish e2e test
// we don't need to worry about deadline since we're only doing this on origin
err = anvilClient.IncreaseTime(i.GetTestContext(), 60*30)
i.NoError(err)

// because can claim works on last block timestamp, we need to do something
err = anvilClient.Mine(i.GetTestContext(), 1)
i.NoError(err)
}
}
}()

// since relayer started w/ 0 ETH, once they're offering the inventory up on origin chain we know the workflow completed
i.Eventually(func() bool {
// first he's gonna check the quotes.
relayerAPIClient, err := client.NewAuthenticatedClient(metrics.Get(), i.apiServer, localsigner.NewSigner(i.relayerWallet.PrivateKey()))
i.NoError(err)

allQuotes, err := relayerAPIClient.GetAllQuotes()
i.NoError(err)

// let's figure out the amount of ETH we need
for _, quote := range allQuotes {
if common.HexToAddress(quote.DestTokenAddr) == chain.EthAddress && quote.DestChainID == originBackendChainID {
// we should now have some ETH on the origin chain since we claimed
// this should be offered up as inventory
destAmountBigInt, _ := new(big.Int).SetString(quote.DestAmount, 10)
if destAmountBigInt.Cmp(realWantAmount) > 0 {
// we found our quote!
// now we can move on
return true
}
}
}
return false
})
Comment on lines +202 to +303
Copy link
Contributor

Choose a reason for hiding this comment

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

The TestETHtoETH function correctly implements a test for Ethereum to Ethereum transactions, aligning with the PR's objective to introduce native Ethereum support. However, ensure that:

  • The hardcoded values such as initialBalance and userWantAmount are justified and documented.
  • Error handling is consistent, especially after external calls like i.destBackend.FundAccount and originFastBridge.Bridge.
  • The use of i.Eventually for asynchronous operations is appropriate, but consider adding comments to clarify the expectations and the rationale behind the chosen timeouts and intervals.
- // Send ETH to the relayer on destination
+ // Send 10 ETH to the relayer on the destination chain to simulate initial funding.
- // let's give the user some money as well
+ // Fund the user's wallet with 1 ETH on the origin chain for testing.
- // non decimal adjusted user want amount
+ // Convert the user's want amount to Wei for accurate transaction handling.
- // now we can send the money
+ // Execute the bridge transaction to send ETH from the user to the destination.

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.

Suggested change
func (i *IntegrationSuite) TestETHtoETH() {
if core.GetEnvBool("CI", false) {
i.T().Skip("skipping until anvil issues are fixed in CI")
}
// Send ETH to the relayer on destination
const initialBalance = 10
i.destBackend.FundAccount(i.GetTestContext(), i.relayerWallet.Address(), *big.NewInt(initialBalance))
// let's give the user some money as well
const userWantAmount = 1
i.originBackend.FundAccount(i.GetTestContext(), i.userWallet.Address(), *big.NewInt(userWantAmount))
// non decimal adjusted user want amount
realWantAmount := new(big.Int).Mul(big.NewInt(userWantAmount), big.NewInt(1e18))
// now our friendly user is going to check the quote and send us some ETH on the origin chain.
i.Eventually(func() bool {
// first he's gonna check the quotes.
userAPIClient, err := client.NewAuthenticatedClient(metrics.Get(), i.apiServer, localsigner.NewSigner(i.userWallet.PrivateKey()))
i.NoError(err)
allQuotes, err := userAPIClient.GetAllQuotes()
i.NoError(err)
// let's figure out the amount of ETH we need
for _, quote := range allQuotes {
if common.HexToAddress(quote.DestTokenAddr) == chain.EthAddress {
destAmountBigInt, _ := new(big.Int).SetString(quote.DestAmount, 10)
if destAmountBigInt.Cmp(realWantAmount) > 0 {
// we found our quote!
// now we can move on
return true
}
}
}
return false
})
// now we can send the money
_, originFastBridge := i.manager.GetFastBridge(i.GetTestContext(), i.originBackend)
auth := i.originBackend.GetTxContext(i.GetTestContext(), i.userWallet.AddressPtr())
auth.TransactOpts.Value = realWantAmount
// we want 499 ETH for 500 requested within a day
tx, err := originFastBridge.Bridge(auth.TransactOpts, fastbridge.IFastBridgeBridgeParams{
DstChainId: uint32(i.destBackend.GetChainID()),
To: i.userWallet.Address(),
OriginToken: chain.EthAddress,
SendChainGas: true,
DestToken: chain.EthAddress,
OriginAmount: realWantAmount,
DestAmount: new(big.Int).Sub(realWantAmount, big.NewInt(1e17)),
Deadline: new(big.Int).SetInt64(time.Now().Add(time.Hour * 24).Unix()),
})
i.NoError(err)
i.originBackend.WaitForConfirmation(i.GetTestContext(), tx)
// TODO: this, but cleaner
anvilClient, err := anvil.Dial(i.GetTestContext(), i.originBackend.RPCAddress())
i.NoError(err)
go func() {
for {
select {
case <-i.GetTestContext().Done():
return
case <-time.After(time.Second * 4):
// increase time by 30 mintutes every second, should be enough to get us a fastish e2e test
// we don't need to worry about deadline since we're only doing this on origin
err = anvilClient.IncreaseTime(i.GetTestContext(), 60*30)
i.NoError(err)
// because can claim works on last block timestamp, we need to do something
err = anvilClient.Mine(i.GetTestContext(), 1)
i.NoError(err)
}
}
}()
// since relayer started w/ 0 ETH, once they're offering the inventory up on origin chain we know the workflow completed
i.Eventually(func() bool {
// first he's gonna check the quotes.
relayerAPIClient, err := client.NewAuthenticatedClient(metrics.Get(), i.apiServer, localsigner.NewSigner(i.relayerWallet.PrivateKey()))
i.NoError(err)
allQuotes, err := relayerAPIClient.GetAllQuotes()
i.NoError(err)
// let's figure out the amount of ETH we need
for _, quote := range allQuotes {
if common.HexToAddress(quote.DestTokenAddr) == chain.EthAddress && quote.DestChainID == originBackendChainID {
// we should now have some ETH on the origin chain since we claimed
// this should be offered up as inventory
destAmountBigInt, _ := new(big.Int).SetString(quote.DestAmount, 10)
if destAmountBigInt.Cmp(realWantAmount) > 0 {
// we found our quote!
// now we can move on
return true
}
}
}
return false
})
func (i *IntegrationSuite) TestETHtoETH() {
if core.GetEnvBool("CI", false) {
i.T().Skip("skipping until anvil issues are fixed in CI")
}
// Send 10 ETH to the relayer on the destination chain to simulate initial funding.
const initialBalance = 10
i.destBackend.FundAccount(i.GetTestContext(), i.relayerWallet.Address(), *big.NewInt(initialBalance))
// Fund the user's wallet with 1 ETH on the origin chain for testing.
const userWantAmount = 1
i.originBackend.FundAccount(i.GetTestContext(), i.userWallet.Address(), *big.NewInt(userWantAmount))
// Convert the user's want amount to Wei for accurate transaction handling.
realWantAmount := new(big.Int).Mul(big.NewInt(userWantAmount), big.NewInt(1e18))
// now our friendly user is going to check the quote and send us some ETH on the origin chain.
i.Eventually(func() bool {
// first he's gonna check the quotes.
userAPIClient, err := client.NewAuthenticatedClient(metrics.Get(), i.apiServer, localsigner.NewSigner(i.userWallet.PrivateKey()))
i.NoError(err)
allQuotes, err := userAPIClient.GetAllQuotes()
i.NoError(err)
// let's figure out the amount of ETH we need
for _, quote := range allQuotes {
if common.HexToAddress(quote.DestTokenAddr) == chain.EthAddress {
destAmountBigInt, _ := new(big.Int).SetString(quote.DestAmount, 10)
if destAmountBigInt.Cmp(realWantAmount) > 0 {
// we found our quote!
// now we can move on
return true
}
}
}
return false
})
// Execute the bridge transaction to send ETH from the user to the destination.
_, originFastBridge := i.manager.GetFastBridge(i.GetTestContext(), i.originBackend)
auth := i.originBackend.GetTxContext(i.GetTestContext(), i.userWallet.AddressPtr())
auth.TransactOpts.Value = realWantAmount
// we want 499 ETH for 500 requested within a day
tx, err := originFastBridge.Bridge(auth.TransactOpts, fastbridge.IFastBridgeBridgeParams{
DstChainId: uint32(i.destBackend.GetChainID()),
To: i.userWallet.Address(),
OriginToken: chain.EthAddress,
SendChainGas: true,
DestToken: chain.EthAddress,
OriginAmount: realWantAmount,
DestAmount: new(big.Int).Sub(realWantAmount, big.NewInt(1e17)),
Deadline: new(big.Int).SetInt64(time.Now().Add(time.Hour * 24).Unix()),
})
i.NoError(err)
i.originBackend.WaitForConfirmation(i.GetTestContext(), tx)
// TODO: this, but cleaner
anvilClient, err := anvil.Dial(i.GetTestContext(), i.originBackend.RPCAddress())
i.NoError(err)
go func() {
for {
select {
case <-i.GetTestContext().Done():
return
case <-time.After(time.Second * 4):
// increase time by 30 mintutes every second, should be enough to get us a fastish e2e test
// we don't need to worry about deadline since we're only doing this on origin
err = anvilClient.IncreaseTime(i.GetTestContext(), 60*30)
i.NoError(err)
// because can claim works on last block timestamp, we need to do something
err = anvilClient.Mine(i.GetTestContext(), 1)
i.NoError(err)
}
}
}()
// since relayer started w/ 0 ETH, once they're offering the inventory up on origin chain we know the workflow completed
i.Eventually(func() bool {
// first he's gonna check the quotes.
relayerAPIClient, err := client.NewAuthenticatedClient(metrics.Get(), i.apiServer, localsigner.NewSigner(i.relayerWallet.PrivateKey()))
i.NoError(err)
allQuotes, err := relayerAPIClient.GetAllQuotes()
i.NoError(err)
// let's figure out the amount of ETH we need
for _, quote := range allQuotes {
if common.HexToAddress(quote.DestTokenAddr) == chain.EthAddress && quote.DestChainID == originBackendChainID {
// we should now have some ETH on the origin chain since we claimed
// this should be offered up as inventory
destAmountBigInt, _ := new(big.Int).SetString(quote.DestAmount, 10)
if destAmountBigInt.Cmp(realWantAmount) > 0 {
// we found our quote!
// now we can move on
return true
}
}
}
return false
})

}
16 changes: 13 additions & 3 deletions services/rfq/e2e/setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/synapsecns/sanguine/services/rfq/api/db/sql"
"github.com/synapsecns/sanguine/services/rfq/api/rest"
"github.com/synapsecns/sanguine/services/rfq/contracts/ierc20"
"github.com/synapsecns/sanguine/services/rfq/relayer/chain"
"github.com/synapsecns/sanguine/services/rfq/relayer/relconfig"
"github.com/synapsecns/sanguine/services/rfq/relayer/service"
"github.com/synapsecns/sanguine/services/rfq/testutil"
Expand Down Expand Up @@ -200,6 +201,7 @@ func (i *IntegrationSuite) setupRelayer() {
Confirmations: 0,
Tokens: map[string]relconfig.TokenConfig{
"ETH": {
Address: chain.EthAddress.String(),
PriceUSD: 2000,
Decimals: 18,
},
Expand All @@ -210,12 +212,13 @@ func (i *IntegrationSuite) setupRelayer() {
Bridge: i.manager.Get(i.GetTestContext(), i.destBackend, testutil.FastBridgeType).Address().String(),
Confirmations: 0,
Tokens: map[string]relconfig.TokenConfig{
"MATIC": {
PriceUSD: 0.5,
"ETH": {
Address: chain.EthAddress.String(),
PriceUSD: 2000,
Decimals: 18,
},
},
NativeToken: "MATIC",
NativeToken: "ETH",
},
},
OmniRPCURL: i.omniServer,
Comment on lines 212 to 224
Copy link
Contributor

Choose a reason for hiding this comment

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

📝 NOTE
This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [204-217]

The configuration for the "ETH" token within the setupRelayer function correctly sets the Address field using chain.EthAddress.String(), ensuring that the native Ethereum token is recognized and handled properly by the relayer. This change is crucial for supporting native Ethereum transactions without requiring wrapping into ERC-20 tokens. However, ensure that the PriceUSD and Decimals values are accurate and reflect the current standards for Ethereum. Additionally, consider externalizing these values to a configuration file or environment variables for easier updates and maintenance.

Expand Down Expand Up @@ -276,7 +279,14 @@ func (i *IntegrationSuite) setupRelayer() {
cfg.QuotableTokens[quotableTokenID] = append(cfg.QuotableTokens[quotableTokenID], fmt.Sprintf("%d-%s", otherBackend.GetChainID(), otherToken))
}
}
}

// Add ETH as quotable token from origin to destination
cfg.QuotableTokens[fmt.Sprintf("%d-%s", originBackendChainID, chain.EthAddress)] = []string{
fmt.Sprintf("%d-%s", destBackendChainID, chain.EthAddress),
}
cfg.QuotableTokens[fmt.Sprintf("%d-%s", destBackendChainID, chain.EthAddress)] = []string{
fmt.Sprintf("%d-%s", originBackendChainID, chain.EthAddress),
}

// TODO: good chance we wanna leave actually starting this up to the indiividual test.
Expand Down
5 changes: 4 additions & 1 deletion services/rfq/relayer/chain/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ func (c Chain) SubmitRelay(ctx context.Context, request reldb.QuoteRequest) (uin
gasAmount := big.NewInt(0)
var err error

if request.Transaction.SendChainGas {
// Check to see if ETH should be sent to destination
if IsGasToken(request.Transaction.DestToken) {
gasAmount = request.Transaction.DestAmount
} else if request.Transaction.SendChainGas {
gasAmount, err = c.Bridge.ChainGasAmount(&bind.CallOpts{Context: ctx})
if err != nil {
return 0, nil, fmt.Errorf("could not get chain gas amount: %w", err)
Expand Down
11 changes: 11 additions & 0 deletions services/rfq/relayer/chain/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package chain

import "github.com/ethereum/go-ethereum/common"

// EthAddress is the address of a chain's native gas token.
var EthAddress = common.HexToAddress("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE")

// IsGasToken returns true if the given token is the gas token.
func IsGasToken(token common.Address) bool {
return token == EthAddress
}