# Offchain Oracle Workers

{% hint style="danger" %}
**Outdated Documentation:** This page covers the architecture used for USC V1, which was deprecated on 2026-03-30. For the latest documentation, please visit: [usc documentation](https://docs.creditcoin.org/usc)
{% endhint %}

## **Motivation for Offchain Oracle Workers**

When the Creditcoin Oracle provisions data from one chain to another there are **three** transactions that must be submitted by the user or DApp builder:

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. **User/Builder submits an oracle query on the** <img src="/files/ZABpsfb0M5qJd9lXhaEc" alt="" data-size="line"> `Creditcoin` **execution chain**. This transaction kicks off the query proving process. After query proving, data from the event emitted in step 1 is proven and available on the *execution chain*.
3. **User/Builder calls the universal smart contract on the execution chain**. This call retrieves the data from the event emitted in step 1 and which has now been made available by the Creditcoin Oracle in step 2. The Universal Smart Contract interprets it, and uses it to trigger DApp business logic in your [business logic smart contracts](/usc/usc-v1/dapp-builder-infrastructure/infrastructure-overview.md#dapp-business-logic-smart-contracts).

The following diagram illustrates the various steps where our bridging process is halted awaiting user/builder input.

<figure><img src="/files/VO6pztC0lw4wyAeKNZln" alt=""><figcaption></figcaption></figure>

### Removing Friction

The first transaction must always be submitted by the end user. However, transactions 2 and 3 can be initiated by the DApp builders on behalf of their users. This is preferable for several reasons:

1. **The fewer transactions your DApp requires users to sign, the better!** Signing just one transaction feels much better than signing 3, potentially spaced several minutes apart.
2. **End users won’t understand why they need to sign 3 different transactions.** This can be a cause of anxiety for them or even prevent some users from following through with using your DApp.
3. Due to a lack of semantic labeling of oracle query results, **it is possible to construct invalid oracle queries,** making them incompatible with a DApp’s Universal Smart Contract. For this reason, DApp builders should submit properly formatted queries on behalf of their users.

## Designing an Offchain Oracle Worker

As seen above, signing the *proving* and *query* transactions on behalf of you end users can drastically improve the UX of your Universal DApp by reducing the number of user interactions needed to trigger core business logic on the <img src="/files/ZABpsfb0M5qJd9lXhaEc" alt="" data-size="line"> `Creditcoin` *execution chain.*

### Worker Transaction Flow

One way of streamlining the execution process is by relying on *automated Offchain Workers*, as illustrated in the following sequence diagram.

{% @mermaid/diagram content="sequenceDiagram
autonumber
box Execution Chain (Creditcoin)
participant BL as Business Logic
participant USC
participant DO as Decentralized Oracle
participant AT as Attestors
end
participant OW as Offchain Worker
box Source Chain
participant SC as Smart Contract
end
USER ->> SC: Calls
Note left of USER: User signs a tx<br/>to initiate interaction
SC ->> AT: Attestors follow all source chain<br/> blocks, including the block<br/> containing our tx
activate AT
AT -->> DO: Relays Attestation
deactivate AT
Note over DO,AT: Only a commitment to the state<br/>of the source chain is relayed. This<br/>commitment can later be used by<br/> the creditcoin oracle to verify<br/> that our source chain<br/> transaction actually took place.
loop
OW -->> SC: Watches for<br/> events that<br/> should trigger<br/> queries
activate SC
SC -->> OW: Emits an Event
deactivate SC
end
OW ->> DO: Requests Proof
activate DO
DO ->> DO: Generates and Stores Proof
DO ->> OW: Emits proof completion event
deactivate DO
activate OW
OW ->> USC: Triggers USC use of proof data
deactivate OW
activate USC
USC ->> DO: Requests proof<br/> data from oracle
deactivate USC
activate DO
DO ->> USC: Returns proof<br/> data
deactivate DO
activate USC
USC ->> BL: Dispatches
deactivate USC
activate BL
BL ->> BL: Runs Business Logic
Note over BL,USC: All business logic  is encapsulated<br/>on execution chain.  Source chain<br/>only serves to query the  USC.
deactivate BL
loop
USER-->>BL: Watches for events
activate BL
BL-->>USER: DApp contract emits events
deactivate BL
activate USER
end
USER->>USER: Updates UI to reflect state change
deactivate USER" fullWidth="true" %}

We can break this down into the same four categories, but with different implications in terms of UX:

* **Initial DApp Query from the source chain.** This is now the only transaction which has to be signed by the end user. All the rest of your DApp's logic is handled by the Offchain Worker, providing a truly native feel.
* **Proof generation.** Steps **n˚4** to **n˚7** are responsible for generating a proof of the event's occurrence on the *source chain.* The Offchain Worker constantly monitors the source chain contract for events. As soon as an event is emitted and made available on the execution chain, it requests a proof from the Creditcoin Oracle. *This requires no further user interaction.*
* **Executing business logic.** Next, steps **n˚8** till **n˚13** are responsible for executing the business logic of your DApp on the *execution chain*. This is initiated by the Offchain Worker, which queries the Universal Smart Contract on the *execution chain* on behalf of the user. *This requires no further user interaction.*
* **Aggregating Results.** Finally, the results of your DApp's execution can be retrieved and processed by the user. This does not require further user interaction, but it *does* require the DApp client to keep watch of the *execution chain*, either via light client or else by querying a remote RPC endpoint.

### **Going Further**

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:

1. Retaining stored records of queries in progress in the event of a Worker shut down.
2. Catching up with any event that might have been missed as result of an unexpected shutdown.
3. Avoiding submitting multiple queries or USC calls for the same event.
4. Following multiple source chain nodes to listen for events in case a node experiences issues.
5. Re-submit valid oracle queries or USC calls in case they fail. A query can fail for many reasons: for example the Prover a query is submitted to to might be experiencing down time or connectivity issues.

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

{% @mermaid/diagram content="---
config:
theme: neo
----------

stateDiagram
s1:New source chain Events?
state if\_events <<choice>>
s3:Request a proof from the prover contract for each event
s4:Periodically checking for proof completion, timeout, etc.
s5:Timeout or payment reclaimed?
state if\_escrow\_payment\_reclaimed <<choice>>
s8:Resubmit proof request with reclaimed funds
s9:Check for proof completion
s10:QueryProofVerified?
state if\_query\_proof\_verified <<choice>>
s11:Retrieve proof
s12:Log successful query
s13:Trigger USC use of proof results
s14:Success!\
restartVerify:keep waiting

```
[*] --> s1
s1 --> if_events
if_events --> s3:Yes
if_events --> s1:No
s3 --> s4
s4 --> ProofPaymentReclaimedOrTimedOut
note right of ProofPaymentReclaimedOrTimedOut
    Cron job checks for QuerySubmitted events that exceed timeout. When EscrowPaymentReclaimed event is received the query
    is either timed out or is failed to be proven.
end note

state ProofPaymentReclaimedOrTimedOut {
    s5 --> if_escrow_payment_reclaimed
    if_escrow_payment_reclaimed --> s8:Yes
    if_escrow_payment_reclaimed --> s9:No
} 
s8 --> s3 
s9 --> ProofVerify

state ProofVerify {
    s10 --> if_query_proof_verified
    if_query_proof_verified --> s11:Yes
    if_query_proof_verified --> restartVerify:No
    s11 --> s12
    s12 --> s13
    s13 --> s14
}

restartVerify --> s4

s14 --> [*]
```

" fullWidth="true" %}

## Next Steps

[USC Tutorials](/usc/usc-v1/dapp-builder-infrastructure/usc-tutorials.md)

*Check out* [*this script*](https://github.com/gluwa/ccnext-testnet-bridge-examples/blob/main/bridge-offchain-worker/src/worker.ts) *for an example of an offchain worker.* [*Here*](https://github.com/gluwa/ccnext-testnet-bridge-examples/blob/b46a76e559cb4c7b1207567a8bf76f36db2f9430/bridge-offchain-worker/src/worker.ts#L237) *is where the oracle query is submitted to the oracle prover contract, and* [*here*](https://github.com/gluwa/ccnext-testnet-bridge-examples/blob/b46a76e559cb4c7b1207567a8bf76f36db2f9430/bridge-offchain-worker/src/worker.ts#L300) *is where the query results are submitted to the Universal Smart Contract.*


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.creditcoin.org/usc/usc-v1/dapp-builder-infrastructure/offchain-oracle-workers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
