diff --git a/services/wallet/router/errors.go b/services/wallet/router/errors.go index fb859115d..145d90beb 100644 --- a/services/wallet/router/errors.go +++ b/services/wallet/router/errors.go @@ -31,4 +31,5 @@ var ( ErrNoBestRouteFound = &errors.ErrorResponse{Code: errors.ErrorCode("WR-023"), Details: "no best route found"} ErrCannotCheckBalance = &errors.ErrorResponse{Code: errors.ErrorCode("WR-024"), Details: "cannot check balance"} ErrCannotCheckLockedAmounts = &errors.ErrorResponse{Code: errors.ErrorCode("WR-025"), Details: "cannot check locked amounts"} + ErrLowAmountInForHopBridge = &errors.ErrorResponse{Code: errors.ErrorCode("WR-026"), Details: "bonder fee greater than estimated received, a higher amount is needed to cover fees"} ) diff --git a/services/wallet/router/router_v2.go b/services/wallet/router/router_v2.go index 24d61a34a..fb4d75f2b 100644 --- a/services/wallet/router/router_v2.go +++ b/services/wallet/router/router_v2.go @@ -1031,6 +1031,12 @@ func (r *Router) checkBalancesForTheBestRoute(ctx context.Context, bestRoute []* // check the best route for the required balances for _, path := range bestRoute { + if path.ProcessorName == pathprocessor.ProcessorBridgeHopName { + if path.TxBonderFees.ToInt().Cmp(path.AmountOut.ToInt()) > 0 { + return ErrLowAmountInForHopBridge + } + } + if path.requiredTokenBalance != nil && path.requiredTokenBalance.Cmp(pathprocessor.ZeroBigIntValue) > 0 { key := makeBalanceKey(path.FromChain.ChainID, path.FromToken.Symbol) if tokenBalance, ok := balanceMapCopy[key]; ok { diff --git a/services/wallet/router/router_v2_test_data.go b/services/wallet/router/router_v2_test_data.go index d859e4066..d53b86263 100644 --- a/services/wallet/router/router_v2_test_data.go +++ b/services/wallet/router/router_v2_test_data.go @@ -2585,6 +2585,46 @@ func getNormalTestParamsList() []normalTestParams { }, }, }, + { + name: "Bridge - Specific Single FromChain - Specific Single ToChain - Sending Small Amount", + input: &RouteInputParams{ + testnetMode: false, + Uuid: uuid.NewString(), + SendType: Bridge, + AddrFrom: common.HexToAddress("0x1"), + AddrTo: common.HexToAddress("0x2"), + AmountIn: (*hexutil.Big)(big.NewInt(0.01 * testAmount1USDC)), + TokenID: pathprocessor.UsdcSymbol, + DisabledFromChainIDs: []uint64{walletCommon.EthereumMainnet, walletCommon.OptimismMainnet}, + DisabledToChainIDs: []uint64{walletCommon.OptimismMainnet, walletCommon.ArbitrumMainnet}, + + testsMode: true, + testParams: &routerTestParams{ + tokenFrom: &token.Token{ + ChainID: 1, + Symbol: pathprocessor.UsdcSymbol, + Decimals: 6, + }, + tokenPrices: testTokenPrices, + baseFee: big.NewInt(testBaseFee), + suggestedFees: testSuggestedFees, + balanceMap: testBalanceMapPerChain, + estimationMap: testEstimationMap, + bonderFeeMap: testBbonderFeeMap, + approvalGasEstimation: testApprovalGasEstimation, + approvalL1Fee: testApprovalL1Fee, + }, + }, + expectedError: ErrLowAmountInForHopBridge, + expectedCandidates: []*PathV2{ + { + ProcessorName: pathprocessor.ProcessorBridgeHopName, + FromChain: &arbitrum, + ToChain: &mainnet, + ApprovalRequired: true, + }, + }, + }, } }