RaylsErc1155Handler
Definition
In Rayls SDK, apart from what you can build using the base contract RaylsApp, we offer other contracts to complement and ease your implementations. Here, you will see the handler for Erc1155, which inherits from RaylsApp — to become integrated to Rayls — and also, of course, from Erc1155.
Methods
If you wish to explore the contract on your own, it can be found in the section below. Here we'll highlight only some of the main methods.
Constructor
abstract contract RaylsErc1155Handler is
RaylsApp,
ERC1155,
Initializable,
Ownable
{
string private _uri;
string public name;
address balanceCommitmentsContract;
mapping(address => mapping(uint256 => uint256)) lockedAmount;
mapping(uint256 => bool) alreadySentDeployInstructions;
/**
* @dev Constructor to initialize the RaylsCore with the provided endpoint and owner.
* @param _endpoint The address of the Rayls endpoint.
* @param _owner The address of the owner of the RaylsCore.
*/
constructor(
string memory uri,
string memory _name,
address _endpoint,
address _owner
) ERC1155(uri) RaylsApp(_endpoint) Ownable(_owner) {
_uri = uri;
name = _name;
_disableInitializers();
}
// ...
}
As we can see, we have the standard uri to represent the ERC1155 in the constructor, a _name, the _endpoint for the RaylsApp and an address to set as the _owner
initialize
function initialize(
string memory uri,
string memory _name
) public virtual initializer {
address _owner = _getOwnerAddressOnInitialize();
address _endpoint = _getEndpointAddressOnInitialize();
resourceId = _getResourceIdOnInitialize();
// ERC1155 initizalization
_uri = uri;
name = _name;
// RaylsApp Initialization
_transferOwnership(_owner);
endpoint = IRaylsEndpoint(_endpoint);
}
As this contract can be used by proxy contracts, we need to do the initializations in a standard methods, not on the constructor (otherwise the proxy contract state won't be updated properly).
sendTeleport
function sendTeleport(
uint256 chainId,
bytes memory _payload,
bytes memory _lockDataPayload,
bytes memory _revertDataPayloadSender,
bytes memory _revertDataPayloadReceiver,
BridgedTransferMetadata memory metadata
) internal {
require(resourceId != bytes32(0), "Token not registered.");
_raylsSendToResourceId(
chainId,
resourceId,
_payload,
_lockDataPayload,
_revertDataPayloadSender,
_revertDataPayloadReceiver,
metadata
);
}
The base of every following teleport method: It basically proxies the request to the RaylsApp method _raylsSendToResourceId, which sends a payload (including possible atomic revert mechanisms) cross-chain.
teleport
function teleport(
address to,
uint256 id,
uint256 value,
uint256 chainId,
bytes memory data
) public virtual returns (bool) {
_burn(msg.sender, id, value);
BridgedTransferMetadata memory metadata = BridgedTransferMetadata({
assetType: RaylsBridgeableERC.ERC1155,
id: id,
from: msg.sender,
to: to,
amount: value
});
sendTeleport(
chainId,
abi.encodeWithSignature(
"receiveTeleport(address,uint256,uint256,bytes)",
to,
id,
value,
data
),
bytes(""),
abi.encodeWithSignature(
"revertTeleportMint(address,uint256,uint256,bytes)",
msg.sender,
id,
value,
data
),
abi.encodeWithSignature(
"revertTeleportBurn(address,uint256,uint256)",
msg.sender,
id,
value
),
metadata
);
return true;
}
A method to teleport (send cross-chain) an amount of the token. This is a vanilla teleport, which means there are no revert mechanisms, that is, it assumes the transaction will be a success.
teleportAtomic
function teleportAtomic(
address to,
uint256 id,
uint256 value,
uint256 chainId,
bytes memory data
) public virtual returns (bool) {
_burn(msg.sender, id, value);
BridgedTransferMetadata memory metadata = BridgedTransferMetadata({
assetType: RaylsBridgeableERC.ERC1155,
id: id,
from: msg.sender,
to: to,
amount: value
});
sendTeleport(
chainId,
abi.encodeWithSignature("receiveTeleportAtomic(address,uint256,uint256,bytes)", to, id, value, data),
abi.encodeWithSignature("unlock(address,uint256,uint256,bytes)", to, id, value, data),
abi.encodeWithSignature("revertTeleportMint(address,uint256,uint256,bytes)", msg.sender, id, value, data),
abi.encodeWithSignature("revertTeleportBurn(address,uint256,uint256)", msg.sender, id, value),
metadata
);
return true;
}
A method to teleport (send cross-chain) an amount of the token. This is an atomic teleport, which means there are revert mechanisms, that is, if the transaction fails by some reason, it will be reverted.
Contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {RaylsApp} from "../RaylsApp.sol";
import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "../interfaces/IRaylsEndpoint.sol";
import "../RaylsMessage.sol";
import "../libraries/Pedersen/Curve.sol";
import "../libraries/SharedObjects.sol";
import "../libraries/Utils.sol";
abstract contract RaylsErc1155Handler is
RaylsApp,
ERC1155,
Initializable,
Ownable
{
string private _uri;
string public name;
address balanceCommitmentsContract;
mapping(address => mapping(uint256 => uint256)) lockedAmount;
mapping(uint256 => bool) alreadySentDeployInstructions;
/**
* @dev Constructor to initialize the RaylsCore with the provided endpoint and owner.
* @param _endpoint The address of the Rayls endpoint.
* @param _owner The address of the owner of the RaylsCore.
*/
constructor(
string memory uri,
string memory _name,
address _endpoint,
address _owner
) ERC1155(uri) RaylsApp(_endpoint) Ownable(_owner) {
_uri = uri;
name = _name;
_disableInitializers();
}
function initialize(
string memory uri,
string memory _name
) public virtual initializer {
address _owner = _getOwnerAddressOnInitialize();
address _endpoint = _getEndpointAddressOnInitialize();
resourceId = _getResourceIdOnInitialize();
// ERC1155 initizalization
_uri = uri;
name = _name;
// RaylsApp Initialization
_transferOwnership(_owner);
endpoint = IRaylsEndpoint(_endpoint);
}
function uri(
uint256 /* id */
) public view virtual override returns (string memory) {
return _uri;
}
function _setURI(string memory newuri) internal virtual override {
_uri = newuri;
}
function teleport(
address to,
uint256 id,
uint256 value,
uint256 chainId,
bytes memory data
) public virtual returns (bool) {
_burn(msg.sender, id, value);
BridgedTransferMetadata memory metadata = BridgedTransferMetadata({
assetType: RaylsBridgeableERC.ERC1155,
id: id,
from: msg.sender,
to: to,
amount: value
});
sendTeleport(
chainId,
abi.encodeWithSignature(
"receiveTeleport(address,uint256,uint256,bytes)",
to,
id,
value,
data
),
bytes(""),
abi.encodeWithSignature(
"revertTeleportMint(address,uint256,uint256,bytes)",
msg.sender,
id,
value,
data
),
abi.encodeWithSignature(
"revertTeleportBurn(address,uint256,uint256)",
msg.sender,
id,
value
),
metadata
);
return true;
}
function teleportAtomic(
address to,
uint256 id,
uint256 value,
uint256 chainId,
bytes memory data
) public virtual returns (bool) {
_burn(msg.sender, id, value);
BridgedTransferMetadata memory metadata = BridgedTransferMetadata({
assetType: RaylsBridgeableERC.ERC1155,
id: id,
from: msg.sender,
to: to,
amount: value
});
sendTeleport(
chainId,
abi.encodeWithSignature("receiveTeleportAtomic(address,uint256,uint256,bytes)", to, id, value, data),
abi.encodeWithSignature("unlock(address,uint256,uint256,bytes)", to, id, value, data),
abi.encodeWithSignature("revertTeleportMint(address,uint256,uint256,bytes)", msg.sender, id, value, data),
abi.encodeWithSignature("revertTeleportBurn(address,uint256,uint256)", msg.sender, id, value),
metadata
);
return true;
}
function receiveTeleport(
address to,
uint256 id,
uint256 value,
bytes memory data
) public virtual {
_mint(to, id, value, data);
}
function receiveTeleportAtomic(
address to,
uint256 id,
uint256 value,
bytes memory data
) public virtual {
_mint(owner(), id, value, data);
if (to != owner()) {
_lock(to, id, value);
}
}
function revertTeleportMint(
address to,
uint256 id,
uint256 value,
bytes memory data
) public virtual receiveMethod {
_mint(to, id, value, data);
}
function revertTeleportBurn(
address to,
uint256 id,
uint256 value
) public virtual receiveMethod {
_burn(to, id, value);
}
/**
* @notice Unlocks the locked funds and calls transfer
* @param to Address of a "to" account to unlock the funds to
* @param amount Amount of tokens to unlock
*/
function unlock(
address to,
uint256 id,
uint256 amount,
bytes memory data
) external returns (bool) {
bool success = _unlock(to, id, amount);
require(success, "cannot unlock the assets");
_safeTransferFrom(owner(), to, id, amount, data);
return true;
}
function _lock(address to, uint256 id, uint256 amount) internal {
require(amount > 0, "Amount must be greater than 0");
require(to != address(0));
lockedAmount[to][id] += amount;
}
function _unlock(
address to,
uint256 id,
uint256 amount
) internal returns (bool) {
require(to != address(0));
uint256 amountToUnlock = lockedAmount[to][id];
require(
amount > 0 && amount <= amountToUnlock,
"Not enough funds to unlock"
);
lockedAmount[to][id] -= amount;
return true;
}
function receiveResourceId(
bytes32 _resourceId
) public virtual receiveMethod onlyFromCommitChain {
resourceId = _resourceId;
_registerResourceId();
}
function submitTokenRegistration() public virtual {
_raylsSend(
endpoint.getCommitChainId(),
endpoint.getCommitChainAddress("TokenRegistry"),
abi.encodeWithSignature(
"addToken((string,string,uint256,uint256,bytes,bytes,bool,uint8))",
SharedObjects.TokenRegistrationData({
name: name,
symbol: name,
totalSupply: 0,
issuerChainId: endpoint.getChainId(),
bytecode: address(this).code,
initializerParams: _generateInitializerParams(),
isFungible: false,
ercStandard: SharedObjects.ErcStandard.ERC1155
})
)
);
}
function _generateInitializerParams() internal virtual view returns (bytes memory) {
return abi.encodeWithSignature("initialize(string,string)", _uri, name);
}
function getLockedAmount(
address account,
uint256 id
) public view returns (uint256) {
return lockedAmount[account][id];
}
function sendTeleport(
uint256 chainId,
bytes memory _payload,
bytes memory _lockDataPayload,
bytes memory _revertDataPayloadSender,
bytes memory _revertDataPayloadReceiver,
BridgedTransferMetadata memory metadata
) internal {
require(resourceId != bytes32(0), "Token not registered.");
_raylsSendToResourceId(
chainId,
resourceId,
_payload,
_lockDataPayload,
_revertDataPayloadSender,
_revertDataPayloadReceiver,
metadata
);
}
}
Updated about 2 months ago