DEV Community

Ying
Ying

Posted on

How GenLayer Contracts Read the Web: A Beginner's Guide to Non-Deterministic Blocks

Smart Contracts That Can Browse the Internet

Imagine a smart contract that can check a sports score, verify a news headline, or read a product price — all on-chain, with consensus. Traditional smart contracts are blind to the outside world. They can only work with data that's explicitly fed to them through oracles or manual transactions.

GenLayer changes this. Its Intelligent Contracts can fetch live web pages and call LLMs directly, then reach agreement among validators on what the result means. This article walks you through how that works, starting from zero.

What Makes This Possible: Non-Deterministic Blocks

The core challenge is simple: if a contract fetches a web page, two validators might get slightly different results (ads change, timestamps shift, content updates). Traditional blockchains can't handle this — they require every node to produce the exact same output.

GenLayer solves this with non-deterministic blocks — special Python functions where web fetches and LLM calls are allowed. After each validator runs the block independently, GenLayer's consensus mechanism (the Equivalence Principle) determines whether the results are "close enough" to agree on.

Here's the mental model:

Deterministic code → same input, same output (like normal smart contracts)
Non-deterministic block → validators may get different raw results
Equivalence Principle → validators agree on whether results are equivalent
Enter fullscreen mode Exit fullscreen mode

Your First Web-Reading Contract

Let's build a contract that checks whether a webpage contains a specific link. This is the simplest possible example of web connectivity:

# { "Depends": "py-genlayer:1jb45aa8ynh2a9c9xn3b7qqh8sm5q93hwfp7jqmwsfhh8jpz09h6" }

from genlayer import *

class WebChecker(gl.Contract):
    has_link: bool

    def __init__(self, url: str, keyword: str):
        target_url = url
        target_keyword = keyword

        def check_page():
            web_data = gl.nondet.web.render(target_url, mode='html')
            return target_keyword in web_data

        self.has_link = gl.eq_principle.strict_eq(check_page)

    @gl.public.view
    def result(self) -> bool:
        return self.has_link
Enter fullscreen mode Exit fullscreen mode

Let's break down what's happening:

  1. The version comment on line 1 pins the GenVM runtime version (like Solidity's pragma)
  2. gl.nondet.web.render() fetches a live web page inside the non-deterministic block
  3. gl.eq_principle.strict_eq() tells validators to compare results with exact equality — if all validators get True, consensus passes

The Rules of Non-Deterministic Blocks

There are a few constraints that keep the system safe:

  • No storage access — you cannot read or write contract state inside a non-deterministic block
  • No side effects leak out — changes to Python globals inside the block don't persist
  • Web calls must happen inside an equivalence principle call — calling gl.nondet.web.render() outside of gl.eq_principle.* will throw an error
  • The block is a zero-argument function — it captures variables from the surrounding scope via closure

Think of it like a sandbox: the contract says "go look at the world and tell me what you found," then validators compare notes.

Choosing the Right Equivalence Method

GenLayer offers different ways for validators to agree:

Method Use When
gl.eq_principle.strict_eq() Result is a simple value (bool, number) where exact match makes sense
gl.eq_principle.prompt_comparative() Result is text/complex data where an LLM should judge equivalence

For our web-checker example, strict_eq is perfect — we're returning a boolean. But if you were summarizing a news article, you'd use prompt_comparative so validators can agree that two slightly different summaries convey the same meaning.

A Practical Example: Price Threshold Monitor

Here's a slightly more useful contract — it checks whether a product page shows a price below a threshold:

# { "Depends": "py-genlayer:1jb45aa8ynh2a9c9xn3b7qqh8sm5q93hwfp7jqmwsfhh8jpz09h6" }

from genlayer import *

class PriceMonitor(gl.Contract):
    item_url: str
    threshold: str
    is_below_threshold: bool

    def __init__(self, item_url: str, threshold: str):
        self.item_url = item_url
        self.threshold = threshold
        self.is_below_threshold = False

    @gl.public.write
    def check_price(self):
        url = self.item_url
        limit = self.threshold

        def fetch_and_compare():
            page = gl.nondet.web.render(url, mode='text')
            prompt = f"Extract the main product price from this page and tell me if it is below {limit}. Answer only YES or NO.

Page content:
{page}"
            result = gl.nondet.llm.call(prompt)
            return result.strip().upper() == "YES"

        self.is_below_threshold = gl.eq_principle.strict_eq(fetch_and_compare)

    @gl.public.view
    def below_threshold(self) -> bool:
        return self.is_below_threshold
Enter fullscreen mode Exit fullscreen mode

This combines both web fetching and LLM reasoning inside a single non-deterministic block. The LLM extracts the price and makes the comparison, then validators agree on the boolean result.

Key Takeaways

  1. GenLayer contracts can read live web data — no external oracle infrastructure needed
  2. Non-deterministic blocks are sandboxed functions where web and LLM calls happen, isolated from contract storage
  3. The Equivalence Principle handles consensus — validators independently execute the block and agree on results
  4. strict_eq works for simple values, while prompt_comparative handles fuzzy text comparison
  5. You write everything in Python — no new language to learn, just a few GenLayer-specific patterns

Next Steps

Ready to try this yourself? Head to GenLayer Studio — it's a zero-setup web IDE where you can write, deploy, and test Intelligent Contracts in your browser. No Docker, no local install needed.

For a full local development environment with testing and linting, check out the GenLayer Project Boilerplate and the official documentation.

Top comments (0)