Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ npm install genlayer-js

Here’s how to initialize the client and connect to the GenLayer Studio:

- **[Reading a transaction](../intelligent-contracts/advanced-features/contract-to-contract-interaction)**: Understand how to query transactions on the GenLayer network.
- **[Reading a transaction](../intelligent-contracts/features/interacting-with-intelligent-contracts)**: Understand how to query transactions on the GenLayer network.
- **[Reading a contract](/developers/decentralized-applications/reading-data)**: Discover how to read data from intelligent contracts on GenLayer.
- **[Writing a contract](../intelligent-contracts/tools/genlayer-studio/contract-state)**: Learn how to write data to intelligent contracts on GenLayer.

Expand Down
2 changes: 1 addition & 1 deletion pages/developers/intelligent-contracts/_meta.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"introduction": "Introduction to Intelligent Contracts",
"features": "Feature List",
"tooling-setup": "Tooling Setup",
"first-contract": "Your First Contract",
"types": "Types",
Expand All @@ -9,7 +10,6 @@
"debugging": "Debugging",
"deploying": "Deploying",
"crafting-prompts": "Crafting Prompts",
"advanced-features": "Advanced Features",
"security-and-best-practices": "Security and Best Practices",
"examples": "Examples",
"tools": "Tools",
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

16 changes: 16 additions & 0 deletions pages/developers/intelligent-contracts/features/_meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"features": "Features",
"storage": "Storage",
"error-handling": "Error Handling",
"upgradability": "Upgradability",
"balances": "Balances",
"interacting-with-intelligent-contracts": "Interacting with Intelligent Contracts",
"interacting-with-evm-contracts": "Interacting with EVM Contracts",
"vector-storage": "Vector Storage",
"debugging": "Debugging",
"special-methods": "Special Methods",
"random": "Random",
"non-determinism": "Non-determinism",
"calling-llms": "Calling LLMs",
"web-access": "Web Access"
}
45 changes: 45 additions & 0 deletions pages/developers/intelligent-contracts/features/balances.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Callout } from "nextra-theme-docs";

# Balances

## Getting Contract Balance

Access your contract's balance using `self.balance` within contract methods:

```python
class Contract(gl.Contract):
@gl.public.view
def get_balance(self):
return self.balance # Shows contract's current balance
```

## Getting Another Contract's Balance

Get any contract's balance by address:

```python
other_contract = gl.get_contract_at(contract_address)
print(other_contract.balance)
```

## Transferring Funds

Transfer funds from sender to current contract:

```python
other_contract = gl.get_contract_at(gl.message.sender_address)
other_contract.emit_transfer(value=u256(5))
other_contract.emit(value=u256(5), on='finalized').transfer(Address("0x..."))
```

## Balance Context

Balance behavior depends on execution context:
- In `write` methods: `self.balance` reflects actual contract balance after state changes
- In `view` methods: Balance shows current state without modifications
- Transfers can only occur in write context

<Callout type="warning">
If message is emitted on acceptance and previous transaction gets successfully appealed after the emit,
the balance will be decremented nonetheless
</Callout>
Comment on lines +25 to +45
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

GenLayer GenVM intelligent contract transfer funds emit_transfer API

💡 Result:

Short answer

  • GenLayer's GenVM exposes ContractAt.emit_transfer(...) to send native-token transfers when calling another contract; it's a "nameless" transfer (no method name) and you pass value as an argument. Recipients handle these by implementing receive and senders attach value or use @gl.public.write.payable for payable methods. [1][2][3]

Minimal example (Python Intelligent Contract)

  • Sender:
    from genlayer import *
    class Sender(gl.Contract):
    @gl.public.write
    def pay(self, to: Address, amount: int):
    gl.ContractAt(to).emit_transfer(value=amount)
  • Receiver:
    from genlayer import *
    class Receiver(gl.Contract):
    def receive(self):
    # called when contract receives a nameless transfer
    payer = gl.message.sender
    amt = gl.message.value
    # handle funds...

Key notes

  • Use @gl.public.write.payable on methods that should accept incoming value. [1][3]
  • Contract balance available via contract.balance; outgoing transfers use ContractAt(...).emit_transfer(value=...). [1][2]
  • See GenLayer docs for full API, types, and simulator testing. [1][2]

Sources
[1] GenLayer — Working With Balances (emit_transfer, payable, receive).
[2] GenLayer SDK — gl.ContractAt and emit_transfer API.
[3] GenLayer Docs — Your First Contract (decorators, payable usage).


🌐 Web query:

GenLayer finalized vs accepted contract event emission semantics

💡 Result:

Short answer — Accepted = tentative; Finalized = irreversible.

  • "Accepted" means validators reached majority but the finality/appeal window is still open. State and logs at Accepted can be appealed/recomputed and therefore may be be rolled back or changed. Use Accepted if you need faster, optimistic visibility but can tolerate reversions. [1][2][3]

  • "Finalized" means the appeal window passed (or fast-finality paid) and the transaction is immutable — contract state, messages and any durable outputs are permanent. Emit events/messages only when you require irreversible guarantees. [2][3]

  • GenLayer supports message-based contract-to-contract writes and lets developers choose when a message is emitted; messages emitted as part of an Accepted-state execution can be subject to appeals, while messages/emissions tied to Finalized state are non-reversible. For cross-contract interaction the docs explicitly point out message emission semantics to avoid cascading rollbacks. [4][2]

If you want, tell me which event/message in your contract you plan to emit and I’ll advise whether to emit at Accepted (optimistic, faster) or wait for Finalized (durable, safe), and show code examples. [1][2][3][4]

Sources:

  1. GenLayer — Transaction Processing / Statuses. [docs.genlayer.com]. [1]
  2. GenLayer — Finality / Finality Window (appeals, fast finality). [docs.genlayer.com]. [2]
  3. GenLayer API — gen_getContractState (status param: "accepted" or "finalized"). [docs.genlayer.com]. [3]
  4. Explanation of GenLayer contract-to-contract messaging and non-reversibility choices. (Medium article). [4]

Code snippet has two issues: incorrect transfer API syntax and misleading warning semantics.

The .emit(..., on='finalized').transfer(...) pattern is not part of the documented GenLayer API. Use the canonical emit_transfer(value=...) method only. Additionally:

  • The snippet description "Transfer funds from sender to current contract" is backwards—transfers go TO another contract.
  • The warning callout mentions "emitted on acceptance" but references on='finalized'; these are contradictory. Transfers emitted during Accepted state can be appealed/rolled back; Finalized emissions are irreversible. Clarify which context applies and align the warning accordingly.
🤖 Prompt for AI Agents
pages/developers/intelligent-contracts/features/balances.mdx lines 25-45: the
sample uses a non-existent emit(..., on='finalized').transfer(...) pattern and
the prose/warning misstates transfer direction and lifecycle semantics; replace
the chained emit call with the documented emit_transfer(value=...) API, update
the explanatory text to state that transfers move funds from the current
contract to another contract (or vice versa depending on the example), and fix
the callout to reference the correct lifecycle state (use "emitted on
acceptance" and on='accepted' if an emission can be appealed/rolled back, or use
"emitted on finalized" and on='finalized' if irreversible) so example code and
warning consistently match the chosen state.

77 changes: 77 additions & 0 deletions pages/developers/intelligent-contracts/features/calling-llms.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Callout } from 'nextra-theme-docs'

# Calling LLMs

## Basic LLM Calls

Execute prompts using large language models:

```python
def llm_call():
response = gl.nondet.exec_prompt("Answer this question")
return response.strip().lower()

# Consensus ensures consistent LLM responses
answer = gl.eq_principle.strict_eq(llm_call)
```

## JSON Response Format

Request structured responses from LLMs:

```python
def structured_llm_call():
prompt = """
Return a JSON object with these keys:
- "score": random integer from 1 to 100
- "status": either "active" or "inactive"
"""
return gl.nondet.exec_prompt(prompt, response_format='json')

result = gl.eq_principle.strict_eq(structured_llm_call)
score = result['score'] # Access JSON fields
```

This approach guarantees that `exec_prompt` returns a valid JSON object, however
correspondence to the specified format depends on the underlying LLM.

Comment on lines +18 to +37
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Make JSON expectations explicit (avoid implying schema validation).
Line 33-35 correctly notes that “valid JSON” ≠ “matches your schema”, but the examples should also reflect that: the prompt in validated_call doesn’t require a number key, yet the code assumes response['number']. Consider tightening the prompt (and optionally showing a defensive .get() + error).

 def validated_call():
     response = gl.nondet.exec_prompt(
-        "Generate a number between 1 and 100",
+        'Return JSON like {"number": <integer 1..100>}. Only return JSON.',
         response_format='json'
     )
 
     # Validate the response
-    if response['number'] < 1 or response['number'] > 100:
-        raise Exception(f"Invalid number: {response['number']}")
+    number = response.get("number")
+    if not isinstance(number, int) or number < 1 or number > 100:
+        raise ValueError(f"Invalid number: {number!r}")
 
-    return response['number']
+    return number

Also applies to: 54-72

## Image Processing

Process images with vision models:

```python
def vision_analysis():
prompt = "Describe what you see in this image"
image_data = b"\x89PNG..."
return gl.nondet.exec_prompt(
prompt,
images=[image_data]
)

description = gl.eq_principle.strict_eq(vision_analysis)
```

<Callout type="warning">
Limit of images is two
</Callout>


Comment on lines 42 to 58
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix broken Python snippet (image_data bytes literal) and clarify the image limit text.
Line 43 has a mismatched quote (b"\x89PNG...') which will not run if copied. Also, consider making the “2 images” constraint a callout/note and phrasing it as a hard limit (if it is).

 def vision_analysis():
     prompt = "Describe what you see in this image"
-    image_data = b"\x89PNG...'
+    image_data = b"\x89PNG..."
     return gl.nondet.exec_prompt(
         prompt,
         images=[image_data]
     )
🤖 Prompt for AI Agents
In pages/developers/intelligent-contracts/features/calling-llms.mdx around lines
40 to 53, the Python snippet has a mismatched quote in the image_data bytes
literal and the surrounding text about image limits is vague; fix the code by
using a valid, consistently quoted bytes literal placeholder (e.g.,
b'\x89PNG...' or b"\x89PNG...") so it’s syntactically correct, and update the
prose to add a clear callout/note stating the hard limit of 2 images (phrase it
as a strict limit) so readers know they may pass at most two images.

## Response Validation

Validate and process LLM responses:

```python
def validated_call():
response = gl.nondet.exec_prompt(
"Generate a number between 1 and 100",
response_format='json'
)

# Validate the response
if response['number'] < 1 or response['number'] > 100:
raise Exception(f"Invalid number: {response['number']}")

return response['number']

result = gl.eq_principle.strict_eq(validated_call)
```
31 changes: 31 additions & 0 deletions pages/developers/intelligent-contracts/features/debugging.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Callout } from "nextra-theme-docs";

# Debugging

## Print Statements

Use `print` calls for basic debugging, which will be present in node or studio output.

Use `gl.trace` to include time stamps in the output (it will be written to genvm_log instead of stdout)

## Profiling

There is also `gl.trace_time_micro` which returns timestamp in the GenVM debug mode. Default bootloader includes
possibility to enable profiling by setting environment variable `GENLAYER_ENABLE_PROFILER=true`.

```python
# {
# "Seq": [
# { "SetEnv": { "name": "GENLAYER_ENABLE_PROFILER", "value": "true" } },
# { "Depends": "py-genlayer:test" }
# ]
# }
```

This will output base-64 encoded gzip-compressed profiling data to stderr after every single VM execution

## Attaching a Debugger

<Callout type="warning" emoji="🏗️">
Unfortunately, attaching a debugger to a running Intelligent Contract is not supported yet
</Callout>
Loading