# How to Create Payable Transactions in GenLayer Contracts

> Learn to create payable transactions in GenLayer contracts using @gl.public.write.payable and gl.message.value. Accept native tokens easily and securely in your decentralized applications.

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

---

**To accept native tokens in a GenLayer contract, decorate your method with `@gl.public.write.payable` and read the attached value through `gl.message.value` as a `u256` type.**

GenLayer contracts are written in Python and executed on the GenVM, using the GenLayer SDK to expose public endpoints. Unlike Ethereum's Solidity where `payable` is a keyword, GenLayer implements payable functionality through decorators that signal the virtual machine to expect attached value. This guide demonstrates how to implement payable transactions using the `genlayer-project-boilerplate` repository.

## The Payable Decorator Pattern

In GenLayer, contract methods are classified by their visibility and mutability using decorators from the `genlayer` module. To enable a method to receive native tokens, you must use **`@gl.public.write.payable`** instead of the standard `@gl.public.write`.

According to the repository's [`CLAUDE.md`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/CLAUDE.md) file, the payable decorator explicitly tells the GenVM that the method may receive a value attached to the transaction. This pattern mirrors Solidity's `payable` keyword but leverages Python's decorator syntax for cleaner implementation.

When a payable method is invoked, the transaction's attached value becomes accessible through **`gl.message.value`**, which returns a `u256` representing the token amount in the smallest denomination.

## Step-by-Step Implementation

### Step 1: Apply the Payable Decorator

Import the GenLayer SDK and apply the decorator to your contract method. The decorator must wrap any function intended to receive funds.

```python
from genlayer import *

class PaymentContract(gl.Contract):
    @gl.public.write.payable
    def deposit(self) -> None:
        """Accepts native token deposits."""
        pass

```

### Step 2: Access Transaction Value

Inside the payable method, retrieve the sender's address and the attached amount using the message context object.

```python
sender = gl.message.sender_address
amount = gl.message.value  # Returns u256

```

The `gl.message` object provides transaction metadata, where `value` specifically contains the amount of native tokens sent by the caller.

### Step 3: Validate and Process Payments

Always validate the incoming amount before executing business logic. This prevents underpayment attacks and ensures contract invariants.

```python
@gl.public.write.payable
def buy_item(self, price: u256) -> None:
    sender = gl.message.sender_address
    sent = gl.message.value
    
    if sent < price:
        raise Exception("Insufficient payment")
    
    # Execute purchase logic here

```

### Step 4: Handle Refunds

If the sent amount exceeds the required price, return the excess using **`gl.vm.transfer`**. This built-in SDK function transfers native tokens from the contract balance to the specified address.

```python
excess = sent - price
if excess > 0:
    gl.vm.transfer(sender, excess)

```

## Complete Working Example

The following contract demonstrates a deposit system and a purchase function with refund logic, showcasing all payable patterns found in the boilerplate:

```python
from genlayer import *

class ExamplePayable(gl.Contract):
    # Persistent storage for user balances

    deposits: TreeMap[Address, u256]

    @gl.public.write.payable
    def deposit(self) -> None:
        """Records any amount of native tokens sent to the contract."""
        sender = gl.message.sender_address
        amount = gl.message.value
        
        # Initialize balance if first deposit

        if sender not in self.deposits:
            self.deposits[sender] = 0
        
        # Accumulate deposit

        self.deposits[sender] += amount

    @gl.public.write.payable
    def buy_item(self, price: u256) -> None:
        """Requires exact or excess payment with automatic refunds."""
        sender = gl.message.sender_address
        sent = gl.message.value
        
        # Validate minimum payment

        if sent < price:
            raise Exception("Insufficient payment")
        
        # Process purchase (emit event or update state here)

        
        # Calculate and return surplus

        excess = sent - price
        if excess > 0:
            gl.vm.transfer(sender, excess)

    @gl.public.view
    def get_deposit(self, addr: str) -> u256:
        """Read-only query for a user's balance."""
        return self.deposits.get(Address(addr), 0)

```

## Validation Patterns and Security Considerations

When implementing payable transactions, follow these security best practices derived from the `genlayer-project-boilerplate` structure:

- **Explicit amount checks**: Never assume `gl.message.value` meets your minimum requirements. Always compare against expected prices using explicit conditionals.
- **Overflow protection**: The `u256` type handles large integers, but validate subtraction operations when calculating refunds to prevent underflow.
- **State updates before transfers**: Update contract state before issuing refunds via `gl.vm.transfer` to prevent reentrancy-style issues, though GenVM's architecture provides additional safety guarantees compared to EVM.
- **View functions for balances**: Use `@gl.public.view` decorators for read-only balance queries to avoid unnecessary gas costs and transaction requirements.

The [`contracts/football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/contracts/football_bets.py) file in the repository provides additional context for contract structure, though it focuses on non-payable patterns that you can adapt using the payable decorator syntax documented in [`CLAUDE.md`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/CLAUDE.md).

## Summary

- **Use `@gl.public.write.payable`** to mark methods that accept native tokens, as documented in [`CLAUDE.md`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/CLAUDE.md) lines 70-71.
- **Access value via `gl.message.value`**, which returns a `u256` type representing the attached amount.
- **Validate minimum payments** using explicit comparisons to prevent underpayment vulnerabilities.
- **Issue refunds** using `gl.vm.transfer(address, amount)` to return excess funds to callers.
- **Store balances** in `TreeMap[Address, u256]` structures for efficient persistent storage of user deposits.

## Frequently Asked Questions

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

The `@gl.public.write` decorator creates a state-modifying method that cannot receive native tokens, while `@gl.public.write.payable` explicitly signals the GenVM to allow and process attached value. Without the payable decorator, any transaction sending funds to the method will be rejected by the protocol.

### How do I refund excess payments in a GenLayer contract?

Use the `gl.vm.transfer(recipient_address, amount)` SDK function to send native tokens from the contract balance back to a user. Calculate the excess by subtracting the required price from `gl.message.value`, then conditionally execute the transfer only if the excess amount exceeds zero.

### What type is `gl.message.value` and how is it handled?

`gl.message.value` returns a `u256` type, an unsigned 256-bit integer representing the smallest denomination of the native token. This type supports standard arithmetic operations but requires careful validation when comparing amounts or calculating refunds to ensure precise token accounting.

### Where can I find examples of payable contracts in the GenLayer boilerplate?

While the [`contracts/football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/contracts/football_bets.py) file in the `genlayer-project-boilerplate` repository primarily demonstrates non-payable patterns, the [`CLAUDE.md`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/CLAUDE.md) file contains the definitive payable decorator syntax and usage patterns. Adapt the structure from [`football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/football_bets.py) by adding the `.payable` suffix to your decorators and implementing `gl.message.value` access as shown in this guide.