CosmWasm / cosmwasm

Framework for building smart contracts in Wasm for the Cosmos SDK
https://www.cosmwasm.com/
Apache License 2.0
1.07k stars 333 forks source link

Using `usize` in enums causes floating point instructions to be generated #1168

Closed 0xekez closed 1 year ago

0xekez commented 2 years ago

Generating the starter cosmwasm contract by running:

cargo generate --git https://github.com/CosmWasm/cw-template.git --name repro

Then, modifying the default code to add a Foo member with a usize parameter as follows:

diff --git a/src/contract.rs b/src/contract.rs
index d0d8ab8..b938246 100644
--- a/src/contract.rs
+++ b/src/contract.rs
@@ -41,6 +41,7 @@ pub fn execute(
     match msg {
         ExecuteMsg::Increment {} => try_increment(deps),
         ExecuteMsg::Reset { count } => try_reset(deps, info, count),
+        ExecuteMsg::Foo(_) => todo!(),
     }
 }

diff --git a/src/msg.rs b/src/msg.rs
index 4cec36d..1883561 100644
--- a/src/msg.rs
+++ b/src/msg.rs
@@ -11,6 +11,7 @@ pub struct InstantiateMsg {
 pub enum ExecuteMsg {
     Increment {},
     Reset { count: i32 },
+    Foo(usize),
 }

 #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]

Causes floating point instructions to be outputted when compiled which will prevent the contract from being uploaded. This is unexpected as using u64 instead will work. An example upload and error message:

$ junod tx wasm store artifacts/repro.wasm --from ezekiiel --fees 34592ujunox --gas auto
Error: rpc error: code = InvalidArgument desc = failed to execute message; message index: 0: Error calling the VM: Error compiling Wasm: Could not compile: WebAssembly translation error: Error in middleware Gatekeeper: Float operator detected: F64Load { memarg: MemoryImmediate { align: 3, offset: 0, memory: 0 } }. The use of floats is not supported.: create wasm contract failed: invalid request

The floating point instructions are generated by cargo wasm and not the rust optimizer so I don't think this is necessarily a bug with cosmwasm but it might be nice to somehow warn about this in either documentation or in the optimizer. Seems like a pretty subtle footgun. I'm happy to work on this if people have thoughts on how this might be resolved.

webmaster128 commented 2 years ago

Thanks for bringing this up. Good point. Last time I debugged something like this the problem was a formatter function that was eventually unused and was kicked out by rust-optimizer but not the simple Rust production build.

But using u64 or u32 explicitly makes sense in most places. With usize you get different sizes between unit tests (64 bit dev machine) and Wasm (32 bit).

0xekez commented 2 years ago

@webmaster128 thanks for the response. I actually didn't even know that webassembly had a 32 bit VM so I'm already learning something :)

Do you think there are steps that we might take (for example: docs updates) to make these things a little more clear? I don't see anywhere that pops out to me after a skim but you might have better ideas. It might also be fine to just let this issue document the solution.

webmaster128 commented 1 year ago

This is solved by https://github.com/CosmWasm/cosmwasm/issues/1845 which will be shipped as part of CosmWasm 1.5.