#[contract_exception]Expand description
#[contract_exception] or #[contract_exception(version = "1.0.0", name = "...")] —
full convenience macro: derives + #[repr(i32)] + impl Exn +
impl ContractTypeName.
name = "..." renames the type in the spec as it does for
#[contract_type], and may not contain :: either.
wire_crate = "..." pins the package label used in the selector hash.
Use it for a protocol-defined exception whose wire identity must survive
a package rename. It does not change the type’s spec name or provenance.
§Exception payloads cannot carry auth tokens
No field may be — or contain — a thruput_sdk::signer::Signed.
A Signed occupies zero wire bytes; its real handle arrives out of band
in the auth-token list the host returns beside a successful return.
Abort frames carry no such list (the host refuses to return auth tokens
on a revert frame), so a Signed reached through an exception decodes
to the uninitialized u32::MAX sentinel — a value that looks like an
auth token, is not one, and faults when consumed or returned.
There is no way to write this correctly, so hand the token back through a successful return instead, or identify it by something inert (the minter’s address, an id) and let the caller re-obtain it.
Two things catch it. This macro’s PartialEq derive (required by Exn)
blocks the direct route — Signed does not implement PartialEq —
so reaching the situation at all takes hand-written impls (or #[exn]).
Beyond that, spec canonicalization walks each throws(...) payload when
the contract is built and rejects any that reaches a signed token,
however deeply nested, so hand-rolled types do not slip through.