Skip to main content

Tezos Integration

Acurast can be used to get access to interoperability ressources for various use cases and bring them to Tezos.

Integration Example

The following example shows a possible integration approach for Tezos.

Tezos smart contract implementation

The first step is the implementation and deployment of the Tezos contract.

The example used is a simple entropy provider written in SmartPy, which receives entropy from an Acurast Processor and exposes it to other contracts on Tezos.

SmartPy IDE

import smartpy as sp

def main():
t_storage: type = sp.record(
governance_address = sp.address,
subscriptions=sp.big_map[sp.address, sp.timestamp]
).layout(("entropy", ("governance_address", ("last_update", ("processors", "subscriptions")))))

class EntropyProvider(sp.Contract):
def __init__(self, initial_storage): = sp.cast(initial_storage, t_storage)

def submit_entropy(self, entropy):
# Ensures that only the processor can call this function
# Update entropy = sp.blake2b( + entropy) =

def subscribe(self, address):
# The subscription is <block_timestamp> + <mutez amount>
### Both values represent seconds
# 1 mutez = 1 second
# 1 tez = ~11.57 days

mutez_to_seconds = sp.fst(sp.ediv(sp.amount, sp.mutez(1)).unwrap_some())
expiration = sp.add(, sp.to_int(mutez_to_seconds))[address] = expiration

def configure(self, actions):
# Only the governance address can call this entry point
assert == sp.sender, "NOT_ALLOWED"

# Perform actions
for action in actions:
with sp.match(action):
with as governance_address: = governance_address
with as update_processor_actions:
for update_processor_action in update_processor_actions:
with sp.match(update_processor_action):
with as processor_address:
with as processor_address:

def withdraw(self, address):
# Only the governance address can call this entry point
assert == sp.sender, "NOT_ALLOWED"
# Transfer balance
sp.send(address, sp.balance)

def consume_entropy(self, max_age_in_seconds):
# Verify if the consumer has an active subscription
subscription =, error = "NOT_SUBSCRIBED")
assert subscription >=, "SUBSCRIPTION_EXPIRED"
# Consumers can specify the maximum entropy age they are willing to accept
assert ( - <= max_age_in_seconds, "ENTROPY_TOO_OLD"


@sp.add_test(name = "EntropyProviderTest")
def test():
scenario = sp.test_scenario(main)

# Test accounts
governance = sp.test_account("governance")
consumer1 = sp.test_account("consumer1")
processor1 = sp.test_account("processor1")

initial_storage = sp.record(
governance_address = governance.address,
entropy = sp.bytes("0x"),
last_update = sp.timestamp(0),
processors = sp.set([processor1.address]),
subscriptions = sp.big_map()
contract = main.EntropyProvider(initial_storage)

scenario += contract

contract.subscribe(consumer1.address).run(amount = sp.mutez(1000000))
valid = False,
exception = "NOT_PROCESSOR",
sender = consumer1.address
sender = processor1.address,
now = sp.timestamp(100)

Job specification

Now that the contract has been deployed, we can prepare the script that will get executed by the Processor to provision the entropy.

The script below computes some random bytes securely and calls the function submit_entropy of the contract deployed above.

const TEZOS_RPCS = [

const entropy = "0x" + generateSecureRandomHex();

fee: 1500,
gasLimit: 3000,
storageLimit: 0,
destination: TEZOS_CONTRACT,
entrypoint: "submit_entropy",
(opHash) => {
print("Succeeded: " + opHash);
(err) => {
print("Failed: " + err);

Job Registration

Check out How to get started with the Acurast Console to register your Job.