ab_contracts_common/
lib.rs

1#![no_std]
2
3pub mod env;
4mod error;
5pub mod metadata;
6pub mod method;
7
8use crate::method::MethodFingerprint;
9use ab_io_type::IoType;
10use ab_io_type::variable_bytes::VariableBytes;
11use core::ffi::c_void;
12use core::ops::Deref;
13use core::ptr::NonNull;
14pub use error::{ContractError, CustomContractErrorCode, ExitCode};
15
16/// Max allowed size of the contract code
17pub const MAX_CODE_SIZE: u32 = 1024 * 1024;
18/// Max number of arguments in a method.
19///
20/// NOTE: Both `self` and return type that is not `()` or `Result<(), ContractError>` count towards
21/// the total number of method arguments.
22pub const MAX_TOTAL_METHOD_ARGS: u8 = 8;
23
24/// Method details used by native execution environment.
25///
26/// `ffi_fn`'s argument is actually `NonNull<InternalArgs>` of corresponding method and must have
27/// corresponding ABI.
28///
29/// NOTE: It is unlikely to be necessary to interact with this directly.
30#[derive(Debug, Copy, Clone)]
31#[doc(hidden)]
32pub struct NativeExecutorContactMethod {
33    pub method_fingerprint: &'static MethodFingerprint,
34    pub method_metadata: &'static [u8],
35    pub ffi_fn: unsafe extern "C" fn(NonNull<NonNull<c_void>>) -> ExitCode,
36}
37
38/// A trait that indicates the struct is a contact.
39///
40/// **Do not implement this trait explicitly!** Implementation is automatically generated by the
41/// macro which generates contract implementation. This trait is required, but not sufficient for
42/// proper contract implementation, use `#[contract]` attribute macro instead.
43pub trait Contract: IoType {
44    /// Main contract metadata, see [`ContractMetadataKind`] for encoding details.
45    ///
46    /// More metadata can be contributed by trait implementations.
47    ///
48    /// [`ContractMetadataKind`]: crate::metadata::ContractMetadataKind
49    const MAIN_CONTRACT_METADATA: &[u8];
50    /// Something that can be used as "code" in native execution environment.
51    ///
52    /// NOTE: It is unlikely to be necessary to interact with this directly.
53    #[doc(hidden)]
54    const CODE: &str;
55    /// Methods of a contract used in native execution environment.
56    ///
57    /// NOTE: It is unlikely to be necessary to interact with this directly.
58    #[doc(hidden)]
59    const NATIVE_EXECUTOR_METHODS: &[NativeExecutorContactMethod];
60    // Default value is provided to only fail to compile when contract that uses
61    // `ab-contracts-common` has feature specified, but `ab-contracts-common` does not, but not the
62    // other way around (as will be the case with dependencies where `guest` feature must not be
63    // enabled)
64    #[cfg(feature = "guest")]
65    #[doc(hidden)]
66    const GUEST_FEATURE_ENABLED: () = ();
67    /// Slot type used by this contract
68    type Slot: IoType;
69    /// Tmp type used by this contract
70    type Tmp: IoType;
71    /// Something that can be used as "code" in native execution environment and primarily used for
72    /// testing.
73    ///
74    /// This is NOT the code compiled for guest architecture!
75    // TODO: Make `const` when possible
76    fn code() -> impl Deref<Target = VariableBytes<MAX_CODE_SIZE>>;
77}
78
79/// A trait that indicates the implementation of a contract trait by a contract.
80///
81/// `DynTrait` here is `dyn ContractTrait`, which is a bit of a hack that allows treating a trait as
82/// a type for convenient API in native execution environment.
83///
84/// **Do not implement this trait explicitly!** Implementation is automatically generated by the
85/// macro which generates contract trait implementation. This trait is required, but not sufficient
86/// for proper trait implementation, use `#[contract]` attribute macro instead.
87///
88/// NOTE: It is unlikely to be necessary to interact with this directly.
89pub trait ContractTrait<DynTrait>
90where
91    DynTrait: ?Sized,
92{
93    /// Methods of a trait used in native execution environment
94    #[doc(hidden)]
95    const NATIVE_EXECUTOR_METHODS: &[NativeExecutorContactMethod];
96}
97
98/// A trait that is implemented for `dyn ContractTrait` and includes constants related to trait
99/// definition.
100///
101/// `dyn ContractTrait` here is a bit of a hack that allows treating a trait as a type. These
102/// constants specifically can't be implemented on a trait itself because that'll make trait
103/// not object safe, which is needed for [`ContractTrait`] that uses a similar hack with
104/// `dyn ContractTrait`.
105///
106/// **Do not implement this trait explicitly!** Implementation is automatically generated by the
107/// macro which generates trait definition. This trait is required, but not sufficient for
108/// proper trait implementation, use `#[contract]` attribute macro instead.
109///
110/// NOTE: It is unlikely to be necessary to interact with this directly.
111pub trait ContractTraitDefinition {
112    // Default value is provided to only fail to compile when trait that uses
113    // `ab-contracts-common` has feature specified, but `ab-contracts-common` does not, but not the
114    // other way around (as will be the case with dependencies where `guest` feature must not be
115    // enabled)
116    #[cfg(feature = "guest")]
117    #[doc(hidden)]
118    const GUEST_FEATURE_ENABLED: () = ();
119    /// Trait metadata, see [`ContractMetadataKind`] for encoding details"]
120    /// Trait metadata, see [`ContractMetadataKind`] for encoding details"]
121    ///
122    /// [`ContractMetadataKind`]: crate::metadata::ContractMetadataKind
123    const METADATA: &[::core::primitive::u8];
124}