R2: Interfaces

IR2BeaconEmitter.sol

// 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

// 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;
    }
}

Last updated