Skip to main content

Substrate With WASM

Acurast can be used on Substrate with an WASM integration. The output of the Acurast Jobs are pushed to a smart contract deployed in the WASM environment, that can then be used by other developers.

Example integration with WASM smart contract parachain

The following example shows a possible integration approach for a WASM smart contract parachain (using pallet-contracts). Similarly to the EVM integration, the example shows how to route the fulfillment's payload to a smart contract by calling the fulfill method on it and passing the payload bytes as argument.

#[derive(RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Eq)]
pub enum ContractMethodSelector {
Custom([u8; 4]),

impl ContractMethodSelector {
fn into_fixed_bytes(self) -> [u8; 4] {
match self {
Self::Default => BlakeTwo256::hash(b"fulfill").as_bytes()[0..4].try_into().unwrap(),
Self::Custom(bytes) => bytes,

#[derive(RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Eq)]
pub struct RegistrationExtra {
pub contract_address: AccountId,
pub selector: ContractMethodSelector,

parameter_types! {
pub const MaxAllowedSources: u16 = 100;
pub AllowedRevocationListUpdate: Vec<AccountId> = vec![];

impl pallet_acurast::Config for Runtime {
type Event = Event;
type RegistrationExtra = RegistrationExtra;
type FulfillmentRouter = AcurastRouter;

pub struct AcurastRouter;
impl pallet_acurast::FulfillmentRouter<Runtime> for AcurastRouter {
fn received_fulfillment(
origin: frame_system::pallet_prelude::OriginFor<Runtime>,
from: <Runtime as frame_system::Config>::AccountId,
fulfillment: pallet_acurast::Fulfillment,
registration: pallet_acurast::JobRegistrationFor<Runtime>,
requester: <<Runtime as frame_system::Config>::Lookup as StaticLookup>::Target,
) -> DispatchResultWithPostInfo {

pub enum Runtime where
Block = Block,
NodeBlock = opaque::Block,
UncheckedExtrinsic = UncheckedExtrinsic,
// All your other pallets
// Contracts
Contracts: pallet_contracts,

// Acurast
Acurast: pallet_acurast,


ink! Contract Example

The following snippet of code shows a very basic WASM smart contract implemented using ink! and capable of receiving the routed fulfill call from the FulfillmentRouter implemented above:

#![cfg_attr(not(feature = "std"), no_std)]

use ink_lang as ink;

mod receiver {

use ink_prelude::vec::Vec;

/// Defines the storage of your contract.
/// Add new fields to the below struct in order
/// to add new static storage fields to your contract.
pub struct Receiver {
source: Option<AccountId>,
target: Option<AccountId>,
payload: Option<Vec<u8>>,

impl Receiver {
/// Constructor that initializes `source`, `target` and `payload` to `None`.
/// Constructors can delegate to other constructors.
pub fn default() -> Self {
Self {
source: None,
target: None,
payload: None,

/// Simply stores the `source`, `target` and `payload` values.
pub fn fulfill(&mut self, source: AccountId, target: AccountId, payload: Vec<u8>) {
self.source = Some(source); = Some(target);
self.payload = Some(payload);

/// Simply returns the current value of our `source`, `target` and `payload`.
pub fn get(&self) -> (Option<AccountId>, Option<AccountId>, Option<Vec<u8>>) {