Skip to content
Global documentation search

Offchain Oracle Workers

When the Creditcoin Oracle provisions data from one chain to another, there are two transactions involved:

  1. The user submits a transaction on the source chain. Usually this would be a source chain smart contract call emitting some event for which we want to transfer data to the execution chain.
  2. The USC contract must be called on the execution chain. This requires generating proofs and calling the USC contract with the proofs and encoded transaction data. The USC contract verifies the proofs synchronously and executes business logic immediately.

The following diagram highlights where these two transactions take place:

The first transaction must always be submitted by the end user. However, the second transaction can be initiated by an off-chain worker on behalf of the user. Using an off-chain worker provides significant UX and technical benefits:

  • Seamless user experience: Without a worker, users would need to wait for attestation (several minutes), manually generate proofs, format the proof data correctly, and then submit a second transaction. With a worker, users only need to sign the initial source chain transaction. Everything else happens automatically in the background.
  • Eliminates technical complexity for end users: Proof generation requires calling the Proof Generation API server, waiting for attestation, handling retries, and properly formatting complex proof structures (Merkle proofs, continuity proofs, encoded transactions). Off-chain workers handle all of this complexity automatically, so users don’t need to understand the underlying oracle mechanics.
  • Reduces transaction failures and improves reliability: Workers can implement robust retry logic, handle API failures gracefully, and ensure proper error handling. Users attempting manual proof generation are more likely to encounter failures due to timing issues (submitting before attestation completes), formatting errors, or network problems.
  • Enables better monitoring and observation: Workers can track processing status, log events, and provide visibility into the cross-chain data flow. This helps DApp teams debug issues and monitor their DApp’s health.

Using an off-chain worker can drastically improve the UX of your Universal DApp by reducing the number of user interactions needed to trigger core business logic on the Creditcoin execution chain.

The worker automates the following process:

  1. Monitor source chain: The worker constantly monitors the source chain contract for events (e.g., TokensBurnedForBridging events).
  2. Wait for attestation: When an event is detected, the worker waits for the block containing the event to be attested on Creditcoin.
  3. Generate proofs: The worker can generate Merkle and continuity proofs via the Proof Generation API server.
  4. Call USC contract: The worker calls the USC contract with the proofs and encoded transaction data. The USC contract verifies the proofs synchronously and executes business logic immediately.
  5. Handle results: The worker can listen for events from the USC contract to confirm successful execution.

All of this happens automatically - the user only needs to sign the initial source chain transaction.

sequenceDiagram
participant User
participant SC as Source Chain<br/>(Smart Contract)
participant Worker as Oracle Worker
participant Attestors as Attestor Network
participant Oracle as Creditcoin Oracle
participant ProofAPI as Proof Generation<br/>API Server
participant USC as USC Contract
participant BusinessLogic as DApp Business Logic<br/>Contract

Note over User,BusinessLogic: Phase 1: User Initiates Transaction User->>SC: Submit Transaction
(e.g., burn tokens) SC->>SC: Execute Logic & Emit Event

Note over Worker,BusinessLogic: Phase 2: Worker Monitors & Waits Worker->>SC: Monitor Source Chain
for Events SC–>>Worker: Event Detected

Note over Attestors: Attestation Process
(happens independently) Attestors->>SC: Monitor Source Chain
for Blocks SC–>>Attestors: New Blocks Detected Attestors->>Oracle: Submit Aggregated Attestation

Worker->>Oracle: Check if Block Attested Oracle–>>Worker: Block Attested ✓

Note over Worker,BusinessLogic: Phase 3: Generate Proofs Worker->>ProofAPI: Request Proofs
(chainKey, blockHeight, txHash)

ProofAPI->>Oracle: Fetch Attestations Oracle–>>ProofAPI: Attestation Data

ProofAPI->>SC: Fetch Source Chain Block SC–>>ProofAPI: Block Data

ProofAPI->>ProofAPI: Generate Merkle & Continuity Proofs

ProofAPI–>>Worker: Return Proofs & Encoded TX

Note over Worker,BusinessLogic: Phase 4: Verify & Execute Worker->>USC: Call processCrossChainData()
(proofs + encoded tx)

USC->>Oracle: Verify Proofs
(via precompile) Oracle->>Oracle: Verify Merkle & Continuity Proofs Oracle–>>USC: Verification Result: ✓ Valid

USC->>BusinessLogic: Execute Business Logic
(e.g., mint tokens) BusinessLogic->>BusinessLogic: Update State and Emit Event
(e.g., TokensMinted)

BusinessLogic–>>User: Listens to Dapp events (optional)

This has just been a starting point designed to introduce you to the use of Offchain Workers. Each DApp builder team will likely want to implement their Worker differently to fit the rest of their technology stack.

Keeping this in mind, the main goal of an Offchain Worker should always be robustness. This includes:

  • Retaining stored records of events in progress in the event of a Worker shutdown
  • Catching up with any event that might have been missed as a result of an unexpected shutdown
  • Avoiding submitting multiple USC calls for the same event (replay protection is handled by the USC contract, but workers should also track processed events)
  • Following multiple source chain nodes to listen for events in case a node experiences issues
  • Retrying failed proof generation or USC calls in case they fail. A call can fail for many reasons: for example, the Proof Generation API server might be experiencing downtime or connectivity issues, or the USC contract call might fail due to network issues

Below is an example of the logical flow that a more advanced oracle worker might use

---
config:
theme: neo
----------

stateDiagram
s1:Monitor source chain for events
state if_events <<choice>>
s2:Event detected
s3:Wait for block attestation
state if_attested <<choice>>
s4:Generate proofs via Proof Generation API
state if_proof_success <<choice>>
s5:Call USC contract with proofs
state if_usc_success <<choice>>
s6:USC verifies synchronously
s7:Business logic executed
s8:Success!
retryAttestation:Retry after delay
retryProof:Retry proof generation
retryUSC:Retry USC call

[] –> s1 s1 –> if_events if_events –> s2:Yes if_events –> s1:No s2 –> s3 s3 –> if_attested if_attested –> s4:Block attested if_attested –> retryAttestation:Not yet attested retryAttestation –> s3 s4 –> if_proof_success if_proof_success –> s5:Proofs generated if_proof_success –> retryProof:API error/retry retryProof –> s4 s5 –> if_usc_success if_usc_success –> s6:Transaction submitted if_usc_success –> retryUSC:Network error/retry retryUSC –> s5 s6 –> s7 s7 –> s8 s8 –> []

" fullWidth="true

USC Tutorials

Check out this script for an example of an offchain worker.