Bypass fee payer authentication
Description
When sending a message, it is possible to specify a separate fee payer who is not part of the message GetSigners()
. If the fee payer signs the transaction, then the fee for the transaction will be decided from their account instead of the first signer.
In the AuthenticatorDecorator
, the transaction is limited to 20,000 gas until the fee payer has been authenticated:
if authentication.IsAuthenticated() {
msgAuthenticated = true
// Once the fee payer is authenticated, we can set the gas limit to its original value
if !feePayerAuthenticated && account.Equals(feePayer) {
originalGasMeter.ConsumeGas(payerGasMeter.GasConsumed(), "fee payer gas")
// Reset this for both contexts
cacheCtx = ad.authenticatorKeeper.TransientStore.
GetTransientContextWithGasMeter(originalGasMeter)
ctx = ctx.WithGasMeter(originalGasMeter)
feePayerAuthenticated = true
}
break
}
The issue is that when a separate fee payer is specified, the account
will not match the feePayer
and the feePayerAuthenticated
will not be set to true
as the fee payer will not be a signer of the individual messages.
Impact
It is currently not possible to specify a separate fee payer for the transaction; they must be one of the signers of the message.
Recommendations
The authenticator attached to the fee payer should be used to verify that they have signed the transaction.
Remediation
This issue has been acknowledged by Osmosis Labs, and a fix was implemented in commit 651eccd9↗. The transaction now fails if the fee payer hasn't been authenticated.