Crate obce

source ·
Expand description

OBCE is a library that provides tools to create custom chain extensions with automatic generation of bindings for both ink! smart contracts and Substrate-based chains.

Usage

obce::definition macro is OBCE’s entrypoint. Using this macro you can define the API of your chain extension for usage in both ink! and Substrate:

#[obce::definition]
pub trait MyChainExtension {
    fn chain_extension_method(&self, val: u32) -> u64;
}

With ink feature enabled, obce::definition automatically produces glue code to correctly call Substrate part of a chain extension. This glue code takes care of argument encoding/decoding, identifier matching, etc.

On the other hand, when substrate feature is enabled, the usage of obce::implementation is required to complete the chain extension implementation.

obce::implementation is used on an impl block to generate the code necessary for usage in Substrate:

use obce::substrate::{
    frame_system::Config as SysConfig,
    pallet_contracts::Config as ContractConfig,
    sp_runtime::traits::StaticLookup,
    ChainExtensionEnvironment,
    ExtensionContext
};

#[obce::definition]
pub trait MyChainExtension {
    fn chain_extension_method(&self, val: u32) -> u64;
}

pub struct ChainExtension;

#[obce::implementation]
impl<'a, E, T, Env> MyChainExtension for ExtensionContext<'a, E, T, Env, ChainExtension>
where
    T: SysConfig + ContractConfig,
    <<T as SysConfig>::Lookup as StaticLookup>::Source: From<<T as SysConfig>::AccountId>,
    Env: ChainExtensionEnvironment<E, T>,
{
    fn chain_extension_method(&self, val: u32) -> u64 {
        val as u64
    }
}

There are various configuration options available for both obce::definition and obce::implementation, all of which are documented in corresponding API sections.

Custom errors

Your chain extension may have chain-specific errors, some of which may terminate contract execution itself. You may use obce::error macro to create your custom error type, with an optional variant that holds critical errors:

use obce::substrate::CriticalError;

#[obce::error]
enum Error {
    One(u32),

    #[obce(critical)]
    Two(CriticalError)
}

Testing

OBCE also provides infrastructure for testing your chain extension using obce::mock.

To start testing your chain extension, mark chain extension definition impl block as obce::mock, and fill the impl block with the required methods:

#[obce::definition]
pub trait MyChainExtension {
    fn chain_extension_method(&self, val: u32) -> u64;
}

// Contract code...

mod simple_test {
    struct Context;

    #[obce::mock]
    impl crate::ChainExtension for Context {
        fn chain_extension_method(&self, val: u32) -> u64 {
            val as u64
        }
    }

    #[test]
    fn call_contract() {
        register_chain_extensions(Context);
        // Call the contract as usual
    }
}

For a complete usage example, as well as more details on how to use the macro correctly see the corresponding API section.

Modules

  • Automatically generated traits that provide the necessary information about the chain extension.

Macros

  • Chain extension identifier lookup.

Attribute Macros

  • Chain extension definition for use with Substrate-based nodes and ink! smart contracts.
  • Chain extension error.
  • Chain extension implementation for use with Substrate-based nodes.
  • Chain extension mocking utility.