RaylsErc20Handler
RaylsErc20Handler is the abstract base contract for ERC20 tokens in the Rayls Sovereign ledger. Extend it to create a fungible token that can be minted, burned and teleported cross-chain.
Inheritance: RaylsApp, ERC20, Initializable, RaylsAccessManaged
Minimal implementation
// 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
)
{}
}Constructor parameters
| Parameter | Description |
|---|---|
_name | ERC20 token name |
_symbol | ERC20 token symbol |
_endpoint | Rayls Sovereign endpoint, which routes messages to other Rayls Nodes through the Private Network Hub |
_raylsNodeEndpoint | Rayls Sovereign endpoint for the Rayls Public Chain |
_userGovernance | RBAC contract that manages user roles and permissions within the Rayls Sovereign ledger |
_owner | Address granted the Owner role (mint, burn, submitTokenUpdate) |
The last parameter (false) marks this as a standard token. Pass true only if you are overriding the default transfer behaviour.
Token registration lifecycle
After deploying your token, call registerToken on the TokenRegistryReplica system contract in the Rayls Sovereign ledger to submit it for approval:
// Call on the TokenRegistryReplica system contract (not on your token)
TokenRegistryReplica.registerToken(
address tokenAddress, // your deployed token contract
SharedObjects.ErcStandard ercStandard, // e.g. ErcStandard.ERC20
bool isCustom // false for standard handlers
)This sends a cross-chain message to the TokenRegistry on the Private Network Hub. Once the Private Network Operator approves the registration, the relayer calls receiveResourceId() on your token contract automatically:
// Called by the relayer (MESSAGE_EXECUTOR role) after approval — do NOT call manually
function receiveResourceId(bytes32 _resourceId) public virtual restrictedOnce receiveResourceId has been called, your token holds a resourceId and is ready for cross-chain teleports.
Mint and burn
// Owner role only
function mint(address to, uint256 value) public virtual restricted
// Owner role only
function burn(address from, uint256 value) public virtual restrictedBoth functions report the balance change automatically to the TokenRegistry on the Private Network Hub, using _submitTokenUpdate.
Balance updates
// Owner role only — manually trigger a balance sync to the Private Hub
function submitTokenUpdate(
SharedObjects.BalanceUpdateType updateType,
uint256 amount
) public virtual restrictedBalanceUpdateType is an enum with the values MINT and BURN. You rarely need to call this function directly, because mint and burn call it internally.
Teleport functions
All teleport functions burn tokens on the source chain and trigger a mint on the destination chain.
Vanilla teleport (VT20)
This is a simple burn and mint with no revert mechanism.
// Burn from msg.sender, mint on destination
function teleport(address to, uint256 value, uint256 chainId) public virtual returns (bool)
// Burn from `from` (requires prior approval from `from`)
function teleportFrom(address from, address to, uint256 value, uint256 chainId) public virtual returns (bool)Atomic teleport (AT20)
Tokens are locked on the destination until the transfer is confirmed, and if the destination fails, the relayer reverts the operation and restores the sender's tokens.
// Atomic burn from msg.sender
function teleportAtomic(address to, uint256 value, uint256 destinationChainId) public virtual returns (bool)
// Atomic burn from `from` (requires prior approval)
function teleportAtomicFrom(address from, address to, uint256 value, uint256 destinationChainId) public virtual returns (bool)Teleport to Public Chain
Send tokens from the Rayls Sovereign ledger to an address on the Rayls Public Chain. The caller must be a registered user (onlyRegisteredUsers).
function teleportToPublicChain(address to, uint256 value, uint256 destinationChainId)
public virtual onlyRegisteredUsers returns (bool)Tokens are locked in the Rayls Sovereign ledger until the Public Chain mint is confirmed, and if that mint fails, revertTeleportToPublicChain restores the balance.
Receive functions (called by the relayer)
These functions are marked restricted and can only be called by the MESSAGE_EXECUTOR role, so you do not call them directly.
| Function | Trigger |
|---|---|
receiveTeleport(address to, uint256 value) | Vanilla teleport arrived, so tokens are minted |
receiveTeleportAtomic(address to, uint256 value) | Atomic teleport arrived, so tokens are minted and locked pending confirmation |
receiveTeleportFromPublicChain(address to, uint256 value) | Transfer from the Public Chain into the Rayls Sovereign ledger arrived, so tokens are unlocked |
revertTeleportMint(address to, uint256 value) | Atomic teleport reverted on the source chain, so tokens are re-minted |
revertTeleportBurn(address to, uint256 value) | Atomic teleport reverted on the destination chain, so tokens are unlocked and burned |
revertTeleportToPublicChain(address from, uint256 amount) | Public Chain mint failed, so tokens are unlocked |
unlock(address to, uint256 amount) | Atomic teleport confirmed, so locked tokens are released |
Access control summary
| Role | Functions |
|---|---|
| Owner | mint, burn, submitTokenUpdate |
| MESSAGE_EXECUTOR | receiveTeleport, receiveTeleportAtomic, receiveTeleportFromPublicChain, revertTeleportMint, revertTeleportBurn, revertTeleportToPublicChain, unlock, receiveResourceId |
| Any address | teleport, teleportFrom, teleportAtomic, teleportAtomicFrom, teleportToPublicChain* |
teleportToPublicChainadditionally requiresonlyRegisteredUsers.
Roles are managed by the RBAC contract (_userGovernance) configured at deployment. See RaylsApp for details.
Updated 6 days ago
