Installing the Rayls SDK

Prerequisites

The SDK must be installed in a project targeting a Rayls Sovereign ledger, meaning an EVM-compatible chain with a Rayls endpoint smart contract configured.

For questions, contact Rayls here.


Installation

# npm
npm install @rayls/contracts

# pnpm
pnpm add @rayls/contracts

Current version: 2.6.3-nightly.2

All contracts must use the fixed pragma:

pragma solidity 0.8.24;

What the SDK provides

The SDK is a set of abstract Solidity contracts that you inherit in order to build tokens and cross-chain apps in a Rayls Sovereign ledger:

ContractPurpose
RaylsAppBase for all cross-chain apps, providing _raylsSend and _raylsSendToResourceId
RaylsErc20HandlerERC20 token with teleport support
RaylsErc721HandlerERC721 NFT with teleport support
RaylsErc1155HandlerERC1155 multi-token with teleport support
RaylsEnygmaHandlerEnygma settlement token with batch cross-chain transfers and DvP
RaylsErc721DvpHandlerERC721 DvP asset-leg handler
RaylsErc1155DvpHandlerERC1155 DvP asset-leg handler

See Building using Rayls SDK for the full contract reference.


Setting up a token

Extend RaylsErc20Handler and pass all required params to the parent constructor:

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

import "@rayls/contracts/tokens/RaylsErc20Handler.sol";

contract MyToken is RaylsErc20Handler {
    constructor(
        string memory _name,
        string memory _symbol,
        address _endpoint,
        address _raylsNodeEndpoint,
        address _userGovernance,
        address _owner
    )
        RaylsErc20Handler(
            _name,
            _symbol,
            _endpoint,
            _raylsNodeEndpoint,
            _userGovernance,
            _owner,
            false   // isCustom: false for standard tokens
        )
    {
        // optional: mint initial supply
        // _mint(msg.sender, 1_000_000 * 10 ** 18);
    }
}

The constructor parameters:

ParameterDescription
_endpointEndpoint for cross-Sovereign messaging
_raylsNodeEndpointEndpoint for Public Chain bridging
_userGovernanceRBAC contract for user roles within Rayls Sovereign
_ownerAddress granted the Owner role (mint, burn)

Token registration

After deploying, call registerToken on the TokenRegistryReplica system contract in the Rayls Sovereign ledger:

TokenRegistryReplica.registerToken(tokenAddress, SharedObjects.ErcStandard.ERC20, false)

Once the Private Network Operator approves it, the relayer calls receiveResourceId() on your contract automatically, and the teleport functions are then ready to use.


Minting tokens

// Owner role only — also notifies the Private Hub's TokenRegistry
function mint(address to, uint256 value) public virtual restricted

mint and burn are protected by restricted, which is role-based access control. The Owner role is granted to the address passed as _owner at deployment.

Access control: Rayls uses RaylsAccessManaged rather than Ownable. Privileged functions use the restricted modifier, which checks roles through RaylsAccessManagerV1 in the Rayls Sovereign ledger. There is no onlyOwner in the current SDK.


Teleporting tokens

Vanilla teleport (VT20)

Burns on source, mints on destination, with no revert mechanism.

function teleport(address to, uint256 value, uint256 chainId) public virtual returns (bool)

Atomic teleport (AT20)

Tokens are locked on the destination until the transfer is confirmed. Where the destination fails, the relayer reverts the operation and returns the tokens to the sender.

function teleportAtomic(address to, uint256 value, uint256 destinationChainId) public virtual returns (bool)

Sending arbitrary messages

For custom cross-chain logic that does not involve tokens, extend RaylsApp directly:

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

import "@rayls/contracts/RaylsApp.sol";

contract HelloWorldContract is RaylsApp {
    string public message;

    constructor(
        address _endpoint,
        address _raylsNodeEndpoint,
        address _userGovernance
    ) RaylsApp(_endpoint, _raylsNodeEndpoint, _userGovernance) {}

    function sendGreeting(uint256 destChainId, address destContract, string memory _msg) external {
        _raylsSend(
            destChainId,
            destContract,
            abi.encodeWithSignature("receiveGreeting(string)", _msg)
        );
    }

    // In production: mark restricted and register selector under MESSAGE_EXECUTOR
    function receiveGreeting(string memory _msg) public {
        message = _msg;
    }
}

The sender deploys this contract in their own Rayls Sovereign ledger and the receiver deploys it in theirs. The sender then calls sendGreeting with the receiver's chain ID and contract address, and the relayer delivers the payload and calls receiveGreeting on the receiver.

Security: Receive functions should be marked restricted in production so that only the Rayls relayer (MESSAGE_EXECUTOR role) can invoke them. See RaylsApp for details.


What’s Next

Did this page help you?