From a410c5586319903b60438cf85549b3aa6753b009 Mon Sep 17 00:00:00 2001 From: Kevin Halliday Date: Fri, 21 Feb 2025 09:55:30 -0500 Subject: [PATCH] fix(solver): handle tokens that decrement max allowance (#3112) Do not error if below max allowance. issue: #3111 --- solver/app/approvals.go | 16 +++++++++++++--- solver/app/procdeps.go | 9 +++++++-- solver/app/reject.go | 9 +++++++-- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/solver/app/approvals.go b/solver/app/approvals.go index bb698a9c6..326b26f78 100644 --- a/solver/app/approvals.go +++ b/solver/app/approvals.go @@ -22,6 +22,8 @@ import ( ) // approveOutboxes gives each outbox max allowance for all supported tokens. +// Most tokens will not decrement allowance when set to max, though some do. +// TODO: monitor allowances, alert or reset when "low" (half type(uint256).max). func approveOutboxes(ctx context.Context, network netconf.Network, backends ethbackend.Backends, solverAddr common.Address) error { addrs, err := contracts.GetAddresses(ctx, network.ID) if err != nil { @@ -99,7 +101,9 @@ func approveToken(ctx context.Context, backend *ethbackend.Backend, token Token, return errors.Wrap(err, "new token") } - isApproved := func() (bool, error) { return isAppproved(ctx, token.Address, backend, solverAddr, outboxAddr) } + isApproved := func() (bool, error) { + return isAppproved(ctx, token.Address, backend, solverAddr, outboxAddr, umath.MaxUint256) + } if approved, err := isApproved(); err != nil { return err @@ -128,7 +132,13 @@ func approveToken(ctx context.Context, backend *ethbackend.Backend, token Token, return nil } -func isAppproved(ctx context.Context, token common.Address, client ethclient.Client, solverAddr, outboxAddr common.Address) (bool, error) { +func isAppproved( + ctx context.Context, + token common.Address, + client ethclient.Client, + solverAddr, outboxAddr common.Address, + spend *big.Int, +) (bool, error) { tkn, err := bindings.NewIERC20(token, client) if err != nil { return false, errors.Wrap(err, "new token") @@ -139,5 +149,5 @@ func isAppproved(ctx context.Context, token common.Address, client ethclient.Cli return false, errors.Wrap(err, "get allowance") } - return new(big.Int).Sub(allowance, umath.MaxUint256).Sign() >= 0, nil + return spend.Cmp(allowance) <= 0, nil } diff --git a/solver/app/procdeps.go b/solver/app/procdeps.go index 99929e77e..43caa72c4 100644 --- a/solver/app/procdeps.go +++ b/solver/app/procdeps.go @@ -122,13 +122,18 @@ func newFiller( return errors.New("unsupported token, should have been rejected [BUG]", "addr", tknAddr.Hex(), "chain_id", destChainID) } - isAppproved, err := isAppproved(ctx, tknAddr, backend, solverAddr, outboxAddr) + isAppproved, err := isAppproved(ctx, tknAddr, backend, solverAddr, outboxAddr, output.Amount) if err != nil { return errors.Wrap(err, "is approved") } if !isAppproved { - return errors.New("outbox not approved to spend token [BUG] ", "token", tkn.Symbol, "chain_id", destChainID) + return errors.New("outbox not approved to spend token", + "token", tkn.Symbol, + "chain_id", destChainID, + "addr", tknAddr.Hex(), + "amount", output.Amount, + ) } } diff --git a/solver/app/reject.go b/solver/app/reject.go index ee26ca90b..b57eda2ee 100644 --- a/solver/app/reject.go +++ b/solver/app/reject.go @@ -148,13 +148,18 @@ func checkApprovals(ctx context.Context, expenses []Payment, client ethclient.Cl continue } - isAppproved, err := isAppproved(ctx, tkn.Address, client, solverAddr, outboxAddr) + isAppproved, err := isAppproved(ctx, tkn.Address, client, solverAddr, outboxAddr, expense.Amount) if err != nil { return errors.Wrap(err, "is approved") } if !isAppproved { - return errors.New("outbox not approved to spend token [BUG]", "token", tkn.Symbol, "chain_id", tkn.ChainID) + return errors.New("outbox not approved to spend token", + "token", tkn.Symbol, + "chain_id", tkn.ChainID, + "addr", tkn.Address.Hex(), + "amount", expense.Amount, + ) } }