-
Notifications
You must be signed in to change notification settings - Fork 33
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-guard): v2 guard logic [SLT-387] #3324
Changes from all commits
44b4bfc
abfca0e
e678664
bdfb0a4
135f30e
43b63ac
bcb5b77
f8fe3e6
61175b3
88fcf4f
873659e
c664fa8
d4bd5f1
e1b452c
1982bee
1570986
a677ffe
4fe0be0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -165,7 +165,7 @@ | |||||||||||||||||
}) | ||||||||||||||||||
|
||||||||||||||||||
// now we can send the money | ||||||||||||||||||
_, originFastBridge := i.manager.GetFastBridge(i.GetTestContext(), i.originBackend) | ||||||||||||||||||
_, originFastBridge := i.manager.GetFastBridgeV2(i.GetTestContext(), i.originBackend) | ||||||||||||||||||
auth := i.originBackend.GetTxContext(i.GetTestContext(), i.userWallet.AddressPtr()) | ||||||||||||||||||
tx, err = originFastBridge.Bridge(auth.TransactOpts, fastbridgev2.IFastBridgeBridgeParams{ | ||||||||||||||||||
DstChainId: uint32(i.destBackend.GetChainID()), | ||||||||||||||||||
|
@@ -318,7 +318,7 @@ | |||||||||||||||||
}) | ||||||||||||||||||
|
||||||||||||||||||
// now we can send the money | ||||||||||||||||||
_, originFastBridge := i.manager.GetFastBridge(i.GetTestContext(), i.originBackend) | ||||||||||||||||||
_, originFastBridge := i.manager.GetFastBridgeV2(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 | ||||||||||||||||||
|
@@ -458,7 +458,7 @@ | |||||||||||||||||
}) | ||||||||||||||||||
|
||||||||||||||||||
// now we can send the money | ||||||||||||||||||
_, originFastBridge := i.manager.GetFastBridge(i.GetTestContext(), i.originBackend) | ||||||||||||||||||
_, originFastBridge := i.manager.GetFastBridgeV2(i.GetTestContext(), i.originBackend) | ||||||||||||||||||
_, destRecipient := i.manager.GetRecipientMock(i.GetTestContext(), i.destBackend) | ||||||||||||||||||
auth := i.originBackend.GetTxContext(i.GetTestContext(), i.userWallet.AddressPtr()) | ||||||||||||||||||
params := fastbridgev2.IFastBridgeBridgeParams{ | ||||||||||||||||||
|
@@ -511,7 +511,7 @@ | |||||||||||||||||
}) | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
func (i *IntegrationSuite) TestDispute() { | ||||||||||||||||||
func (i *IntegrationSuite) TestDisputeV1() { | ||||||||||||||||||
// start the guard | ||||||||||||||||||
go func() { | ||||||||||||||||||
_ = i.guard.Start(i.GetTestContext()) | ||||||||||||||||||
|
@@ -551,8 +551,105 @@ | |||||||||||||||||
_, originFastBridge := i.manager.GetFastBridge(i.GetTestContext(), i.originBackend) | ||||||||||||||||||
auth := i.originBackend.GetTxContext(i.GetTestContext(), i.userWallet.AddressPtr()) | ||||||||||||||||||
// we want 499 usdc for 500 requested within a day | ||||||||||||||||||
tx, err = originFastBridge.Bridge(auth.TransactOpts, fastbridge.IFastBridgeBridgeParams{ | ||||||||||||||||||
DstChainId: uint32(i.destBackend.GetChainID()), | ||||||||||||||||||
Sender: i.userWallet.Address(), | ||||||||||||||||||
To: i.userWallet.Address(), | ||||||||||||||||||
OriginToken: originUSDC.Address(), | ||||||||||||||||||
SendChainGas: true, | ||||||||||||||||||
DestToken: destUSDC.Address(), | ||||||||||||||||||
OriginAmount: realRFQAmount, | ||||||||||||||||||
DestAmount: new(big.Int).Sub(realRFQAmount, big.NewInt(10_000_000)), | ||||||||||||||||||
Deadline: new(big.Int).SetInt64(time.Now().Add(time.Hour * 24).Unix()), | ||||||||||||||||||
}) | ||||||||||||||||||
i.NoError(err) | ||||||||||||||||||
i.originBackend.WaitForConfirmation(i.GetTestContext(), tx) | ||||||||||||||||||
|
||||||||||||||||||
// fetch the txid and raw request | ||||||||||||||||||
var txID [32]byte | ||||||||||||||||||
var rawRequest []byte | ||||||||||||||||||
parser, err := fastbridge.NewParser(originFastBridge.Address()) | ||||||||||||||||||
i.NoError(err) | ||||||||||||||||||
i.Eventually(func() bool { | ||||||||||||||||||
receipt, err := i.originBackend.TransactionReceipt(i.GetTestContext(), tx.Hash()) | ||||||||||||||||||
i.NoError(err) | ||||||||||||||||||
for _, log := range receipt.Logs { | ||||||||||||||||||
_, parsedEvent, ok := parser.ParseEvent(*log) | ||||||||||||||||||
if !ok { | ||||||||||||||||||
continue | ||||||||||||||||||
} | ||||||||||||||||||
event, ok := parsedEvent.(*fastbridge.FastBridgeBridgeRequested) | ||||||||||||||||||
if ok { | ||||||||||||||||||
txID = event.TransactionId | ||||||||||||||||||
rawRequest = event.Request | ||||||||||||||||||
return true | ||||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
return false | ||||||||||||||||||
}) | ||||||||||||||||||
|
||||||||||||||||||
// call prove() from the relayer wallet before relay actually occurred on dest | ||||||||||||||||||
relayerAuth := i.originBackend.GetTxContext(i.GetTestContext(), i.relayerWallet.AddressPtr()) | ||||||||||||||||||
fakeHash := common.HexToHash("0xdeadbeef") | ||||||||||||||||||
tx, err = originFastBridge.Prove(relayerAuth.TransactOpts, rawRequest, fakeHash) | ||||||||||||||||||
i.NoError(err) | ||||||||||||||||||
i.originBackend.WaitForConfirmation(i.GetTestContext(), tx) | ||||||||||||||||||
|
||||||||||||||||||
// verify that the guard calls Dispute() | ||||||||||||||||||
i.Eventually(func() bool { | ||||||||||||||||||
results, err := i.guardStore.GetPendingProvensByStatus(i.GetTestContext(), guarddb.Disputed) | ||||||||||||||||||
i.NoError(err) | ||||||||||||||||||
if len(results) != 1 { | ||||||||||||||||||
return false | ||||||||||||||||||
} | ||||||||||||||||||
result, err := i.guardStore.GetPendingProvenByID(i.GetTestContext(), txID) | ||||||||||||||||||
i.NoError(err) | ||||||||||||||||||
return result.TxHash == fakeHash && result.Status == guarddb.Disputed && result.TransactionID == txID | ||||||||||||||||||
}) | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
func (i *IntegrationSuite) TestDisputeV2() { | ||||||||||||||||||
// start the guard | ||||||||||||||||||
go func() { | ||||||||||||||||||
_ = i.guard.Start(i.GetTestContext()) | ||||||||||||||||||
}() | ||||||||||||||||||
|
||||||||||||||||||
// load token contracts | ||||||||||||||||||
const startAmount = 1000 | ||||||||||||||||||
const rfqAmount = 900 | ||||||||||||||||||
opts := i.destBackend.GetTxContext(i.GetTestContext(), nil) | ||||||||||||||||||
destUSDC, destUSDCHandle := i.cctpDeployManager.GetMockMintBurnTokenType(i.GetTestContext(), i.destBackend) | ||||||||||||||||||
realStartAmount, err := testutil.AdjustAmount(i.GetTestContext(), big.NewInt(startAmount), destUSDC.ContractHandle()) | ||||||||||||||||||
i.NoError(err) | ||||||||||||||||||
realRFQAmount, err := testutil.AdjustAmount(i.GetTestContext(), big.NewInt(rfqAmount), destUSDC.ContractHandle()) | ||||||||||||||||||
i.NoError(err) | ||||||||||||||||||
|
||||||||||||||||||
// add initial usdc to relayer on destination | ||||||||||||||||||
tx, err := destUSDCHandle.MintPublic(opts.TransactOpts, i.relayerWallet.Address(), realStartAmount) | ||||||||||||||||||
i.Nil(err) | ||||||||||||||||||
i.destBackend.WaitForConfirmation(i.GetTestContext(), tx) | ||||||||||||||||||
i.Approve(i.destBackend, destUSDC, i.relayerWallet) | ||||||||||||||||||
|
||||||||||||||||||
// add initial USDC to relayer on origin | ||||||||||||||||||
optsOrigin := i.originBackend.GetTxContext(i.GetTestContext(), nil) | ||||||||||||||||||
originUSDC, originUSDCHandle := i.cctpDeployManager.GetMockMintBurnTokenType(i.GetTestContext(), i.originBackend) | ||||||||||||||||||
tx, err = originUSDCHandle.MintPublic(optsOrigin.TransactOpts, i.relayerWallet.Address(), realStartAmount) | ||||||||||||||||||
i.Nil(err) | ||||||||||||||||||
i.originBackend.WaitForConfirmation(i.GetTestContext(), tx) | ||||||||||||||||||
i.Approve(i.originBackend, originUSDC, i.relayerWallet) | ||||||||||||||||||
|
||||||||||||||||||
// add initial USDC to user on origin | ||||||||||||||||||
tx, err = originUSDCHandle.MintPublic(optsOrigin.TransactOpts, i.userWallet.Address(), realRFQAmount) | ||||||||||||||||||
i.Nil(err) | ||||||||||||||||||
i.originBackend.WaitForConfirmation(i.GetTestContext(), tx) | ||||||||||||||||||
i.Approve(i.originBackend, originUSDC, i.userWallet) | ||||||||||||||||||
|
||||||||||||||||||
// now we can send the money | ||||||||||||||||||
_, originFastBridge := i.manager.GetFastBridgeV2(i.GetTestContext(), i.originBackend) | ||||||||||||||||||
auth := i.originBackend.GetTxContext(i.GetTestContext(), i.userWallet.AddressPtr()) | ||||||||||||||||||
// we want 499 usdc for 500 requested within a day | ||||||||||||||||||
tx, err = originFastBridge.Bridge(auth.TransactOpts, fastbridgev2.IFastBridgeBridgeParams{ | ||||||||||||||||||
DstChainId: uint32(i.destBackend.GetChainID()), | ||||||||||||||||||
Sender: i.userWallet.Address(), | ||||||||||||||||||
To: i.userWallet.Address(), | ||||||||||||||||||
OriginToken: originUSDC.Address(), | ||||||||||||||||||
|
@@ -670,7 +767,7 @@ | |||||||||||||||||
return false | ||||||||||||||||||
}) | ||||||||||||||||||
|
||||||||||||||||||
_, originFastBridge := i.manager.GetFastBridge(i.GetTestContext(), i.originBackend) | ||||||||||||||||||
_, originFastBridge := i.manager.GetFastBridgeV2(i.GetTestContext(), i.originBackend) | ||||||||||||||||||
auth := i.originBackend.GetTxContext(i.GetTestContext(), i.userWallet.AddressPtr()) | ||||||||||||||||||
parser, err := fastbridge.NewParser(originFastBridge.Address()) | ||||||||||||||||||
i.NoError(err) | ||||||||||||||||||
Comment on lines
+770
to
773
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Potential mismatch in parser usage: using In Apply this diff to correct the parser: - parser, err := fastbridge.NewParser(originFastBridge.Address())
+ parser, err := fastbridgev2.NewParser(originFastBridge.Address()) 📝 Committable suggestion
Suggested change
|
||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -63,6 +63,10 @@ | |||||
originBackendChainID: i.manager.Get(i.GetTestContext(), i.originBackend, testutil.FastBridgeType).Address().String(), | ||||||
destBackendChainID: i.manager.Get(i.GetTestContext(), i.destBackend, testutil.FastBridgeType).Address().String(), | ||||||
}, | ||||||
FastBridgeContractsV2: map[uint32]string{ | ||||||
originBackendChainID: i.manager.Get(i.GetTestContext(), i.originBackend, testutil.FastBridgeV2Type).Address().String(), | ||||||
destBackendChainID: i.manager.Get(i.GetTestContext(), i.destBackend, testutil.FastBridgeV2Type).Address().String(), | ||||||
}, | ||||||
Port: strconv.Itoa(apiPort), | ||||||
} | ||||||
api, err := rest.NewAPI(i.GetTestContext(), apiCfg, i.metrics, i.omniClient, apiStore) | ||||||
|
@@ -147,7 +151,7 @@ | |||||
// but this way we can do something while we're waiting for the other backend to startup. | ||||||
// no need to wait for these to deploy since they can happen in background as soon as the backend is up. | ||||||
predeployTokens := []contracts.ContractType{testutil.DAIType, testutil.USDTType, testutil.WETH9Type} | ||||||
predeploys := append(predeployTokens, testutil.FastBridgeType) | ||||||
predeploys := append(predeployTokens, testutil.FastBridgeV2Type) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure both FastBridge versions are deployed in Currently, only Apply this diff to include both versions: predeployTokens := []contracts.ContractType{testutil.DAIType, testutil.USDTType, testutil.WETH9Type}
- predeploys := append(predeployTokens, testutil.FastBridgeV2Type)
+ predeploys := append(predeployTokens, testutil.FastBridgeType, testutil.FastBridgeV2Type) 📝 Committable suggestion
Suggested change
|
||||||
slices.Reverse(predeploys) // return fast bridge first | ||||||
|
||||||
ethAmount := *new(big.Int).Mul(big.NewInt(params.Ether), big.NewInt(10)) | ||||||
|
@@ -267,15 +271,41 @@ | |||||
|
||||||
erc20, err := ierc20.NewIERC20(token.Address(), backend) | ||||||
i.Require().NoError(err, "Failed to get erc20") | ||||||
_, fastBridge := i.manager.GetFastBridge(i.GetTestContext(), backend) | ||||||
allowance, err := erc20.Allowance(&bind.CallOpts{Context: i.GetTestContext()}, user.Address(), fastBridge.Address()) | ||||||
|
||||||
// approve fastbridgev1 | ||||||
_, fastBridgeV1 := i.manager.GetFastBridge(i.GetTestContext(), backend) | ||||||
allowance, err := erc20.Allowance(&bind.CallOpts{Context: i.GetTestContext()}, user.Address(), fastBridgeV1.Address()) | ||||||
i.Require().NoError(err, "Failed to get allowance") | ||||||
|
||||||
if allowance.Cmp(big.NewInt(0)) == 0 { | ||||||
err = retry.WithBackoff(i.GetTestContext(), func(ctx context.Context) error { | ||||||
txOpts := backend.GetTxContext(ctx, user.AddressPtr()) | ||||||
tx, err := erc20.Approve(txOpts.TransactOpts, fastBridgeV1.Address(), core.CopyBigInt(abi.MaxUint256)) | ||||||
if err != nil { | ||||||
return fmt.Errorf("failed to approve: %w", err) | ||||||
} | ||||||
backend.WaitForConfirmation(ctx, tx) | ||||||
return nil | ||||||
}) | ||||||
i.Require().NoError(err, "Failed to approve") | ||||||
} | ||||||
|
||||||
// approve fastbridgev2 | ||||||
_, fastBridgeV2 := i.manager.GetFastBridgeV2(i.GetTestContext(), backend) | ||||||
allowance, err = erc20.Allowance(&bind.CallOpts{Context: i.GetTestContext()}, user.Address(), fastBridgeV2.Address()) | ||||||
i.Require().NoError(err, "Failed to get allowance") | ||||||
|
||||||
if allowance.Cmp(big.NewInt(0)) == 0 { | ||||||
txOpts := backend.GetTxContext(i.GetTestContext(), user.AddressPtr()) | ||||||
tx, err := erc20.Approve(txOpts.TransactOpts, fastBridge.Address(), core.CopyBigInt(abi.MaxUint256)) | ||||||
err = retry.WithBackoff(i.GetTestContext(), func(ctx context.Context) error { | ||||||
txOpts := backend.GetTxContext(ctx, user.AddressPtr()) | ||||||
tx, err := erc20.Approve(txOpts.TransactOpts, fastBridgeV2.Address(), core.CopyBigInt(abi.MaxUint256)) | ||||||
if err != nil { | ||||||
return fmt.Errorf("failed to approve: %w", err) | ||||||
} | ||||||
backend.WaitForConfirmation(ctx, tx) | ||||||
return nil | ||||||
}) | ||||||
i.Require().NoError(err, "Failed to approve") | ||||||
backend.WaitForConfirmation(i.GetTestContext(), tx) | ||||||
} | ||||||
} | ||||||
|
||||||
|
@@ -286,11 +316,14 @@ | |||||
dsn := filet.TmpDir(i.T(), "") | ||||||
cctpContractOrigin, _ := i.cctpDeployManager.GetSynapseCCTP(i.GetTestContext(), i.originBackend) | ||||||
cctpContractDest, _ := i.cctpDeployManager.GetSynapseCCTP(i.GetTestContext(), i.destBackend) | ||||||
rfqAddressV1Origin := i.manager.Get(i.GetTestContext(), i.originBackend, testutil.FastBridgeType).Address().String() | ||||||
rfqAddressV1Dest := i.manager.Get(i.GetTestContext(), i.destBackend, testutil.FastBridgeType).Address().String() | ||||||
return relconfig.Config{ | ||||||
// generated ex-post facto | ||||||
Chains: map[int]relconfig.ChainConfig{ | ||||||
originBackendChainID: { | ||||||
RFQAddress: i.manager.Get(i.GetTestContext(), i.originBackend, testutil.FastBridgeType).Address().String(), | ||||||
RFQAddress: i.manager.Get(i.GetTestContext(), i.originBackend, testutil.FastBridgeV2Type).Address().String(), | ||||||
RFQAddressV1: &rfqAddressV1Origin, | ||||||
RebalanceConfigs: relconfig.RebalanceConfigs{ | ||||||
Synapse: &relconfig.SynapseCCTPRebalanceConfig{ | ||||||
SynapseCCTPAddress: cctpContractOrigin.Address().Hex(), | ||||||
|
@@ -307,7 +340,8 @@ | |||||
NativeToken: "ETH", | ||||||
}, | ||||||
destBackendChainID: { | ||||||
RFQAddress: i.manager.Get(i.GetTestContext(), i.destBackend, testutil.FastBridgeType).Address().String(), | ||||||
RFQAddress: i.manager.Get(i.GetTestContext(), i.destBackend, testutil.FastBridgeV2Type).Address().String(), | ||||||
RFQAddressV1: &rfqAddressV1Dest, | ||||||
RebalanceConfigs: relconfig.RebalanceConfigs{ | ||||||
Synapse: &relconfig.SynapseCCTPRebalanceConfig{ | ||||||
SynapseCCTPAddress: cctpContractDest.Address().Hex(), | ||||||
|
@@ -362,26 +396,38 @@ | |||||
defer wg.Done() | ||||||
|
||||||
err := retry.WithBackoff(i.GetTestContext(), func(ctx context.Context) error { | ||||||
metadata, rfqContract := i.manager.GetFastBridge(i.GetTestContext(), backend) | ||||||
metadataV1, rfqContractV1 := i.manager.GetFastBridge(i.GetTestContext(), backend) | ||||||
txContextV1 := backend.GetTxContext(i.GetTestContext(), metadataV1.OwnerPtr()) | ||||||
|
||||||
txContext := backend.GetTxContext(i.GetTestContext(), metadata.OwnerPtr()) | ||||||
proverRole, err := rfqContract.PROVERROLE(&bind.CallOpts{Context: i.GetTestContext()}) | ||||||
relayerRole, err := rfqContractV1.RELAYERROLE(&bind.CallOpts{Context: i.GetTestContext()}) | ||||||
proverRole, err := rfqContractV1.RELAYERROLE(&bind.CallOpts{Context: i.GetTestContext()}) | ||||||
if err != nil { | ||||||
return fmt.Errorf("could not get prover role: %w", err) | ||||||
} | ||||||
tx, err := rfqContractV1.GrantRole(txContextV1.TransactOpts, relayerRole, i.relayerWallet.Address()) | ||||||
if err != nil { | ||||||
return fmt.Errorf("could not grant relayer role: %w", err) | ||||||
} | ||||||
backend.WaitForConfirmation(i.GetTestContext(), tx) | ||||||
|
||||||
metadataV2, rfqContractV2 := i.manager.GetFastBridgeV2(i.GetTestContext(), backend) | ||||||
txContextV2 := backend.GetTxContext(i.GetTestContext(), metadataV2.OwnerPtr()) | ||||||
|
||||||
tx, err := rfqContract.GrantRole(txContext.TransactOpts, proverRole, i.relayerWallet.Address()) | ||||||
proverRole, err = rfqContractV2.PROVERROLE(&bind.CallOpts{Context: i.GetTestContext()}) | ||||||
if err != nil { | ||||||
return fmt.Errorf("could not get prover role: %w", err) | ||||||
} | ||||||
tx, err = rfqContractV2.GrantRole(txContextV2.TransactOpts, proverRole, i.relayerWallet.Address()) | ||||||
if err != nil { | ||||||
return fmt.Errorf("could not grant prover role: %w", err) | ||||||
} | ||||||
backend.WaitForConfirmation(i.GetTestContext(), tx) | ||||||
|
||||||
quoterRole, err := rfqContract.QUOTERROLE(&bind.CallOpts{Context: i.GetTestContext()}) | ||||||
quoterRole, err := rfqContractV2.QUOTERROLE(&bind.CallOpts{Context: i.GetTestContext()}) | ||||||
if err != nil { | ||||||
return fmt.Errorf("could not get quoter role: %w", err) | ||||||
} | ||||||
|
||||||
tx, err = rfqContract.GrantRole(txContext.TransactOpts, quoterRole, i.relayerWallet.Address()) | ||||||
tx, err = rfqContractV2.GrantRole(txContextV2.TransactOpts, quoterRole, i.relayerWallet.Address()) | ||||||
if err != nil { | ||||||
return fmt.Errorf("could not grant quoter role: %w", err) | ||||||
} | ||||||
|
@@ -488,13 +534,24 @@ | |||||
go func(backend backends.SimulatedTestBackend) { | ||||||
defer wg.Done() | ||||||
|
||||||
metadata, rfqContract := i.manager.GetFastBridge(i.GetTestContext(), backend) | ||||||
metadataV1, rfqContractV1 := i.manager.GetFastBridge(i.GetTestContext(), backend) | ||||||
|
||||||
txContext := backend.GetTxContext(i.GetTestContext(), metadataV1.OwnerPtr()) | ||||||
guardRole, err := rfqContractV1.GUARDROLE(&bind.CallOpts{Context: i.GetTestContext()}) | ||||||
i.NoError(err) | ||||||
|
||||||
tx, err := rfqContractV1.GrantRole(txContext.TransactOpts, guardRole, i.guardWallet.Address()) | ||||||
i.NoError(err) | ||||||
|
||||||
backend.WaitForConfirmation(i.GetTestContext(), tx) | ||||||
|
||||||
metadataV2, rfqContractV2 := i.manager.GetFastBridgeV2(i.GetTestContext(), backend) | ||||||
|
||||||
txContext := backend.GetTxContext(i.GetTestContext(), metadata.OwnerPtr()) | ||||||
guardRole, err := rfqContract.GUARDROLE(&bind.CallOpts{Context: i.GetTestContext()}) | ||||||
txContext = backend.GetTxContext(i.GetTestContext(), metadataV2.OwnerPtr()) | ||||||
guardRole, err = rfqContractV2.GUARDROLE(&bind.CallOpts{Context: i.GetTestContext()}) | ||||||
i.NoError(err) | ||||||
|
||||||
tx, err := rfqContract.GrantRole(txContext.TransactOpts, guardRole, i.guardWallet.Address()) | ||||||
tx, err = rfqContractV2.GrantRole(txContext.TransactOpts, guardRole, i.guardWallet.Address()) | ||||||
i.NoError(err) | ||||||
|
||||||
backend.WaitForConfirmation(i.GetTestContext(), tx) | ||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -34,7 +34,9 @@ type Config struct { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// ChainConfig represents the configuration for a chain. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type ChainConfig struct { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Bridge is the rfq bridge contract address. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// RFQAddressV1 is the legacy V1 rfq bridge contract address. OPTIONAL. Only populate if also guarding a deprecated V1 contract. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RFQAddressV1 *string `yaml:"rfq_address_v1"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// RFQAddress is the current/latest rfq bridge contract address. REQUIRED. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RFQAddress string `yaml:"rfq_address"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Confirmations is the number of required confirmations. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Confirmations uint64 `yaml:"confirmations"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -66,12 +68,19 @@ func LoadConfig(path string) (config Config, err error) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Validate validates the config. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
func (c Config) Validate() (err error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for chainID := range c.Chains { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
addr, err := c.GetRFQAddress(chainID) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
addrV1, err := c.GetRFQAddressV1(chainID) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return fmt.Errorf("could not get rfq address: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return fmt.Errorf("could not get v1 rfq address: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if !common.IsHexAddress(addr) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return fmt.Errorf("invalid rfq address: %s", addr) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if addrV1 != nil && !common.IsHexAddress(*addrV1) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return fmt.Errorf("invalid rfq v1 address: %s", *addrV1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
addrV2, err := c.GetRFQAddressV2(chainID) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return fmt.Errorf("could not get v2 rfq address: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if !common.IsHexAddress(addrV2) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return fmt.Errorf("invalid rfq v2 address: %s", addrV2) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+71
to
+83
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add test coverage for address validation logic The validation logic for both V1 and V2 addresses lacks test coverage. Consider adding test cases for:
Would you like me to help create comprehensive test cases for the validation logic? Additionally, consider making error messages more descriptive: -return fmt.Errorf("could not get v1 rfq address: %w", err)
+return fmt.Errorf("failed to retrieve RFQ V1 address for chain %d: %w", chainID, err)
-return fmt.Errorf("invalid rfq v1 address: %s", *addrV1)
+return fmt.Errorf("invalid RFQ V1 address format for chain %d: %s", chainID, *addrV1)
-return fmt.Errorf("could not get v2 rfq address: %w", err)
+return fmt.Errorf("failed to retrieve RFQ V2 address for chain %d: %w", chainID, err)
-return fmt.Errorf("invalid rfq v2 address: %s", addrV2)
+return fmt.Errorf("invalid RFQ V2 address format for chain %d: %s", chainID, addrV2) 📝 Committable suggestion
Suggested change
🧰 Tools🪛 GitHub Check: codecov/patch[warning] 71-71: services/rfq/guard/guardconfig/config.go#L71 [warning] 75-75: services/rfq/guard/guardconfig/config.go#L75 [warning] 77-79: services/rfq/guard/guardconfig/config.go#L77-L79 [warning] 81-82: services/rfq/guard/guardconfig/config.go#L81-L82 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -83,11 +92,20 @@ func (c Config) GetChains() map[int]ChainConfig { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return c.Chains | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// GetRFQAddress returns the RFQ address for the given chain. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
func (c Config) GetRFQAddress(chainID int) (string, error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// GetRFQAddressV1 returns the RFQ address for the given chain. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
func (c Config) GetRFQAddressV1(chainID int) (*string, error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
chainCfg, ok := c.Chains[chainID] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if !ok { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return nil, fmt.Errorf("v1 chain config not found for chain %d", chainID) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return chainCfg.RFQAddressV1, nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// GetRFQAddressV2 returns the RFQ address for the given chain. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
func (c Config) GetRFQAddressV2(chainID int) (string, error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
chainCfg, ok := c.Chains[chainID] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if !ok { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return "", fmt.Errorf("chain config not found for chain %d", chainID) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return "", fmt.Errorf("v2 chain config not found for chain %d", chainID) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return chainCfg.RFQAddress, nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -115,6 +133,7 @@ func NewGuardConfigFromRelayer(relayerCfg relconfig.Config) Config { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for chainID, chainCfg := range relayerCfg.GetChains() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cfg.Chains[chainID] = ChainConfig{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RFQAddressV1: chainCfg.RFQAddressV1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RFQAddress: chainCfg.RFQAddress, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Confirmations: chainCfg.FinalityConfirmations, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+136
to
139
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add test coverage for guard config creation The NewGuardConfigFromRelayer function's handling of the new RFQAddressV1 field is untested. Consider adding test cases to verify:
Would you like me to help create test cases for the config creation logic? 🧰 Tools🪛 GitHub Check: codecov/patch[warning] 136-136: services/rfq/guard/guardconfig/config.go#L136 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential mismatch in parser usage: using
fastbridge.NewParser
with FastBridgeV2In
TestDisputeV2
, you're creating a parser withfastbridge.NewParser(originFastBridge.Address())
, butoriginFastBridge
is a FastBridgeV2 instance. This may lead to incorrect event parsing. Consider usingfastbridgev2.NewParser
instead to match the contract version.Apply this diff to use the correct parser:
📝 Committable suggestion