Petite Fleece Cheetah
High
There is currently a refund logic that transfers the funds to a fee payer.
The root cause lies in the fact that the transaction fees can be paid by other enitities and the funds are returned to a fee payer and not a granter.
Fee granter has to pay for the fees.
Fee grantor paid for the fees but the funds are returned to a fee payer.
Loss of funds for a fee granter.
Consider the current refund mechanism:
// RefundTx refunds the given tx by sending the fee back to the fee payer.
func (k Keeper) RefundTx(ctx context.Context, tx sdk.FeeTx) error {
txFee := tx.GetFee()
if txFee.IsZero() {
// not possible with the global min gas price mechanism
// but having this check for compatibility in the future
return nil
}
txFeePayer := tx.FeePayer()
return k.bankKeeper.SendCoinsFromModuleToAccount(ctx, k.feeCollectorName, txFeePayer, txFee)
}
The problem is that the fees are refunded to the feePayer
(the sender of the message) without taking into account the fact that the actual payer can be feeGranter
resulting in a loss of funds for the granter:
type FeeTx interface {
[Tx](https://pkg.go.dev/github.com/cosmos/cosmos-sdk/types#Tx)
GetGas() [uint64](https://pkg.go.dev/builtin#uint64)
GetFee() [Coins](https://pkg.go.dev/github.com/cosmos/cosmos-sdk/types#Coins)
FeePayer() [][byte](https://pkg.go.dev/builtin#byte)
FeeGranter() [][byte](https://pkg.go.dev/builtin#byte)
}
Check out the Celestia solution for this issue:
// getRecipient returns the address that should receive the refund.
func getRecipient(feeTx sdk.FeeTx) sdk.AccAddress {
if feeGranter := feeTx.FeeGranter(); feeGranter != nil {
return feeGranter
}
return feeTx.FeePayer()
}
Here the funds are actually sent to the right entity.