docs: Value Transfers and Messages pages#386
Conversation
- External messages: EOA → contract via payable methods, gl.message.value - Internal messages: contract → contract/EOA via emit_transfer (deferred) - Complete escrow example showing both patterns - Payable methods section added to writing-data (JS SDK side) - Funding table: Studio faucet UI, Studionet auto-fund, testnet faucet
New pages: - Value Transfers: payable methods, gl.message.value, sending/receiving GEN, balances, special handlers, JS client examples - Messages: three-tier interaction model (transactions, internal messages, external messages), ghost contracts, gl.message context, accepted vs finalized timing, IC and EVM interfaces Updated: - interacting-with-intelligent-contracts: added value param to emit examples - interacting-with-evm-contracts: added external message context - special-methods: linked to value transfers - writing-data: added payable methods JS section - balances: redirected to value-transfers - _meta.json: reordered navigation
✅ Deploy Preview for genlayer-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThese changes introduce comprehensive documentation for GenLayer intelligent contract value transfers and messaging architecture. The updates include two new detailed guide pages, restructured navigation, consolidated balance-related content, and added examples demonstrating payable methods and value-bearing message operations across different transaction types and execution layers. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (5)
pages/developers/decentralized-applications/writing-data.mdx (1)
91-92: Use bigint literals for wei constants in examples.In JavaScript,
BigInt(10 ** 18)computes10 ** 18as a Number first (IEEE-754 double), which cannot represent all integers exactly beyond 2^53 (~9e15). The Number intermediate loses precision, andBigInt()cannot recover it. Use bigint literals instead:5n * 10n ** 18n.Suggested fix
- value: BigInt(5) * BigInt(10 ** 18), // 5 GEN in wei + value: 5n * 10n ** 18n, // 5 GEN in wei🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pages/developers/decentralized-applications/writing-data.mdx` around lines 91 - 92, The example uses BigInt(5) * BigInt(10 ** 18) which loses precision because 10 ** 18 is computed as a Number first; replace this with bigint literals so the multiplication is done purely in BigInt (e.g., use 5n * 10n ** 18n) and update the value assignment (the symbol to change is the value property in that example).pages/developers/intelligent-contracts/features/value-transfers.mdx (4)
92-92: Clarify "both layers" reference.The phrase "The balance is visible on both layers" could be more explicit about which layers are being referenced (intelligent contract layer and chain layer).
📝 Proposed clarification
-On the GenLayer network, an IC's GEN balance is held by its [ghost contract](/developers/intelligent-contracts/features/messages#ghost-contracts) on the chain layer. `self.balance` reads from this. The balance is visible on both layers. +On the GenLayer network, an IC's GEN balance is held by its [ghost contract](/developers/intelligent-contracts/features/messages#ghost-contracts) on the chain layer. `self.balance` reads from this. The balance is visible on both the intelligent contract layer and the chain layer.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pages/developers/intelligent-contracts/features/value-transfers.mdx` at line 92, The sentence referencing "both layers" is ambiguous; update the text that follows "self.balance reads from this" to explicitly name the two layers as "the intelligent contract layer and the chain layer" (mentioning the ghost contract and self.balance for context) so it reads e.g. "The balance is visible on both the intelligent contract layer and the chain layer." Ensure the terms "ghost contract" and "self.balance" remain referenced for clarity.
55-68: Add explanation for the empty interface pattern.The empty
_Recipientinterface class (lines 56-60) and its usage at line 68 may confuse readers. While the callout at lines 71-73 mentions future simplification, adding a brief comment explaining why the empty interface is currently required would improve clarity.📝 Proposed enhancement
`@gl.evm.contract_interface` class _Recipient: + # Empty interface required for external message routing + # (will be simplified in a future version) class View: pass class Write: pass🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pages/developers/intelligent-contracts/features/value-transfers.mdx` around lines 55 - 68, Add a short inline comment explaining the empty interface pattern: why the _Recipient class with empty View and Write nested classes exists and is used to call _Recipient(Address(recipient)).emit_transfer(value=v) in Faucet.send; mention that it serves as a temporary/explicit contract interface placeholder required by the current gl.evm.contract_interface mechanism and will be simplified later. Place the comment above the _Recipient class definition (referencing _Recipient and Faucet.send) so readers immediately understand the intent and link to the existing call site.
50-69: Consider adding error handling documentation.The documentation covers successful value transfer scenarios comprehensively but doesn't address failure cases such as:
- Insufficient balance in the sending contract
- Target contract reverting during execution
- How failures propagate in internal vs external messages
While not critical for the initial release, adding a brief section on error scenarios would help developers build more robust contracts.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pages/developers/intelligent-contracts/features/value-transfers.mdx` around lines 50 - 69, Add a short "Error handling" subsection after the "Sending Value to an EOA or EVM Contract" example describing failure scenarios: document insufficient balance (what happens when Faucet.send lacks funds and how gl.message.value is validated), target contract reverts (behavior when _Recipient.emit_transfer triggers a revert), and how failures propagate differently for internal vs external messages (finalization semantics and whether exceptions like gl.vm.UserError bubble up or are swallowed). Reference the example symbols Faucet.send, _Recipient.emit_transfer, Address(recipient), and gl.message.value so readers can map behaviors to the provided code snippet and include recommended mitigations (pre-check balances, try/catch patterns or fallback handling) briefly.
7-7: Consider using LaTeX or explicit notation for the exponent.The superscript notation "10¹⁸" may not render consistently across all contexts. Since LaTeX is supported in the Nextra configuration per coding guidelines, consider using
$10^{18}$or explicitly write "10^18" for better compatibility.📝 Proposed alternatives
Option 1 (LaTeX):
-GenLayer uses GEN as its native token. Values are denominated in wei (1 GEN = 10¹⁸ wei). Use the `u256` type for value amounts in contract code. +GenLayer uses GEN as its native token. Values are denominated in wei (1 GEN = $10^{18}$ wei). Use the `u256` type for value amounts in contract code.Option 2 (explicit):
-GenLayer uses GEN as its native token. Values are denominated in wei (1 GEN = 10¹⁸ wei). Use the `u256` type for value amounts in contract code. +GenLayer uses GEN as its native token. Values are denominated in wei (1 GEN = 10^18 wei). Use the `u256` type for value amounts in contract code.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pages/developers/intelligent-contracts/features/value-transfers.mdx` at line 7, Replace the superscript "10¹⁸" with a renderer-safe notation in the sentence about GenLayer/GEN/wei and the `u256` type—either use LaTeX `$10^{18}$` or the plain text `10^18` so the value denomination "1 GEN = 10^18 wei" renders consistently; update the string that currently reads "1 GEN = 10¹⁸ wei" in the value-transfers content to one of these alternatives.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@pages/api-references/genlayer-node.mdx`:
- Around line 812-819: Close the unclosed code/JSON fence immediately before the
gen_dbg_traceTransaction section and demote the heading level by changing the
top-level heading "gen_dbg_traceTransaction" to a level-3 heading (###
gen_dbg_traceTransaction) so the JSON block is properly terminated and the
heading becomes a subsection; locate the heading string
"gen_dbg_traceTransaction" in the document and insert a closing ``` for the open
JSON/code fence just above it, then replace the leading "#" with "###" on the
heading line.
- Around line 826-892: The JSON examples in the gen_dbg_traceTransaction
request/response blocks are escaped (they use "\{" and "\}") which makes them
invalid for copy/paste; update the fenced json blocks for the example request
and response to use normal JSON braces (remove all backslash-escaped braces and
any extraneous escaping around keys/values) so the examples become valid JSON
while preserving the existing fields like "jsonrpc", "method":
"gen_dbg_traceTransaction", "params", and the "result" object with keys such as
"transaction_id", "result_code", "return_data", "genvm_log", "storage_proof",
"run_time", and "eq_outputs".
---
Nitpick comments:
In `@pages/developers/decentralized-applications/writing-data.mdx`:
- Around line 91-92: The example uses BigInt(5) * BigInt(10 ** 18) which loses
precision because 10 ** 18 is computed as a Number first; replace this with
bigint literals so the multiplication is done purely in BigInt (e.g., use 5n *
10n ** 18n) and update the value assignment (the symbol to change is the value
property in that example).
In `@pages/developers/intelligent-contracts/features/value-transfers.mdx`:
- Line 92: The sentence referencing "both layers" is ambiguous; update the text
that follows "self.balance reads from this" to explicitly name the two layers as
"the intelligent contract layer and the chain layer" (mentioning the ghost
contract and self.balance for context) so it reads e.g. "The balance is visible
on both the intelligent contract layer and the chain layer." Ensure the terms
"ghost contract" and "self.balance" remain referenced for clarity.
- Around line 55-68: Add a short inline comment explaining the empty interface
pattern: why the _Recipient class with empty View and Write nested classes
exists and is used to call _Recipient(Address(recipient)).emit_transfer(value=v)
in Faucet.send; mention that it serves as a temporary/explicit contract
interface placeholder required by the current gl.evm.contract_interface
mechanism and will be simplified later. Place the comment above the _Recipient
class definition (referencing _Recipient and Faucet.send) so readers immediately
understand the intent and link to the existing call site.
- Around line 50-69: Add a short "Error handling" subsection after the "Sending
Value to an EOA or EVM Contract" example describing failure scenarios: document
insufficient balance (what happens when Faucet.send lacks funds and how
gl.message.value is validated), target contract reverts (behavior when
_Recipient.emit_transfer triggers a revert), and how failures propagate
differently for internal vs external messages (finalization semantics and
whether exceptions like gl.vm.UserError bubble up or are swallowed). Reference
the example symbols Faucet.send, _Recipient.emit_transfer, Address(recipient),
and gl.message.value so readers can map behaviors to the provided code snippet
and include recommended mitigations (pre-check balances, try/catch patterns or
fallback handling) briefly.
- Line 7: Replace the superscript "10¹⁸" with a renderer-safe notation in the
sentence about GenLayer/GEN/wei and the `u256` type—either use LaTeX `$10^{18}$`
or the plain text `10^18` so the value denomination "1 GEN = 10^18 wei" renders
consistently; update the string that currently reads "1 GEN = 10¹⁸ wei" in the
value-transfers content to one of these alternatives.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 72cde97c-e844-4b9a-96a8-20894968c62d
📒 Files selected for processing (9)
pages/api-references/genlayer-node.mdxpages/developers/decentralized-applications/writing-data.mdxpages/developers/intelligent-contracts/features/_meta.jsonpages/developers/intelligent-contracts/features/balances.mdxpages/developers/intelligent-contracts/features/interacting-with-evm-contracts.mdxpages/developers/intelligent-contracts/features/interacting-with-intelligent-contracts.mdxpages/developers/intelligent-contracts/features/messages.mdxpages/developers/intelligent-contracts/features/special-methods.mdxpages/developers/intelligent-contracts/features/value-transfers.mdx
| The transaction enters the consensus pipeline: activation → proposal → commit → reveal → finalization. | ||
|
|
||
| <Callout type="warning"> | ||
| **Studio:** Transactions are submitted via JSON-RPC, not as EVM calls to a ghost contract. The consensus pipeline is simulated in Python. |
There was a problem hiding this comment.
This is wrong, you still call eth_sendRawTransaction or whatever it's called, the studio emulates the flow. check in the studio exactly how its defined, but as stated is wrong
| **Studio:** Transactions are submitted via JSON-RPC, not as EVM calls to a ghost contract. The consensus pipeline is simulated in Python. | ||
| </Callout> | ||
|
|
||
| ## Internal Messages (IC → IC) |
There was a problem hiding this comment.
Important to understand messages are async. maybe explained in messages, but probably good to have a note here as well
| def transfer(self, to: Address, amount: u256) -> None: ... | ||
|
|
||
| # Read from an EVM contract | ||
| balance = ERC20(token_address).view().balance_of(my_address) |
There was a problem hiding this comment.
how do I actually get my address?
| balance = ERC20(token_address).view().balance_of(my_address) | ||
|
|
||
| # Write to an EVM contract | ||
| ERC20(token_address).emit(value=u256(0)).transfer(recipient, amount) |
There was a problem hiding this comment.
Isn't value optional here?
| The message executes as soon as the parent transaction is accepted by initial consensus, before the appeal window closes. | ||
|
|
||
| <Callout type="warning"> | ||
| If the parent transaction is appealed, the re-execution may emit the message again — potentially multiple times across appeal rounds. The receiving contract must be **idempotent**: it must handle duplicate or unexpected messages gracefully. |
There was a problem hiding this comment.
Also, of course if the parent tx is appealed and in the end has a different outcome, the message might be "invalid" (ie would not have been emitted if this was the original outcome), but it cannot be taken back. contrac design must account for this possibiilty
| other_balance = gl.get_contract_at(addr).balance | ||
|
|
||
| # EVM contract balance | ||
| evm_balance = EthContract(addr).balance |
There was a problem hiding this comment.
This also is the same even if the target is an EOA not a contract
|
|
||
| In `write` methods, `self.balance` reflects the current state including any value received in the current call. In `view` methods, it shows a snapshot without modifications. | ||
|
|
||
| ### Where Balance Lives |
There was a problem hiding this comment.
Not sure if here is the best place to explain, but also, when a message is emitted - balance is taken from the contract, put into the message, and only applied to target when the message is activated
There was a problem hiding this comment.
So value goes from sender balance -> message -> recipient balance
- Fix transaction flow: SDK sends signed addTransaction via eth_sendRawTransaction - Clarify messages are async (caller doesn't wait) - Show how to get own address (gl.message.contract_address) - Make value optional in EVM emit example - Expand appeal risk callout: invalid messages can't be taken back - Explain value flow: sender balance → message → recipient balance - Note EOA transfers use same mechanism as EVM contract calls
Summary
gl.message.value, sending/receiving GEN, balances,__receive__/__handle_undefined_method__, funding accounts, JS client examplesgl.messagecontext, accepted vs finalized timing,@gl.contract_interfaceand@gl.evm.contract_interfaceKey concepts documented
Summary by CodeRabbit