Intelligent Contracts
Types
Collection Types

Collection Types

GenVM provides storage-compatible collection types that replace Python's built-in collections. These are essential for managing dynamic data structures in Intelligent Contracts.

DynArray (Dynamic Arrays)

DynArray[T] replaces Python's list[T] and provides dynamic array functionality with storage compatibility.

Basic DynArray Usage

class ArrayOperations(gl.Contract):
    # Simple arrays
    numbers: DynArray[u256]
    names: DynArray[str]
    addresses: DynArray[Address]
    
    # Nested arrays
    matrix: DynArray[DynArray[u256]]
    
    def __init__(self):
        pass
    
    @gl.public.write
    def add_number(self, num: int):
        self.numbers.append(num)
    
    @gl.public.write
    def add_name(self, name: str):
        self.names.append(name)
    
    @gl.public.write
    def add_address(self, addr: str):
        address = Address(addr)
        self.addresses.append(address)
    
    @gl.public.view
    def get_number_at(self, index: int) -> int:
        if index < len(self.numbers):
            return self.numbers[index]
        return u256(0)
    
    @gl.public.view
    def get_array_length(self) -> int:
        return u256(len(self.numbers))
    
    @gl.public.write
    def remove_last(self):
        if len(self.numbers) > 0:
            self.numbers.pop()
    
    # Matrix operations
    @gl.public.write
    def add_row(self, row: DynArray[int]):
        self.matrix.append(row)
    
    @gl.public.view
    def get_matrix_element(self, row: int, col: int) -> int:
        if row < len(self.matrix) and col < len(self.matrix[row]):
            return self.matrix[row][col]
        return u256(0)

DynArray with Custom Types

from genlayer import *
from dataclasses import dataclass
 
import json
import typing
 
@allow_storage
@dataclass
class User:
    name: str
    age: u8
    balance: u256
 
class UserArrayOperations(gl.Contract):
    users: DynArray[User]
    user_ids: DynArray[str]
    
    def __init__(self):
        pass
    
    @gl.public.write
    def add_user(self, name: str, age: int, balance: int):
        user = User(name=name, age=age, balance=balance)
        self.users.append(user)
        self.user_ids.append(f"user_{len(self.users)}")
    
    @gl.public.view
    def find_user_by_name(self, name: str) -> TreeMap[str, typing.Any]:
        for user in self.users:
            if user.name == name:
                return user
        return User("", u8(0), u256(0))

TreeMap (Ordered Maps)

TreeMap[K, V] replaces Python's dict[K, V] and provides ordered map functionality with storage compatibility.

Basic TreeMap Usage

class MapOperations(gl.Contract):
    # Simple maps
    balances: TreeMap[Address, u256]
    names: TreeMap[str, str]
    flags: TreeMap[str, bool]
    
    def __init__(self):
        pass
    
    @gl.public.write
    def set_balance(self, address: str, amount: int):
        account = Address(address)
        self.balances[account] = amount
    
    @gl.public.write
    def set_name(self, key: str, name: str):
        self.names[key] = name
    
    @gl.public.view
    def get_balance(self, address: str) -> int:
        account = Address(address)
        return self.balances.get(account, u256(0))
    
    @gl.public.view
    def get_name(self, key: str) -> str:
        return self.names.get(key, "")
    
    @gl.public.view
    def has_balance(self, address: str) -> bool:
        account = Address(address)
        return account in self.balances

TreeMap with Complex Values

@allow_storage
@dataclass
class UserProfile:
    name: str
    email: str
    balance: u256
    is_active: bool
 
class UserProfileMap(gl.Contract):
    profiles: TreeMap[Address, UserProfile]
    permissions: DynArray[str]
    user_permissions: TreeMap[Address, DynArray[str]]
    
    def __init__(self):
        pass
    
    @gl.public.write
    def create_profile(self, name: str, email: str):
        address = gl.message.sender_address
        profile = UserProfile(
            name=name,
            email=email,
            balance=u256(0),
            is_active=True
        )
        self.profiles[address] = profile
        self.user_permissions[address] = self.permissions
    
    @gl.public.write
    def add_permission(self, user: str, permission: str):
        account = Address(user)
        if account in self.user_permissions:
            self.user_permissions[account].append(permission)
    
    @gl.public.view
    def get_profile(self, address: str) -> TreeMap[str, typing.Any]:
        account = Address(address)
        return self.profiles.get(account, UserProfile("", "", u256(0), False))
    
    @gl.public.view
    def has_permission(self, user: str, permission: str) -> bool:
        account = Address(user)
        if account in self.user_permissions:
            return permission in self.user_permissions[account]
        return False