Skip to content

Commit

Permalink
fix(callbacks)!: SendPacket validation bypass and erroneous event emi…
Browse files Browse the repository at this point in the history
…ssion are fixed (#4568)

* fix: fixed callbacks out of gas handling

* fix: fixed panics and oog errors not showing up on events

* docs(callbacks): added godocs for error precedence

---------

Co-authored-by: Carlos Rodriguez <[email protected]>
(cherry picked from commit e192899)

# Conflicts:
#	modules/apps/callbacks/ibc_middleware.go
  • Loading branch information
srdtrk authored and mergify[bot] committed Feb 21, 2024
1 parent 6cb509e commit d042db4
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 3 deletions.
20 changes: 20 additions & 0 deletions modules/apps/callbacks/ibc_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ package ibccallbacks
import (
"fmt"

<<<<<<< HEAD
=======
errorsmod "cosmossdk.io/errors"
storetypes "cosmossdk.io/store/types"

>>>>>>> e1928999 (fix(callbacks)!: SendPacket validation bypass and erroneous event emission are fixed (#4568))
sdk "github.com/cosmos/cosmos-sdk/types"
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"

Expand Down Expand Up @@ -239,6 +245,11 @@ func (im IBCMiddleware) WriteAcknowledgement(

// processCallback executes the callbackExecutor and reverts contract changes if the callbackExecutor fails.
//
// Error Precedence and Returns:
// - oogErr: Takes the highest precedence. If the callback runs out of gas, an error wrapped with types.ErrCallbackOutOfGas is returned.
// - panicErr: Takes the second-highest precedence. If a panic occurs and it is not propagated, an error wrapped with types.ErrCallbackPanic is returned.
// - callbackErr: If the callbackExecutor returns an error, it is returned as-is.
//
// panics if
// - the contractExecutor panics for any reason, and the callbackType is SendPacket, or
// - the contractExecutor runs out of gas and the relayer has not reserved gas grater than or equal to
Expand All @@ -259,11 +270,20 @@ func (IBCMiddleware) processCallback(
if callbackType == types.CallbackTypeSendPacket {
panic(r)
}
err = errorsmod.Wrapf(types.ErrCallbackPanic, "ibc %s callback panicked with: %v", callbackType, r)
}

// if the callback ran out of gas and the relayer has not reserved enough gas, then revert the state
<<<<<<< HEAD
if cachedCtx.GasMeter().IsPastLimit() && callbackData.AllowRetry() {
panic(sdk.ErrorOutOfGas{Descriptor: fmt.Sprintf("ibc %s callback out of gas; commitGasLimit: %d", callbackType, callbackData.CommitGasLimit)})
=======
if cachedCtx.GasMeter().IsPastLimit() {
if callbackData.AllowRetry() {
panic(storetypes.ErrorOutOfGas{Descriptor: fmt.Sprintf("ibc %s callback out of gas; commitGasLimit: %d", callbackType, callbackData.CommitGasLimit)})
}
err = errorsmod.Wrapf(types.ErrCallbackOutOfGas, "ibc %s callback out of gas", callbackType)
>>>>>>> e1928999 (fix(callbacks)!: SendPacket validation bypass and erroneous event emission are fixed (#4568))
}

// allow the transaction to be committed, continuing the packet lifecycle
Expand Down
15 changes: 12 additions & 3 deletions modules/apps/callbacks/ibc_middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,23 @@ func (s *CallbacksTestSuite) TestSendPacket() {
ibcmock.MockApplicationCallbackError, // execution failure on SendPacket should prevent packet sends
},
{
"failure: callback execution reach out of gas, but sufficient gas provided by relayer",
"failure: callback execution reach out of gas panic, but sufficient gas provided",
func() {
packetData.Memo = fmt.Sprintf(`{"src_callback": {"address":"%s", "gas_limit":"400000"}}`, callbackAddr)
},
types.CallbackTypeSendPacket,
true,
sdk.ErrorOutOfGas{Descriptor: fmt.Sprintf("mock %s callback panic", types.CallbackTypeSendPacket)},
},
{
"failure: callback execution reach out of gas error, but sufficient gas provided",
func() {
packetData.Memo = fmt.Sprintf(`{"src_callback": {"address":"%s", "gas_limit":"400000"}}`, simapp.OogErrorContract)
},
types.CallbackTypeSendPacket,
false,
errorsmod.Wrapf(types.ErrCallbackOutOfGas, "ibc %s callback out of gas", types.CallbackTypeSendPacket),
},
}

for _, tc := range testCases {
Expand Down Expand Up @@ -756,7 +765,7 @@ func (s *CallbacksTestSuite) TestProcessCallback() {
}
},
false,
nil,
errorsmod.Wrapf(types.ErrCallbackPanic, "ibc %s callback panicked with: %v", callbackType, "callbackExecutor panic"),
},
{
"success: callbackExecutor oog panic, but retry is not allowed",
Expand All @@ -768,7 +777,7 @@ func (s *CallbacksTestSuite) TestProcessCallback() {
}
},
false,
nil,
errorsmod.Wrapf(types.ErrCallbackOutOfGas, "ibc %s callback out of gas", callbackType),
},
{
"failure: callbackExecutor error",
Expand Down
2 changes: 2 additions & 0 deletions modules/apps/callbacks/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ var (
ErrNotPacketDataProvider = errorsmod.Register(ModuleName, 3, "packet is not a PacketDataProvider")
ErrCallbackKeyNotFound = errorsmod.Register(ModuleName, 4, "callback key not found in packet data")
ErrCallbackAddressNotFound = errorsmod.Register(ModuleName, 5, "callback address not found in packet data")
ErrCallbackOutOfGas = errorsmod.Register(ModuleName, 6, "callback out of gas")
ErrCallbackPanic = errorsmod.Register(ModuleName, 7, "callback panic")
)

0 comments on commit d042db4

Please sign in to comment.