diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index 89318b8e1f..1451607273 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -171,7 +171,13 @@ func (k Keeper) create(ctx context.Context, creator sdk.AccAddress, wasmCode []b } gasLeft := k.runtimeGasForContract(sdkCtx) - checksum, gasUsed, err := k.wasmVM.StoreCode(wasmCode, gasLeft) + var gasUsed uint64 + if sdkCtx.ExecMode() == sdk.ExecModeSimulate { + // only simulate storing the code, no files are written + checksum, gasUsed, err = k.wasmVM.SimulateStoreCode(wasmCode, gasLeft) + } else { + checksum, gasUsed, err = k.wasmVM.StoreCode(wasmCode, gasLeft) + } k.consumeRuntimeGas(sdkCtx, gasUsed) if err != nil { return 0, checksum, errorsmod.Wrap(types.ErrCreateFailed, err.Error()) diff --git a/x/wasm/keeper/wasmtesting/mock_engine.go b/x/wasm/keeper/wasmtesting/mock_engine.go index 14a3976d1a..886a27aef1 100644 --- a/x/wasm/keeper/wasmtesting/mock_engine.go +++ b/x/wasm/keeper/wasmtesting/mock_engine.go @@ -24,6 +24,7 @@ var _ types.WasmEngine = &MockWasmEngine{} type MockWasmEngine struct { StoreCodeFn func(codeID wasmvm.WasmCode, gasLimit uint64) (wasmvm.Checksum, uint64, error) StoreCodeUncheckedFn func(codeID wasmvm.WasmCode) (wasmvm.Checksum, error) + SimulateStoreCodeFn func(codeID wasmvm.WasmCode, gasLimit uint64) (wasmvm.Checksum, uint64, error) AnalyzeCodeFn func(codeID wasmvm.Checksum) (*wasmvmtypes.AnalysisReport, error) InstantiateFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, initMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.ContractResult, uint64, error) ExecuteFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.ContractResult, uint64, error) @@ -117,6 +118,13 @@ func (m *MockWasmEngine) StoreCodeUnchecked(codeID wasmvm.WasmCode) (wasmvm.Chec return m.StoreCodeUncheckedFn(codeID) } +func (m *MockWasmEngine) SimulateStoreCode(codeID wasmvm.WasmCode, gasLimit uint64) (wasmvm.Checksum, uint64, error) { + if m.SimulateStoreCodeFn == nil { + panic("not supposed to be called!") + } + return m.SimulateStoreCodeFn(codeID, gasLimit) +} + func (m *MockWasmEngine) AnalyzeCode(codeID wasmvm.Checksum) (*wasmvmtypes.AnalysisReport, error) { if m.AnalyzeCodeFn == nil { panic("not supposed to be called!") diff --git a/x/wasm/types/wasmer_engine.go b/x/wasm/types/wasmer_engine.go index ce1a56ffc4..9a0c20b28a 100644 --- a/x/wasm/types/wasmer_engine.go +++ b/x/wasm/types/wasmer_engine.go @@ -30,6 +30,11 @@ type WasmEngine interface { // Use this for adding code that was checked before, particularly in the case of state sync. StoreCodeUnchecked(code wasmvm.WasmCode) (wasmvm.Checksum, error) + // SimulateStoreCode works like StoreCode, but does not actually store the code. + // Instead, it just does all the validation and compilation steps without storing the result on disk. + // Returns both the checksum, as well as the gas cost of compilation (in CosmWasm Gas) or an error. + SimulateStoreCode(code wasmvm.WasmCode, gasLimit uint64) (wasmvm.Checksum, uint64, error) + // AnalyzeCode will statically analyze the code. // Currently just reports if it exposes all IBC entry points. AnalyzeCode(checksum wasmvm.Checksum) (*wasmvmtypes.AnalysisReport, error)