diff --git a/CHANGELOG.md b/CHANGELOG.md index fedf6aafec..a3f7e06fa4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ [Full Changelog](https://github.com/CosmWasm/wasmd/compare/v0.28.0...HEAD) -## [v0.27.0](https://github.com/CosmWasm/wasmd/tree/v0.28.0) (2022-07-29) +## [v0.28.0](https://github.com/CosmWasm/wasmd/tree/v0.28.0) (2022-07-29) [Full Changelog](https://github.com/CosmWasm/wasmd/compare/v0.27.0...v0.28.0) @@ -22,6 +22,7 @@ Migration notes: The main issue here is likely "Custom" queries from a blockchain, which want to send info (eg. how many tokens were swapped). Since those custom bindings are maintained by the chain, they can use the data field to pass any deterministic information back to the contract. We recommend using JSON encoding there with some documented format the contracts can parse out easily. +* For possible non-determinism issues, we also sort all attributes in events. Better safe than sorry. ## [v0.27.0](https://github.com/CosmWasm/wasmd/tree/v0.27.0) (2022-05-19) diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index 3fdcbec483..986a185e0a 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -500,6 +500,7 @@ func (k Keeper) reply(ctx sdk.Context, contractAddress sdk.AccAddress, reply was // prepare querier querier := k.newQueryHandler(ctx, contractAddress) gas := k.runtimeGasForContract(ctx) + res, gasUsed, execErr := k.wasmVM.Reply(codeInfo.CodeHash, env, reply, prefixStore, cosmwasmAPI, querier, k.gasMeter(ctx), gas, costJSONDeserialization) k.consumeRuntimeGas(ctx, gasUsed) if execErr != nil { diff --git a/x/wasm/keeper/msg_dispatcher.go b/x/wasm/keeper/msg_dispatcher.go index 51650d85ef..59a836fa5f 100644 --- a/x/wasm/keeper/msg_dispatcher.go +++ b/x/wasm/keeper/msg_dispatcher.go @@ -1,7 +1,9 @@ package keeper import ( + "bytes" "fmt" + "sort" wasmvmtypes "github.com/CosmWasm/wasmvm/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -109,6 +111,13 @@ func (d MessageDispatcher) DispatchSubmessages(ctx sdk.Context, contractAddr sdk ctx.EventManager().EmitEvents(filteredEvents) if msg.Msg.Wasm == nil { filteredEvents = []sdk.Event{} + } else { + for _, e := range filteredEvents { + attributes := e.Attributes + sort.SliceStable(attributes, func(i, j int) bool { + return bytes.Compare(attributes[i].Key, attributes[j].Key) < 0 + }) + } } } // on failure, revert state from sandbox, and ignore events (just skip doing the above)