R2: Integration Guide

R2 Beacon Integration Guide for DApp Developers

Overview

R2 Beacon is an omni-chain identity system that tracks and scores user activities across different blockchains. By integrating R2 Beacon into your DApp, you enable "business-aware" actions that contribute to users' identity scores while maintaining privacy and security.

Note: Business-aware actions provide context about user interactions, making them more meaningful than raw transaction data. For example, instead of just recording a transfer of 0.1 ETH, you can specify that a user purchased a subscription.

Prerequisites

  • Solidity ^0.8.24

  • An APP_ID registered with R2 Registry

  • Basic understanding of smart contract development

Quick Start

  1. Install the R2 Beacon contract:

npm install @r2-beacon/contracts
# or
yarn add @r2-beacon/contracts
  1. Import and inherit the R2BeaconEmitter contract:

import {R2BeaconEmitter} from "@r2-beacon/contracts/R2BeaconEmitter.sol";

contract YourDApp is R2BeaconEmitter {
    constructor(bytes32 appId) R2BeaconEmitter(appId) {}
}

Implementation Guide

Basic Integration

  1. First, inherit from the R2BeaconEmitter contract:

contract GameMarketplace is R2BeaconEmitter {
    constructor(bytes32 appId) R2BeaconEmitter(appId) {}
}

Defining Business Actions

Define constants for your business actions using the _createActionId helper or direct keccak256 hashing:

contract GameMarketplace is R2BeaconEmitter {
    bytes32 public constant PURCHASE_ITEM = keccak256("PURCHASE_ITEM");
    bytes32 public constant START_SUBSCRIPTION = keccak256("START_SUBSCRIPTION");
    bytes32 public constant COMPLETE_ACHIEVEMENT = keccak256("COMPLETE_ACHIEVEMENT");

    constructor(bytes32 appId) R2BeaconEmitter(appId) {}
}

Emitting Actions

Use the _emitR2Action function to record business-aware actions:

function purchaseGameItem(uint256 itemId) external payable {
    require(msg.value >= getItemPrice(itemId), "Insufficient payment");
    
    // Your item purchase logic here
    
    _emitR2Action(
        PURCHASE_ITEM,
        msg.value,
        abi.encode(itemId)
    );
}

function startSubscription(uint256 durationInDays) external payable {
    require(msg.value >= getSubscriptionPrice(durationInDays), "Insufficient payment");
    
    // Your subscription logic here
    
    _emitR2Action(
        START_SUBSCRIPTION,
        msg.value,
        abi.encode(durationInDays)
    );
}

Configuration

The R2BeaconEmitter interface accepts the following parameters when emitting actions:

Parameter
Type
Description
Required

action

bytes32

Identifier for the business action

Yes

amount

uint256

Value/amount involved in the action

Yes

data

bytes

Additional context data (ABI encoded)

No

API Reference

Core Functions

_emitR2Action

function _emitR2Action(
    bytes32 action,
    uint256 amount,
    bytes calldata data
) internal virtual

Emits a business-aware action to the R2 Beacon system.

_createActionId

function _createActionId(
    string calldata actionName
) internal pure returns (bytes32 actionId)

Utility function to create action identifiers from strings.

Events

R2Action

event R2Action(
    address indexed user,
    bytes32 indexed appId,
    bytes32 indexed action,
    uint256 amount,
    bytes data
);

Common Issues & Solutions

1. Invalid APP_ID

Issue: Contract deployment fails with R2Beacon_InvalidAppId

Solution: Ensure you've registered your DApp with R2 Registry and are using the correct APP_ID:

// Incorrect
bytes32 appId = bytes32(0); // Will revert

// Correct
bytes32 appId = bytes32(uint256(keccak256("YOUR_APP_NAME")));

2. Action Not Registered

Issue: Actions aren't appearing in the R2 Beacon

Solution: Verify that your action identifiers are properly registered:

// Incorrect
_emitR2Action(bytes32(0), amount, data); // Will revert

// Correct
bytes32 constant MY_ACTION = keccak256("MY_ACTION");
_emitR2Action(MY_ACTION, amount, data);

3. Data Encoding Issues

Issue: Action data is not properly decoded

Solution: Always use abi.encode for complex data types:

// Incorrect
bytes memory data = bytes(abi.encodePacked(value1, value2));

// Correct
bytes memory data = abi.encode(value1, value2);

Warning: Never include sensitive user data in the data parameter. The R2 Beacon is public, and all emitted data will be visible on-chain.

Last updated