Attribute Macro concordium_std::receive
source · #[receive]
Expand description
Derive the appropriate export for an annotated receive function.
This macro requires the following items to be present
contract = "<contract-name>"
where <contract-name> is the name of the smart contract.name = "<receive-name>"
where <receive-name> is the name of the receive function, or thefallback
option. The generated function is exported as<contract-name>.<receive-name>
, or iffallback
is given, as<contract-name>.
.Contract name and receive name is required to be unique in the module. In particular, a contract may have only a single fallback method.
The annotated function must be of a specific type, which depends on the enabled attributes. Without any of the optional attributes the function must have a signature of
#[receive(contract = "my_contract", name = "some_receive")]
fn contract_receive(
ctx: &ReceiveContext,
host: &Host<MyState>
) -> ReceiveResult<MyReturnValue> {...}
Where the ReceiveContext
, Host
, and ReceiveResult
are from concordium-std
and MyState
and MyReturnValue
are user-defined
types.
§Optional attributes
§payable
: Make function accept an amount of CCD
Without setting the payable
attribute, the function will reject any
non-zero amount of CCD, supplied with the transaction. This means we are
required to explicitly mark our functions as payable
, if they are to
accept CCD.
Setting the payable
attribute changes the required signature to include an
extra argument of type Amount
, allowing the function to access the amount
of CCD supplied with the transaction.
§Example
#[receive(contract = "my_contract", name = "some_receive", payable)]
fn contract_receive(
ctx: &ReceiveContext,
host: &Host<MyState>,
amount: Amount
) -> ReceiveResult<MyReturnValue> {...}
§mutable
: Function can mutate the state
Setting the mutable
attribute changes the required signature so the host
becomes a mutable reference.
When a receive method is mutable, the state, e.g. MyState
, is serialized
and stored after each invocation. This means that even if the state does
not change semantically, it will be considered as modified by callers.
Thus the mutable
option should only be used when absolutely necessary.
§Example
#[receive(contract = "my_contract", name = "some_receive", mutable)]
fn contract_receive(
ctx: &ReceiveContext,
host: &mut Host<MyState>,
) -> ReceiveResult<MyReturnValue> {...}
§enable_logger
: Function can access event logging
Setting the enable_logger
attribute changes the required signature to
include an extra argument &mut Logger
, allowing the function to
log events.
§Example
#[receive(contract = "my_contract", name = "some_receive", enable_logger)]
fn contract_receive(
ctx: &ReceiveContext,
host: &Host<MyState>,
logger: &mut Logger,
) -> ReceiveResult<MyReturnValue> {...}
§low_level
: Manually deal with the low-level state including writing
bytes Setting the low_level
attribute disables the generated code for
serializing the contract state. However, the return value is still
serialized automatically.
If low_level
is set, the &Host<State>
in the signature is
replaced by &mut LowLevelHost
found in concordium-std
, which gives
access to manipulating the low-level contract state directly via the methods
state()
and state_mut()
.
§Example
#[receive(contract = "my_contract", name = "some_receive", low_level)]
fn contract_receive(
ctx: &ReceiveContext,
state: &mut LowLevelHost,
) -> ReceiveResult<MyReturnValue> {...}
§parameter="<Param>"
: Generate schema for parameter
To make schema generation include the parameter for this function, add
the attribute parameter
and set it equal to a string literal containing
the type used for the parameter. The parameter type must
implement the SchemaType trait, which for most cases can be derived
automatically.
§Example
#[derive(SchemaType)]
struct MyParam { ... }
#[receive(contract = "my_contract", name = "some_receive", parameter = "MyParam")]
fn contract_receive(
ctx: &ReceiveContext,
host: &Host<MyState>,
) -> ReceiveResult<A> {...}
§return_value="<ReturnValue>"
: Generate schema for the return value.
To make schema generation include the return value for this function, add
the attribute return_value
and set it equal to a string literal containing
the type used for the parameter. The parameter type must
implement the SchemaType trait, which for most cases can be derived
automatically.
§Example
#[derive(SchemaType)]
struct MyReturnValue { ... }
#[receive(contract = "my_contract", name = "some_receive", return_value = "MyReturnValue")]
fn contract_receive(
ctx: &ReceiveContext,
host: &Host<MyState>,
) -> ReceiveResult<MyReturnValue> {...}
§error="<Error>"
: Generate schema for error
To make schema generation include the error for this function, add
the attribute error
and set it equal to a string literal containing
the type used for the error. The error type must
implement the SchemaType trait, which for most cases can be derived
automatically.
§Example
#[derive(SchemaType)]
enum MyError { ... }
#[receive(contract = "my_contract", name = "some_receive", error = "MyError")]
fn contract_receive(
ctx: &ReceiveContext,
host: &Host<MyState>,
) -> Result<A, MyError> {...}
§fallback
: Create a fallback entrypoint.
A contract can have a single fallback entrypoint defined.
If defined, invocations on missing entrypoint will be redirected to the
fallback entrypoint. For fallback entrypoints, the name
attribute is not
allowed. This is because fallback entrypoints always have the empty string
as their name.
To get the name of the entrypoint used for invocation, use
ctx.named_entrypoint()
. The method is available in all receive methods,
but is only useful on fallback entrypoints.
§Example
#[receive(contract = "my_contract", fallback)]
fn contract_receive(
ctx: &ReceiveContext,
host: &Host<MyState>,
) -> ReceiveResult<MyReturnValue> {
let named_entrypoint = ctx.named_entrypoint();
// ...
}
§crypto_primitives
: Function can access cryptographic primitives
Setting the crypto_primitives
attribute changes the required signature to
include an extra argument &CryptoPrimitives
, which provides
cryptographic primitives such as verifying signatures and hashing data.
§Example
#[receive(contract = "my_contract", name = "some_receive", crypto_primitives)]
fn some_receive(
ctx: &ReceiveContext,
host: &Host<MyState>,
crypto_primitives: &CryptoPrimitives,
) -> ReceiveResult<MyReturnValue> {...}