# GenLayer Intelligent Contract Structure: A Complete Technical Guide

> Explore the technical structure of a GenLayer intelligent contract. Learn how to define state with TreeMap DynArray and implement public methods for your decentralized applications.

- Repository: [GenLayer Labs/genlayer-project-boilerplate](https://github.com/genlayerlabs/genlayer-project-boilerplate)
- Tags: deep-dive
- Published: 2026-08-20

---

**A GenLayer intelligent contract is a Python class that inherits from `gl.Contract`, declares persistent state using deterministic collection types like `TreeMap` or `DynArray`, and exposes functionality through explicitly decorated public methods while isolating non-deterministic operations behind equivalence-principle wrappers.**

A GenLayer intelligent contract enables developers to combine deterministic blockchain state management with non-deterministic AI capabilities like LLM inference and web scraping. The `genlayerlabs/genlayer-project-boilerplate` repository provides the canonical reference implementation in [`contracts/football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/contracts/football_bets.py), demonstrating how Python classes transform into consensus-safe, AI-native smart contracts. Understanding the precise anatomy of these contracts—from storage declarations to method decorators—is essential for writing secure code that executes correctly across distributed validators.

## Core Structural Components

### Contract Inheritance and Base Class

Every intelligent contract must subclass **`gl.Contract`** to gain access to the GenLayer SDK runtime. This inheritance provides the foundational machinery for state serialization, consensus management, and validator coordination. Without this base class, the contract cannot be deployed or executed on the GenLayer network.

In [`contracts/football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/contracts/football_bets.py) at line 22:

```python
class FootballBets(gl.Contract):

```

### Persistent Storage Declarations

State variables must use **GenLayer-specific collection types** rather than native Python containers to ensure deterministic serialization across all validators. These specialized types handle merkelization and consensus verification automatically.

Common storage types include:

- **`TreeMap[K, V]`** – Sorted key-value mapping for persistent storage
- **`DynArray[T]`** – Dynamic array with deterministic ordering
- **`u256`** – 256-bit unsigned integer for numeric values
- **`Address`** – Validated blockchain address type

In [`contracts/football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/contracts/football_bets.py) at line 23:

```python
bets: TreeMap[Address, TreeMap[str, Bet]]
points: TreeMap[Address, u256]

```

### Constructor Restrictions

The **`__init__`** method is optional but must remain purely deterministic. It cannot perform non-deterministic actions like web calls or LLM prompts; those operations belong in dedicated helper methods invoked after deployment. Use the constructor only for deterministic initialization or configuration constants.

From [`contracts/football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/contracts/football_bets.py) at line 26:

```python
def __init__(self):
    pass

```

### Public Method Decorators

All callable contract methods require explicit **visibility decorators** to declare their intent and execution permissions:

- **`@gl.public.view`** – Read-only operations that do not modify state; execute without gas fees for queries
- **`@gl.public.write`** – State-modifying operations that require consensus and consume gas
- **`@gl.public.write.payable`** – State-modifying operations that accept value transfers

In [`contracts/football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/contracts/football_bets.py) at line 58:

```python
@gl.public.write
def create_bet(self, game_date: str, team1: str, team2: str, predicted_winner: str) -> None:
    sender_address = gl.message.sender_address
    # ... state modification logic

```

### Non-Deterministic Operations and Equivalence Principle

External interactions—such as web scraping or LLM inference—violate traditional blockchain determinism. GenLayer solves this through the **Equivalence Principle**, which wraps non-deterministic calls in consensus mechanisms. These operations must be isolated in private helper methods using `gl.nondet` functions and wrapped with equivalence-principle validators.

Key patterns include:

- **`gl.nondet.web.render`** – Fetches and renders web content
- **`gl.nondet.exec_prompt`** – Executes LLM prompts
- **`gl.eq_principle.strict_eq`** – Requires exact consensus across validators
- **`gl.eq_principle.prompt_comparative`** – Uses LLM to compare outputs for equivalence

In [`contracts/football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/contracts/football_bets.py) lines 29-55, the private method `_check_match` demonstrates this architecture:

```python
def _check_match(self, url: str, team1: str, team2: str) -> dict:
    web_result = gl.nondet.web.render(url)
    # ... processing logic using gl.eq_principle.strict_eq

```

### Data Classes for Complex Storage

Custom data structures require both **`@allow_storage`** and **`@dataclass`** decorators to be storable within GenLayer collection types. The `@allow_storage` marker enables the runtime to serialize and deserialize the class for persistent storage in `TreeMap` or `DynArray` containers.

In [`contracts/football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/contracts/football_bets.py) lines 8-20:

```python
@allow_storage
@dataclass
class Bet:
    id: str
    has_resolved: bool
    game_date: str
    resolution_url: str
    team1: str
    team2: str
    predicted_winner: str
    real_winner: str
    real_score: str

```

### Message Context and Access Control

Access the transaction sender's address via **`gl.message.sender_address`** to implement per-user state management and access control patterns. This provides the calling address for authentication and authorization logic.

In [`contracts/football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/contracts/football_bets.py) at line 70:

```python
sender_address = gl.message.sender_address
self.bets[sender_address] = ...

```

## Minimal Contract Example

The following "Hello World" contract demonstrates the essential structure: inheritance, storage declaration, write/view decorators, and message context.

```python
from genlayer import *

class HelloWorld(gl.Contract):
    # Persistent storage: a simple counter per address

    counters: TreeMap[Address, u256]

    @gl.public.write
    def increment(self) -> None:
        addr = gl.message.sender_address
        self.counters[addr] = self.counters.get(addr, 0) + 1

    @gl.public.view
    def get_counter(self, addr: str) -> u256:
        return self.counters.get(Address(addr), 0)

```

## Production Implementation Reference

The [`contracts/football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/contracts/football_bets.py) file serves as the canonical production example, integrating all structural elements:

- **Complex nested storage**: `TreeMap[Address, TreeMap[str, Bet]]` for user-bet relationships
- **Data class persistence**: The `Bet` dataclass marked with `@allow_storage`
- **Non-deterministic resolution**: Web scraping and LLM inference wrapped in `gl.eq_principle.strict_eq`
- **Access control**: Using `gl.message.sender_address` to isolate user data

This implementation demonstrates how to safely combine external data fetching with deterministic state transitions while maintaining consensus safety across validators.

## Summary

- **Inherit from `gl.Contract`** to activate the GenLayer runtime environment
- **Use GenLayer collection types** (`TreeMap`, `DynArray`, `u256`) for all persistent storage to ensure deterministic serialization
- **Apply visibility decorators** (`@gl.public.view`, `@gl.public.write`) to control method access and state modification permissions
- **Isolate non-deterministic logic** in private methods and wrap with equivalence-principle functions like `gl.eq_principle.strict_eq`
- **Mark dataclasses with `@allow_storage`** to enable storage of complex objects in collections
- **Access caller identity** through `gl.message.sender_address` for user-specific state management

## Frequently Asked Questions

### What makes a Python class a GenLayer intelligent contract?

A Python class becomes a GenLayer intelligent contract by subclassing **`gl.Contract`** and following the storage and method conventions defined in the GenLayer SDK. The inheritance provides consensus machinery, while the use of GenLayer-specific types for storage and decorators for methods ensures the contract can execute deterministically across distributed validators. According to the `genlayerlabs/genlayer-project-boilerplate` source code, without inheriting from `gl.Contract`, the runtime cannot process the class as a deployable contract.

### Why can't I use standard Python lists and dictionaries for storage?

Standard Python containers like `list` and `dict` lack deterministic ordering guarantees and serialization formats required for blockchain consensus. GenLayer contracts use specialized types like **`TreeMap`** and **`DynArray`** because these implement deterministic ordering and merkelization, ensuring all validators reach identical state conclusions after execution. As implemented in [`contracts/football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/contracts/football_bets.py), these types replace native containers to maintain consensus safety.

### How do I handle external API calls in my contract?

External API calls must be isolated in private helper methods using **`gl.nondet.web.render`** or similar non-deterministic functions, then wrapped with equivalence-principle validators like **`gl.eq_principle.strict_eq`**. This pattern ensures that while validators may receive slightly different responses from external services, the network reaches consensus on the canonical result before state modification occurs. The [`football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/football_bets.py) contract demonstrates this in its `_check_match` method, which fetches web data and processes it through consensus mechanisms.

### What is the difference between `@gl.public.view` and `@gl.public.write`?

**`@gl.public.view`** marks read-only methods that do not modify contract state and execute without gas fees, suitable for querying data. **`@gl.public.write`** marks state-modifying operations that require validator consensus, consume gas, and permanently alter the blockchain state. According to the reference implementation, view methods return serializable values immediately, while write methods trigger consensus rounds and equivalence-principle validation for any non-deterministic sub-operations.