RaylsErc721DvpHandler

RaylsErc721DvpHandler is the abstract base contract for ERC721 NFTs that participate in cross-chain Delivery vs. Payment (DvP) swaps in the Rayls Sovereign ledger. The seller deposits an NFT and initiates a swap offering it in exchange for Enygma tokens from a buyer on a different Rayls Node.

Inheritance: RaylsApp, ERC721, Initializable, ReentrancyGuard, RaylsAccessManaged

See Rayls Sovereign internal DvP for the full cross-chain DvP flow overview.


Minimal implementation

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

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

contract MyDvpNFT is RaylsErc721DvpHandler {
    constructor(
        string memory _uri,
        string memory _name,
        string memory _symbol,
        address _endpoint,
        address _raylsNodeEndpoint,
        address _userGovernance,
        address _owner
    )
        RaylsErc721DvpHandler(
            _uri,
            _name,
            _symbol,
            _endpoint,
            _raylsNodeEndpoint,
            _userGovernance,
            _owner,
            false
        )
    {}
}

Constructor parameters

ParameterDescription
_uriBase URI for token metadata
_nameERC721 collection name
_symbolERC721 collection symbol
_endpointRayls Sovereign endpoint, which routes messages to other Rayls Nodes through the Private Network Hub
_raylsNodeEndpointRayls Sovereign endpoint for the Rayls Public Chain
_userGovernanceRBAC contract that manages user roles and permissions within the Rayls Sovereign ledger
_ownerAddress granted the Owner role
_isCustomTrue for the custom-token issuer flow, false for the standard template path

Token registration lifecycle

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

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

Once the registration is approved, the relayer calls receiveResourceId() on your contract automatically, after which the token can participate in DvP swaps.


DvP flow

Step 1 — Deposit the NFT

The seller locks their token into the DvP contract before initiating a swap.

function depositIntoDvp(uint256 _tokenId) public virtual nonReentrant

After this call, lockedForDvp[_tokenId] is set to true, and the NFT cannot be transferred until the swap is either completed or cancelled.

Step 2 — Initiate the cross-chain swap

function swapWithDvpForEnygma(
    uint256 _nftId,
    uint256 _enygmaAmount,
    bytes32 _enygmaResourceId,
    uint256 _destChainId,
    bytes32 _sharedId,
    uint64 _validityTime
) public virtual nonReentrant
ParameterDescription
_nftIdID of the locked NFT to offer
_enygmaAmountAmount of Enygma tokens requested from the buyer
_enygmaResourceIdResource ID of the Enygma contract on the buyer's Sovereign ledger
_destChainIdChain ID of the buyer's Rayls Node
_sharedIdUnique identifier shared by both swap legs
_validityTimeSeconds until the swap expires (pass 0 for the contract default)

Step 3a — Swap completed (relayer-triggered)

The relayer calls this function automatically once both legs of the swap succeed, so you should not call it yourself.

// restricted — RELAYER role only
function dvpSwapCompleted(
    SharedObjects.DvpSwapCompletedParams calldata params
) public virtual restricted nonReentrant

When it executes, the NFT is burned from the seller, minted on the buyer's Sovereign ledger, and the Enygma payment is released.

Step 3b — Cancel the swap

Call cancelSwap if the swap has expired or the counterparty did not respond.

function cancelSwap(
    bytes32 _sharedId,
    uint256 _toChainId,
    uint256 _nftId,
    uint256 _enygmaAmount,
    bytes32 _enygmaResourceId
) public virtual nonReentrant

Once the cancellation is registered, call withdrawFromDvp to recover the locked NFT:

function withdrawFromDvp(uint256 _tokenId) public virtual nonReentrant

The relayer finalises the unlock by calling unlockFromDvp, which returns the NFT to the seller's available balance.


Mint and burn

// Owner role only
function mint(address _to, uint256 _id, SharedObjects.Dvp721ExtraData[] memory _extraDatas)
    public virtual restricted nonReentrant

// Owner role only
function burn(uint256 _id) public virtual restricted nonReentrant

Swap validity time

// Owner role only
function setSwapValidityTime(uint64 _validityTime) public virtual restricted

Access control summary

RoleFunctions
Ownermint, burn, submitTokenUpdate, setSwapValidityTime
RELAYERdvpSwapCompleted, unlockFromDvp, notifySenderWithPNCommunicator, notifySenderAndReceiverWithPNCommunicator
MESSAGE_EXECUTORunlock, receiveResourceId, MintFromSwapDvp
Any addressdepositIntoDvp, swapWithDvpForEnygma, cancelSwap, withdrawFromDvp

Did this page help you?