> For the complete documentation index, see [llms.txt](https://read.roke.to/roketo-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://read.roke.to/roketo-docs/infrastracture/r2-interchain-incentivisation/r2-interfaces.md).

# R2: Interfaces

### IR2BeaconEmitter.sol

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

/**
 * @title IR2BeaconEmitter
 * @notice Standard interface for emitting business-aware actions to R2 Beacon
 * @dev Implement this interface to make your contract R2 Beacon compatible
 */
interface IR2BeaconEmitter {
    /**
     * @dev Emitted when a business-aware action occurs
     */
    event R2Action(
        address indexed user,
        bytes32 indexed appId,
        bytes32 indexed action,
        uint256 amount,
        bytes data
    );
    
    /// @notice Returns the registered APP_ID for this contract
    function getAppId() external view returns (bytes32);
}

/**
 * @title R2BeaconEmitter
 * @notice Basic implementation of R2 Beacon emission capabilities
 * @dev Inherit this contract to add R2 Beacon support to your DApp
 */
abstract contract R2BeaconEmitter is IR2BeaconEmitter {
    /// @dev Application identifier assigned by R2 Registry
    bytes32 public immutable APP_ID;
    
    /// @dev Custom errors for better gas efficiency and clarity
    error R2Beacon_InvalidAppId();
    error R2Beacon_InvalidActionId();
    
    constructor(bytes32 appId) {
        if (appId == bytes32(0)) {
            revert R2Beacon_InvalidAppId();
        }
        APP_ID = appId;
    }
    
    /// @inheritdoc IR2BeaconEmitter
    function getAppId() external view returns (bytes32) {
        return APP_ID;
    }

    /**
     * @dev Internal function to emit business-aware actions
     * @param action Registered action identifier
     * @param amount Value/amount involved (optional)
     * @param data Additional data (optional)
     */
    function _emitR2Action(
        bytes32 action,
        uint256 amount,
        bytes calldata data
    ) internal virtual {
        if (action == bytes32(0)) {
            revert R2Beacon_InvalidActionId();
        }
        
        emit R2Action({
            user: msg.sender,
            appId: APP_ID,
            action: action,
            amount: amount,
            data: data
        });
    }
    
    /**
     * @dev Utility function to create action identifiers
     * @param actionName Name of the action
     * @return actionId Hash of the action name
     */
    function _createActionId(string calldata actionName) internal pure returns (bytes32 actionId) {
        assembly {
            actionId := keccak256(actionName.offset, actionName.length)
        }
    }
}
```

### Example Implementation

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import {R2BeaconEmitter} from "./R2BeaconEmitter.sol";

contract GameApp is R2BeaconEmitter {
    /// @dev Game-specific actions
    bytes32 public constant GAME_START = keccak256("GAME_START");
    bytes32 public constant GAME_WIN = keccak256("GAME_WIN");
    bytes32 public constant ITEM_PURCHASE = keccak256("ITEM_PURCHASE");
    
    /// @dev Game-specific errors
    error Game_InsufficientPayment();
    error Game_InvalidItem();
    
    constructor(bytes32 appId) R2BeaconEmitter(appId) {}
    
    function startGame(uint256 gameMode) external {
        // Game start logic here
        
        _emitR2Action(
            GAME_START,
            0,
            abi.encode(gameMode)
        );
    }
    
    function purchaseItem(uint256 itemId) external payable {
        // Item purchase logic here
        if (msg.value < getItemPrice(itemId)) {
            revert Game_InsufficientPayment();
        }
        
        _emitR2Action(
            ITEM_PURCHASE,
            msg.value,
            abi.encode(itemId)
        );
    }
    
    function getItemPrice(uint256 itemId) public pure returns (uint256) {
        // Price logic here
        return 0.1 ether;
    }
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://read.roke.to/roketo-docs/infrastracture/r2-interchain-incentivisation/r2-interfaces.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
