Search code examples
rustnearprotocolrust-macrosnear-sdk-rs

NEAR-sdk #[near_bindgen] colliding with other macros


I've put together a minimum working example, and you can see it here: https://github.com/synthesis-labs/near-mwe. In summary: I have a simple macro that checks that the owner (an arbitrary definition in the context of a struct of the contract) has a particular identity. This is just a simple expansion and insertion into the AST of the function.

When I build this with a classic cargo build then the build works fine and the macro expands appropriately; however to deploy smart contracts I need to build for a WASM-32 target; and then the project fails to compile. Interestingly if I remove the #[near_bindgen] directive then I can build for the WASM-32 target and the macro expands correctly.

The error I get when compiling with the #[near_bindgen] included and for the WASM-32 target is as follows:

cargo build --target wasm32-unknown-unknown

error[E0424]: expected value, found module `self`
  --> src/main.rs:13:5
   |
13 |     #[state_safe]
   |     ^^^^^^^^^^^^^ `self` value is a keyword only available in methods with a `self` parameter
14 |     pub fn change_owner(&mut self, new_owner: String) -> () {
   |            ------------ this function can't have a `self` parameter

I can successfully build the project without the --target wasm32-unknown-unknown or I can remove the #[near_bindgen] and build it with the --target wasm32-unknown-unknown directive.


Solution

  • Figured it out!

    #[near_bindgen] causes the macro to be evaluated twice. The second evaluation occurs when the #[near_bindgen] macro is generating the extern bindings for the NEAR contract, and this only occurs when building for the wasm32 target.

    By parsing the macro token stream for the signatures of the #[near_bindgen] bindings I can drop out of the second invocation of the macro, thereby not inserting invalid code into the bindings:

        if input.to_string().contains("target_arch = \"wasm32\"") {
            return input;
        }