Attribute Macro pallet_contracts_proc_macro::define_env

source ·
#[define_env]
Expand description

Defines a host functions set that can be imported by contract wasm code.

NB: Be advised that all functions defined by this macro will panic if called with unexpected arguments.

It’s up to you as the user of this macro to check signatures of wasm code to be executed and reject the code if any imported function has a mismatched signature.

§Example

#[define_env]
pub mod some_env {
	fn foo(ctx: _, memory: _, key_ptr: u32, value_ptr: u32, value_len: u32) -> Result<(), TrapReason> {
		ctx.some_host_fn(KeyType::Fix, key_ptr, value_ptr, value_len).map(|_| ())
	}
}

This example will expand to the foo() defined in the wasm module named seal0. This is because the module seal0 is the default when no module is specified.

To define a host function in seal2 and seal3 modules, it should be annotated with the appropriate attribute as follows:

§Example

#[define_env]
pub mod some_env {
	#[version(2)]
	fn foo(ctx: _, memory: _, key_ptr: u32, value_ptr: u32, value_len: u32) -> Result<ReturnErrorCode, TrapReason> {
		ctx.some_host_fn(KeyType::Fix, key_ptr, value_ptr, value_len).map(|_| ())
	}

	#[version(3)]
	#[unstable]
	fn bar(ctx: _, memory: _, key_ptr: u32, value_ptr: u32, value_len: u32) -> Result<u32, TrapReason> {
		ctx.some_host_fn(KeyType::Fix, key_ptr, value_ptr, value_len).map(|_| ())
	}
}

The function bar is additionally annotated with unstable which removes it from the stable interface. Check out the README to learn about unstable functions.

In legacy versions of pallet_contracts, it was a naming convention that all host functions had to be named with the seal_ prefix. For the sake of backwards compatibility, each host function now can get a such prefix-named alias function generated by marking it by the #[prefixed_alias] attribute:

§Example

#[define_env]
pub mod some_env {
	#[version(1)]
	#[prefixed_alias]
	fn foo(ctx: _, memory: _, key_ptr: u32, value_ptr: u32, value_len: u32) -> Result<ReturnErrorCode, TrapReason> {
		ctx.some_host_fn(KeyType::Fix, key_ptr, value_ptr, value_len).map(|_| ())
	}

	#[version(42)]
	fn bar(ctx: _, memory: _, key_ptr: u32, value_ptr: u32, value_len: u32) -> Result<u32, TrapReason> {
		ctx.some_host_fn(KeyType::Fix, key_ptr, value_ptr, value_len).map(|_| ())
	}
}

In this example, the following host functions will be generated by the macro:

  • foo() in module seal1,
  • seal_foo() in module seal1,
  • bar() in module seal42.

Only following return types are allowed for the host functions defined with the macro:

  • Result<(), TrapReason>,
  • Result<ReturnErrorCode, TrapReason>,
  • Result<u32, TrapReason>.

The macro expands to pub struct Env declaration, with the following traits implementations:

  • pallet_contracts::wasm::Environment<Runtime<E>> where E: Ext
  • pallet_contracts::wasm::Environment<()>

The implementation on () can be used in places where no Ext exists, yet. This is useful when only checking whether a code can be instantiated without actually executing any code.

§Generating Documentation

Passing doc attribute to the macro (like #[define_env(doc)]) will make it also expand additional pallet_contracts::api_doc::seal0, pallet_contracts::api_doc::seal1, ... modules each having its Api trait containing functions holding documentation for every host function defined by the macro.

§Deprecated Interfaces

An interface can be annotated with #[deprecated]. It is mutually exclusive with #[unstable]. Deprecated interfaces have the following properties: - New contract codes utilizing those interfaces cannot be uploaded. - New contracts from existing codes utilizing those interfaces cannot be instantiated.

  • Existing contracts containing those interfaces still work.

Those interfaces will eventually be removed.

To build up these docs, run:

cargo doc