chore_: map insufficient funds error
This commit maps this kind of errors `status-proxy-0.error: failed with 50011064 gas: insufficient funds for gas * price + value: address 0x4eeB09cf0076F840b38511D808464eE48efD4305 have 0 want 10000000000000` to this form: `status-proxy-0.error: failed with 50011064 gas: insufficient funds for gas * price + value: address 0x4eeB09cf0076F840b38511D808464eE48efD4305` which means that we don't want to display to a user details of how much they have and how much is needed for fees, cause those data are very often misleading, referring mostly to "how much user has". New error added in case there is no positive balances across all enabled chains.
This commit is contained in:
parent
85fba77b7d
commit
9b9a91f654
|
@ -27,6 +27,28 @@ func IsErrorResponse(err error) bool {
|
|||
return ok
|
||||
}
|
||||
|
||||
// ErrorCodeFromError returns the ErrorCode from an error.
|
||||
func ErrorCodeFromError(err error) ErrorCode {
|
||||
if err == nil {
|
||||
return GenericErrorCode
|
||||
}
|
||||
if errResp, ok := err.(*ErrorResponse); ok {
|
||||
return errResp.Code
|
||||
}
|
||||
return GenericErrorCode
|
||||
}
|
||||
|
||||
// DetailsFromError returns the details from an error.
|
||||
func DetailsFromError(err error) string {
|
||||
if err == nil {
|
||||
return ""
|
||||
}
|
||||
if errResp, ok := err.(*ErrorResponse); ok {
|
||||
return errResp.Details
|
||||
}
|
||||
return err.Error()
|
||||
}
|
||||
|
||||
// CreateErrorResponseFromError creates an ErrorResponse from a generic error.
|
||||
func CreateErrorResponseFromError(err error) error {
|
||||
if err == nil {
|
||||
|
|
|
@ -32,4 +32,5 @@ var (
|
|||
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"}
|
||||
ErrNoPositiveBalance = &errors.ErrorResponse{Code: errors.ErrorCode("WR-027"), Details: "no positive balance"}
|
||||
)
|
||||
|
|
|
@ -56,8 +56,13 @@ type ProcessorInputParams struct {
|
|||
|
||||
// for testing purposes
|
||||
TestsMode bool
|
||||
TestEstimationMap map[string]uint64 // [brifge-name, estimated-value]
|
||||
TestBonderFeeMap map[string]*big.Int // [token-symbol, bonder-fee]
|
||||
TestEstimationMap map[string]Estimation // [bridge-name, estimation]
|
||||
TestBonderFeeMap map[string]*big.Int // [token-symbol, bonder-fee]
|
||||
TestApprovalGasEstimation uint64
|
||||
TestApprovalL1Fee uint64
|
||||
}
|
||||
|
||||
type Estimation struct {
|
||||
Value uint64
|
||||
Err error
|
||||
}
|
||||
|
|
|
@ -236,7 +236,7 @@ func (s *CelerBridgeProcessor) EstimateGas(params ProcessorInputParams) (uint64,
|
|||
if params.TestsMode {
|
||||
if params.TestEstimationMap != nil {
|
||||
if val, ok := params.TestEstimationMap[s.Name()]; ok {
|
||||
return val, nil
|
||||
return val.Value, val.Err
|
||||
}
|
||||
}
|
||||
return 0, ErrNoEstimationFound
|
||||
|
|
|
@ -228,7 +228,7 @@ func (h *HopBridgeProcessor) EstimateGas(params ProcessorInputParams) (uint64, e
|
|||
if params.TestsMode {
|
||||
if params.TestEstimationMap != nil {
|
||||
if val, ok := params.TestEstimationMap[h.Name()]; ok {
|
||||
return val, nil
|
||||
return val.Value, val.Err
|
||||
}
|
||||
}
|
||||
return 0, ErrNoEstimationFound
|
||||
|
|
|
@ -65,7 +65,7 @@ func (s *ENSPublicKeyProcessor) EstimateGas(params ProcessorInputParams) (uint64
|
|||
if params.TestsMode {
|
||||
if params.TestEstimationMap != nil {
|
||||
if val, ok := params.TestEstimationMap[s.Name()]; ok {
|
||||
return val, nil
|
||||
return val.Value, val.Err
|
||||
}
|
||||
}
|
||||
return 0, ErrNoEstimationFound
|
||||
|
|
|
@ -101,7 +101,7 @@ func (s *ENSRegisterProcessor) EstimateGas(params ProcessorInputParams) (uint64,
|
|||
if params.TestsMode {
|
||||
if params.TestEstimationMap != nil {
|
||||
if val, ok := params.TestEstimationMap[s.Name()]; ok {
|
||||
return val, nil
|
||||
return val.Value, val.Err
|
||||
}
|
||||
}
|
||||
return 0, ErrNoEstimationFound
|
||||
|
|
|
@ -64,7 +64,7 @@ func (s *ENSReleaseProcessor) EstimateGas(params ProcessorInputParams) (uint64,
|
|||
if params.TestsMode {
|
||||
if params.TestEstimationMap != nil {
|
||||
if val, ok := params.TestEstimationMap[s.Name()]; ok {
|
||||
return val, nil
|
||||
return val.Value, val.Err
|
||||
}
|
||||
}
|
||||
return 0, ErrNoEstimationFound
|
||||
|
|
|
@ -75,7 +75,7 @@ func (s *ERC1155Processor) EstimateGas(params ProcessorInputParams) (uint64, err
|
|||
if params.TestsMode {
|
||||
if params.TestEstimationMap != nil {
|
||||
if val, ok := params.TestEstimationMap[s.Name()]; ok {
|
||||
return val, nil
|
||||
return val.Value, val.Err
|
||||
}
|
||||
}
|
||||
return 0, ErrNoEstimationFound
|
||||
|
|
|
@ -112,7 +112,7 @@ func (s *ERC721Processor) EstimateGas(params ProcessorInputParams) (uint64, erro
|
|||
if params.TestsMode {
|
||||
if params.TestEstimationMap != nil {
|
||||
if val, ok := params.TestEstimationMap[s.Name()]; ok {
|
||||
return val, nil
|
||||
return val.Value, val.Err
|
||||
}
|
||||
}
|
||||
return 0, ErrNoEstimationFound
|
||||
|
|
|
@ -93,7 +93,7 @@ func (s *StickersBuyProcessor) EstimateGas(params ProcessorInputParams) (uint64,
|
|||
if params.TestsMode {
|
||||
if params.TestEstimationMap != nil {
|
||||
if val, ok := params.TestEstimationMap[s.Name()]; ok {
|
||||
return val, nil
|
||||
return val.Value, val.Err
|
||||
}
|
||||
}
|
||||
return 0, ErrNoEstimationFound
|
||||
|
|
|
@ -173,7 +173,7 @@ func (s *SwapParaswapProcessor) EstimateGas(params ProcessorInputParams) (uint64
|
|||
if params.TestsMode {
|
||||
if params.TestEstimationMap != nil {
|
||||
if val, ok := params.TestEstimationMap[s.Name()]; ok {
|
||||
return val, nil
|
||||
return val.Value, val.Err
|
||||
}
|
||||
}
|
||||
return 0, ErrNoEstimationFound
|
||||
|
|
|
@ -47,10 +47,10 @@ var optimism = params.Network{
|
|||
RelatedChainID: walletCommon.OptimismMainnet,
|
||||
}
|
||||
|
||||
var testEstimationMap = map[string]uint64{
|
||||
ProcessorTransferName: uint64(1000),
|
||||
ProcessorBridgeHopName: uint64(5000),
|
||||
ProcessorSwapParaswapName: uint64(2000),
|
||||
var testEstimationMap = map[string]Estimation{
|
||||
ProcessorTransferName: {uint64(1000), nil},
|
||||
ProcessorBridgeHopName: {uint64(5000), nil},
|
||||
ProcessorSwapParaswapName: {uint64(2000), nil},
|
||||
}
|
||||
|
||||
type expectedResult struct {
|
||||
|
@ -329,17 +329,17 @@ func TestPathProcessors(t *testing.T) {
|
|||
assert.Greater(t, estimatedGas, uint64(0))
|
||||
|
||||
input := tt.input
|
||||
input.TestEstimationMap = map[string]uint64{
|
||||
"randomName": 10000,
|
||||
input.TestEstimationMap = map[string]Estimation{
|
||||
"randomName": {10000, nil},
|
||||
}
|
||||
estimatedGas, err = processor.EstimateGas(input)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, err, ErrNoEstimationFound)
|
||||
assert.Equal(t, ErrNoEstimationFound, err)
|
||||
assert.Equal(t, uint64(0), estimatedGas)
|
||||
} else {
|
||||
estimatedGas, err := processor.EstimateGas(tt.input)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, err, ErrNoEstimationFound)
|
||||
assert.Equal(t, ErrNoEstimationFound, err)
|
||||
assert.Equal(t, uint64(0), estimatedGas)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -69,7 +69,7 @@ func (s *TransferProcessor) EstimateGas(params ProcessorInputParams) (uint64, er
|
|||
if params.TestsMode {
|
||||
if params.TestEstimationMap != nil {
|
||||
if val, ok := params.TestEstimationMap[s.Name()]; ok {
|
||||
return val, nil
|
||||
return val.Value, val.Err
|
||||
}
|
||||
}
|
||||
return 0, ErrNoEstimationFound
|
||||
|
|
|
@ -308,16 +308,35 @@ func (r *Router) GetPathProcessors() map[string]pathprocessor.PathProcessor {
|
|||
return r.pathProcessors
|
||||
}
|
||||
|
||||
func containsNetworkChainID(chainID uint64, chainIDs []uint64) bool {
|
||||
for _, cID := range chainIDs {
|
||||
if cID == chainID {
|
||||
func arrayContainsElement[T comparable](el T, arr []T) bool {
|
||||
for _, e := range arr {
|
||||
if e == el {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func arraysWithSameElements[T comparable](ar1 []T, ar2 []T, isEqual func(T, T) bool) bool {
|
||||
if len(ar1) != len(ar2) {
|
||||
return false
|
||||
}
|
||||
for _, el := range ar1 {
|
||||
if !arrayContainsElement(el, ar2) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func sameSingleChainTransfer(fromChains []*params.Network, toChains []*params.Network) bool {
|
||||
return len(fromChains) == 1 &&
|
||||
len(toChains) == 1 &&
|
||||
arraysWithSameElements(fromChains, toChains, func(a, b *params.Network) bool {
|
||||
return a.ChainID == b.ChainID
|
||||
})
|
||||
}
|
||||
|
||||
type Router struct {
|
||||
rpcClient *rpc.Client
|
||||
tokenManager *token.Manager
|
||||
|
@ -484,7 +503,7 @@ func (r *Router) SuggestedRoutes(
|
|||
continue
|
||||
}
|
||||
|
||||
if containsNetworkChainID(network.ChainID, disabledFromChainIDs) {
|
||||
if arrayContainsElement(network.ChainID, disabledFromChainIDs) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -568,10 +587,10 @@ func (r *Router) SuggestedRoutes(
|
|||
continue
|
||||
}
|
||||
|
||||
if len(preferedChainIDs) > 0 && !containsNetworkChainID(dest.ChainID, preferedChainIDs) {
|
||||
if len(preferedChainIDs) > 0 && !arrayContainsElement(dest.ChainID, preferedChainIDs) {
|
||||
continue
|
||||
}
|
||||
if containsNetworkChainID(dest.ChainID, disabledToChainIDs) {
|
||||
if arrayContainsElement(dest.ChainID, disabledToChainIDs) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
@ -133,6 +133,10 @@ func (s SendType) canUseProcessor(p pathprocessor.PathProcessor) bool {
|
|||
}
|
||||
}
|
||||
|
||||
func (s SendType) simpleTransfer(p pathprocessor.PathProcessor) bool {
|
||||
return s == Transfer && p.Name() == pathprocessor.ProcessorTransferName
|
||||
}
|
||||
|
||||
func (s SendType) processZeroAmountInProcessor(amountIn *big.Int, amountOut *big.Int, processorName string) bool {
|
||||
if amountIn.Cmp(pathprocessor.ZeroBigIntValue) == 0 {
|
||||
if s == Transfer {
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"math"
|
||||
"math/big"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
@ -21,6 +22,10 @@ import (
|
|||
"github.com/status-im/status-go/signal"
|
||||
)
|
||||
|
||||
const (
|
||||
hexAddressLength = 42
|
||||
)
|
||||
|
||||
var (
|
||||
routerTask = async.TaskType{
|
||||
ID: 1,
|
||||
|
@ -71,8 +76,8 @@ type RouteInputParams struct {
|
|||
type routerTestParams struct {
|
||||
tokenFrom *walletToken.Token
|
||||
tokenPrices map[string]float64
|
||||
estimationMap map[string]uint64 // [processor-name, estimated-value]
|
||||
bonderFeeMap map[string]*big.Int // [token-symbol, bonder-fee]
|
||||
estimationMap map[string]pathprocessor.Estimation // [processor-name, estimation]
|
||||
bonderFeeMap map[string]*big.Int // [token-symbol, bonder-fee]
|
||||
suggestedFees *SuggestedFees
|
||||
baseFee *big.Int
|
||||
balanceMap map[string]*big.Int // [token-symbol, balance]
|
||||
|
@ -407,7 +412,7 @@ func validateFromLockedAmount(input *RouteInputParams) error {
|
|||
excludedChainCount := 0
|
||||
|
||||
for chainID, amount := range input.FromLockedAmount {
|
||||
if containsNetworkChainID(chainID, input.DisabledFromChainIDs) {
|
||||
if arrayContainsElement(chainID, input.DisabledFromChainIDs) {
|
||||
return ErrDisabledChainFoundAmongLockedNetworks
|
||||
}
|
||||
|
||||
|
@ -500,8 +505,21 @@ func (r *Router) SuggestedRoutesV2(ctx context.Context, input *RouteInputParams)
|
|||
|
||||
balanceMap, err := r.getBalanceMapForTokenOnChains(ctx, input, selectedFromChains)
|
||||
// return only if there are no balances, otherwise try to resolve the candidates for chains we know the balances for
|
||||
if len(balanceMap) == 0 && err != nil {
|
||||
return nil, errors.CreateErrorResponseFromError(err)
|
||||
if len(balanceMap) == 0 {
|
||||
if err != nil {
|
||||
return nil, errors.CreateErrorResponseFromError(err)
|
||||
}
|
||||
} else {
|
||||
noBalanceOnAnyChain := true
|
||||
for _, value := range balanceMap {
|
||||
if value.Cmp(pathprocessor.ZeroBigIntValue) > 0 {
|
||||
noBalanceOnAnyChain = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if noBalanceOnAnyChain {
|
||||
return nil, ErrNoPositiveBalance
|
||||
}
|
||||
}
|
||||
|
||||
candidates, processorErrors, err := r.resolveCandidates(ctx, input, selectedFromChains, selectedToChains, balanceMap)
|
||||
|
@ -530,7 +548,23 @@ func (r *Router) SuggestedRoutesV2(ctx context.Context, input *RouteInputParams)
|
|||
}
|
||||
}
|
||||
|
||||
return suggestedRoutes, err
|
||||
mapError := func(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
pattern := "insufficient funds for gas * price + value: address "
|
||||
addressIndex := strings.Index(errors.DetailsFromError(err), pattern)
|
||||
if addressIndex != -1 {
|
||||
addressIndex += len(pattern) + hexAddressLength
|
||||
return errors.CreateErrorResponseFromError(&errors.ErrorResponse{
|
||||
Code: errors.ErrorCodeFromError(err),
|
||||
Details: errors.DetailsFromError(err)[:addressIndex],
|
||||
})
|
||||
}
|
||||
return err
|
||||
}
|
||||
// map some errors to more user-friendly messages
|
||||
return suggestedRoutes, mapError(err)
|
||||
}
|
||||
|
||||
// getBalanceMapForTokenOnChains returns the balance map for passed address, where the key is in format "chainID-tokenSymbol" and
|
||||
|
@ -584,6 +618,10 @@ func (r *Router) getBalanceMapForTokenOnChains(ctx context.Context, input *Route
|
|||
balanceMap[makeBalanceKey(chain.ChainID, token.Symbol)] = tokenBalance
|
||||
}
|
||||
|
||||
if token.IsNative() {
|
||||
continue
|
||||
}
|
||||
|
||||
// add native token balance for the chain
|
||||
nativeBalance, err := r.getBalance(ctx, chain.ChainID, nativeToken, input.AddrFrom)
|
||||
if err != nil {
|
||||
|
@ -756,11 +794,11 @@ func (r *Router) getSelectedChains(input *RouteInputParams) (selectedFromChains
|
|||
continue
|
||||
}
|
||||
|
||||
if !containsNetworkChainID(network.ChainID, input.DisabledFromChainIDs) {
|
||||
if !arrayContainsElement(network.ChainID, input.DisabledFromChainIDs) {
|
||||
selectedFromChains = append(selectedFromChains, network)
|
||||
}
|
||||
|
||||
if !containsNetworkChainID(network.ChainID, input.DisabledToChainIDs) {
|
||||
if !arrayContainsElement(network.ChainID, input.DisabledToChainIDs) {
|
||||
selectedToChains = append(selectedToChains, network)
|
||||
}
|
||||
}
|
||||
|
@ -781,8 +819,8 @@ func (r *Router) resolveCandidates(ctx context.Context, input *RouteInputParams,
|
|||
return nil, nil, errors.CreateErrorResponseFromError(err)
|
||||
}
|
||||
|
||||
appendProcessorErrorFn := func(processorName string, err error) {
|
||||
log.Error("routerv2.resolveCandidates error", "processor", processorName, "err", err)
|
||||
appendProcessorErrorFn := func(processorName string, sendType SendType, fromChainID uint64, toChainID uint64, amount *big.Int, err error) {
|
||||
log.Error("routerv2.resolveCandidates error", "processor", processorName, "sendType", sendType, "fromChainId: ", fromChainID, "toChainId", toChainID, "amount", amount, "err", err)
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
processorErrors = append(processorErrors, &ProcessorError{
|
||||
|
@ -855,6 +893,11 @@ func (r *Router) resolveCandidates(ctx context.Context, input *RouteInputParams,
|
|||
continue
|
||||
}
|
||||
|
||||
// if just a single from and to chain is selected for transfer, we can skip the bridge as potential path
|
||||
if !input.SendType.simpleTransfer(pProcessor) && sameSingleChainTransfer(selectedFromChains, selectedToChains) {
|
||||
continue
|
||||
}
|
||||
|
||||
if !input.SendType.processZeroAmountInProcessor(amountOption.amount, input.AmountOut.ToInt(), pProcessor.Name()) {
|
||||
continue
|
||||
}
|
||||
|
@ -893,7 +936,7 @@ func (r *Router) resolveCandidates(ctx context.Context, input *RouteInputParams,
|
|||
|
||||
can, err := pProcessor.AvailableFor(processorInputParams)
|
||||
if err != nil {
|
||||
appendProcessorErrorFn(pProcessor.Name(), err)
|
||||
appendProcessorErrorFn(pProcessor.Name(), input.SendType, processorInputParams.FromChain.ChainID, processorInputParams.ToChain.ChainID, processorInputParams.AmountIn, err)
|
||||
continue
|
||||
}
|
||||
if !can {
|
||||
|
@ -902,24 +945,24 @@ func (r *Router) resolveCandidates(ctx context.Context, input *RouteInputParams,
|
|||
|
||||
bonderFees, tokenFees, err := pProcessor.CalculateFees(processorInputParams)
|
||||
if err != nil {
|
||||
appendProcessorErrorFn(pProcessor.Name(), err)
|
||||
appendProcessorErrorFn(pProcessor.Name(), input.SendType, processorInputParams.FromChain.ChainID, processorInputParams.ToChain.ChainID, processorInputParams.AmountIn, err)
|
||||
continue
|
||||
}
|
||||
|
||||
gasLimit, err := pProcessor.EstimateGas(processorInputParams)
|
||||
if err != nil {
|
||||
appendProcessorErrorFn(pProcessor.Name(), err)
|
||||
appendProcessorErrorFn(pProcessor.Name(), input.SendType, processorInputParams.FromChain.ChainID, processorInputParams.ToChain.ChainID, processorInputParams.AmountIn, err)
|
||||
continue
|
||||
}
|
||||
|
||||
approvalContractAddress, err := pProcessor.GetContractAddress(processorInputParams)
|
||||
if err != nil {
|
||||
appendProcessorErrorFn(pProcessor.Name(), err)
|
||||
appendProcessorErrorFn(pProcessor.Name(), input.SendType, processorInputParams.FromChain.ChainID, processorInputParams.ToChain.ChainID, processorInputParams.AmountIn, err)
|
||||
continue
|
||||
}
|
||||
approvalRequired, approvalAmountRequired, approvalGasLimit, l1ApprovalFee, err := r.requireApproval(ctx, input.SendType, &approvalContractAddress, processorInputParams)
|
||||
if err != nil {
|
||||
appendProcessorErrorFn(pProcessor.Name(), err)
|
||||
appendProcessorErrorFn(pProcessor.Name(), input.SendType, processorInputParams.FromChain.ChainID, processorInputParams.ToChain.ChainID, processorInputParams.AmountIn, err)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -936,7 +979,7 @@ func (r *Router) resolveCandidates(ctx context.Context, input *RouteInputParams,
|
|||
|
||||
amountOut, err := pProcessor.CalculateAmountOut(processorInputParams)
|
||||
if err != nil {
|
||||
appendProcessorErrorFn(pProcessor.Name(), err)
|
||||
appendProcessorErrorFn(pProcessor.Name(), input.SendType, processorInputParams.FromChain.ChainID, processorInputParams.ToChain.ChainID, processorInputParams.AmountIn, err)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -1041,7 +1084,7 @@ func (r *Router) resolveCandidates(ctx context.Context, input *RouteInputParams,
|
|||
return candidates, processorErrors, nil
|
||||
}
|
||||
|
||||
func (r *Router) checkBalancesForTheBestRoute(ctx context.Context, bestRoute []*PathV2, input *RouteInputParams, balanceMap map[string]*big.Int) (hasPositiveBalance bool, err error) {
|
||||
func (r *Router) checkBalancesForTheBestRoute(ctx context.Context, bestRoute []*PathV2, balanceMap map[string]*big.Int) (hasPositiveBalance bool, err error) {
|
||||
balanceMapCopy := copyMapGeneric(balanceMap, func(v interface{}) interface{} {
|
||||
return new(big.Int).Set(v.(*big.Int))
|
||||
}).(map[string]*big.Int)
|
||||
|
@ -1182,7 +1225,7 @@ func (r *Router) resolveRoutes(ctx context.Context, input *RouteInputParams, can
|
|||
for len(allRoutes) > 0 {
|
||||
bestRoute = findBestV2(allRoutes, tokenPrice, nativeTokenPrice)
|
||||
var hasPositiveBalance bool
|
||||
hasPositiveBalance, err = r.checkBalancesForTheBestRoute(ctx, bestRoute, input, balanceMap)
|
||||
hasPositiveBalance, err = r.checkBalancesForTheBestRoute(ctx, bestRoute, balanceMap)
|
||||
|
||||
if err != nil {
|
||||
// If it's about transfer or bridge and there is more routes, but on the best (cheapest) one there is not enugh balance
|
||||
|
|
|
@ -216,8 +216,12 @@ func TestNoBalanceForTheBestRouteRouterV2(t *testing.T) {
|
|||
if tt.expectedError != nil {
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, tt.expectedError.Error(), err.Error())
|
||||
assert.NotNil(t, routes)
|
||||
assertPathsEqual(t, tt.expectedCandidates, routes.Candidates)
|
||||
if tt.expectedError == ErrNoPositiveBalance {
|
||||
assert.Nil(t, routes)
|
||||
} else {
|
||||
assert.NotNil(t, routes)
|
||||
assertPathsEqual(t, tt.expectedCandidates, routes.Candidates)
|
||||
}
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, len(tt.expectedCandidates), len(routes.Candidates))
|
||||
|
|
|
@ -45,9 +45,9 @@ const (
|
|||
)
|
||||
|
||||
var (
|
||||
testEstimationMap = map[string]uint64{
|
||||
pathprocessor.ProcessorTransferName: uint64(1000),
|
||||
pathprocessor.ProcessorBridgeHopName: uint64(5000),
|
||||
testEstimationMap = map[string]pathprocessor.Estimation{
|
||||
pathprocessor.ProcessorTransferName: {Value: uint64(1000), Err: nil},
|
||||
pathprocessor.ProcessorBridgeHopName: {Value: uint64(5000), Err: nil},
|
||||
}
|
||||
|
||||
testBbonderFeeMap = map[string]*big.Int{
|
||||
|
@ -208,6 +208,46 @@ type normalTestParams struct {
|
|||
|
||||
func getNormalTestParamsList() []normalTestParams {
|
||||
return []normalTestParams{
|
||||
{
|
||||
name: "ETH transfer - Insufficient Funds",
|
||||
input: &RouteInputParams{
|
||||
testnetMode: false,
|
||||
Uuid: uuid.NewString(),
|
||||
SendType: Transfer,
|
||||
AddrFrom: common.HexToAddress("0x1"),
|
||||
AddrTo: common.HexToAddress("0x2"),
|
||||
AmountIn: (*hexutil.Big)(big.NewInt(testAmount1ETHInWei)),
|
||||
TokenID: pathprocessor.EthSymbol,
|
||||
DisabledFromChainIDs: []uint64{walletCommon.OptimismMainnet, walletCommon.ArbitrumMainnet},
|
||||
DisabledToChainIDs: []uint64{walletCommon.OptimismMainnet, walletCommon.ArbitrumMainnet},
|
||||
|
||||
testsMode: true,
|
||||
testParams: &routerTestParams{
|
||||
tokenFrom: &token.Token{
|
||||
ChainID: 1,
|
||||
Symbol: pathprocessor.EthSymbol,
|
||||
Decimals: 18,
|
||||
},
|
||||
tokenPrices: testTokenPrices,
|
||||
suggestedFees: testSuggestedFees,
|
||||
balanceMap: testBalanceMapPerChain,
|
||||
estimationMap: map[string]pathprocessor.Estimation{
|
||||
pathprocessor.ProcessorTransferName: {
|
||||
Value: uint64(0),
|
||||
Err: fmt.Errorf("failed with 50000000 gas: insufficient funds for gas * price + value: address %s have 68251537427723 want 100000000000000", common.HexToAddress("0x1")),
|
||||
},
|
||||
},
|
||||
bonderFeeMap: testBbonderFeeMap,
|
||||
approvalGasEstimation: testApprovalGasEstimation,
|
||||
approvalL1Fee: testApprovalL1Fee,
|
||||
},
|
||||
},
|
||||
expectedError: &errors.ErrorResponse{
|
||||
Code: errors.GenericErrorCode,
|
||||
Details: fmt.Sprintf("failed with 50000000 gas: insufficient funds for gas * price + value: address %s", common.HexToAddress("0x1")),
|
||||
},
|
||||
expectedCandidates: []*PathV2{},
|
||||
},
|
||||
{
|
||||
name: "ETH transfer - No Specific FromChain - No Specific ToChain - 0 AmountIn",
|
||||
input: &RouteInputParams{
|
||||
|
@ -2669,20 +2709,7 @@ func getNoBalanceTestParamsList() []noBalanceTestParams {
|
|||
approvalL1Fee: testApprovalL1Fee,
|
||||
},
|
||||
},
|
||||
expectedError: &errors.ErrorResponse{
|
||||
Code: ErrNotEnoughTokenBalance.Code,
|
||||
Details: fmt.Sprintf(ErrNotEnoughTokenBalance.Details, pathprocessor.UsdcSymbol, walletCommon.OptimismMainnet),
|
||||
},
|
||||
expectedCandidates: []*PathV2{
|
||||
{
|
||||
ProcessorName: pathprocessor.ProcessorTransferName,
|
||||
FromChain: &optimism,
|
||||
ToChain: &optimism,
|
||||
ApprovalRequired: false,
|
||||
requiredTokenBalance: big.NewInt(testAmount100USDC),
|
||||
requiredNativeBalance: big.NewInt((testBaseFee + testPriorityFeeLow) * testApprovalGasEstimation),
|
||||
},
|
||||
},
|
||||
expectedError: ErrNoPositiveBalance,
|
||||
},
|
||||
{
|
||||
name: "ERC20 transfer - Specific FromChain - Specific ToChain - Not Enough Native Balance",
|
||||
|
@ -2766,30 +2793,7 @@ func getNoBalanceTestParamsList() []noBalanceTestParams {
|
|||
approvalL1Fee: testApprovalL1Fee,
|
||||
},
|
||||
},
|
||||
expectedError: &errors.ErrorResponse{
|
||||
Code: ErrNotEnoughTokenBalance.Code,
|
||||
Details: fmt.Sprintf(ErrNotEnoughTokenBalance.Details, pathprocessor.UsdcSymbol, walletCommon.ArbitrumMainnet),
|
||||
},
|
||||
expectedCandidates: []*PathV2{
|
||||
{
|
||||
ProcessorName: pathprocessor.ProcessorBridgeHopName,
|
||||
FromChain: &mainnet,
|
||||
ToChain: &optimism,
|
||||
ApprovalRequired: true,
|
||||
},
|
||||
{
|
||||
ProcessorName: pathprocessor.ProcessorTransferName,
|
||||
FromChain: &optimism,
|
||||
ToChain: &optimism,
|
||||
ApprovalRequired: false,
|
||||
},
|
||||
{
|
||||
ProcessorName: pathprocessor.ProcessorBridgeHopName,
|
||||
FromChain: &arbitrum,
|
||||
ToChain: &optimism,
|
||||
ApprovalRequired: true,
|
||||
},
|
||||
},
|
||||
expectedError: ErrNoPositiveBalance,
|
||||
},
|
||||
{
|
||||
name: "ERC20 transfer - No Specific FromChain - Specific ToChain - Enough Token Balance On Arbitrum Chain But Not Enough Native Balance",
|
||||
|
|
Loading…
Reference in New Issue