Pallet Precompile
Use this precompile to interact with the sft
runtime pallet to create an ERC-1155 collection.
Contract Address
0x00000000000000000000000000000000000006c3
Solidity Interfaces
interface TRNSFT {
event InitializeSftCollection(address indexed collectionOwner, address indexed precompileAddress);
function initializeCollection(address owner, bytes calldata name, bytes calldata metadataPath, address[] calldata royaltyAddresses, uint32[] calldata royaltyEntitlements) external returns (address, uint32);
}
Token Precompile
Contract Address
The ERC-1155 contract address for The Root Network native semi-fungible tokens uses the following format:
0xBBBBBBBB[4-byte-collection-id]000000000000000000000000
To make things easier, the @therootnetwork/evm
provides a handy function to convert token asset ID to its equivalent contract address.
import { collectionIdToERC1155Address } from "@therootnetwork/evm";
const COLLECTION_ID = 1;
const COLLECTION_CONTRACT_ADDRESS = collectionIdToERC1155Address(COLLECTION_ID);
Solidity Interfaces
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
interface IERC1155 is IERC165 {
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
function balanceOf(address owner, uint256 id) external view returns (uint256);
function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) external view returns (uint256[] memory);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address account, address operator) external view returns (bool);
function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;
function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;
}
interface IERC1155Burnable is IERC1155 {
function burn(address account, uint256 id, uint256 value) external;
function burnBatch(address account, uint256[] calldata ids, uint256[] calldata values) external;
}
interface IERC1155Supply is IERC1155 {
function totalSupply(uint256 id) external view returns (uint256);
function exists(uint256 id) external view returns (bool);
}
interface IERC1155MetadataURI is IERC1155 {
function uri(uint256 id) external view returns (string memory);
}
interface TRN1155 is IERC165 {
event TokenCreated(uint32 indexed serialNumber);
event MaxSupplyUpdated(uint128 indexed maxSupply);
event BaseURIUpdated(string baseURI);
event PublicMintToggled(uint256 id, bool indexed enabled);
event MintFeeUpdated(uint256 id, address indexed paymentAsset, uint256 indexed mintFee);
function createToken(bytes calldata name, uint128 initialIssuance, uint128 maxIssuance, address tokenOwner) external returns (uint32);
function mint(address owner, uint256 id, uint256 amount) external;
function mintBatch(address owner, uint256[] calldata ids, uint256[] calldata amounts) external;
function setMaxSupply(uint256 id, uint32 maxSupply) external;
function setBaseURI(bytes calldata baseURI) external;
function togglePublicMint(uint256 id, bool enabled) external;
function setMintFee(uint256 id, address paymentAsset, uint256 mintFee) external;
}
interface Ownable is IERC165 {
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
function owner() external view returns (address);
function renounceOwnership() external;
function transferOwnership(address owner) external;
}
Soulbound Tokens
The ERC1155 precompile supports Soulbound token functionality and implements
the IERC5484 interface.
enum BurnAuth { IssuerOnly, OwnerOnly, Both, Neither };
Soulbound token ABI
"event PendingIssuanceCreated(address indexed to, uint256 issuanceId, uint256[] tokenIds, uint256[] balances)",
"event Issued(address indexed from, address indexed to, uint256 indexed tokenId, uint8 burnAuth)",
"function setBurnAuth(uint256,uint8)",
"function issueSoulbound(address,uint256[],uint256[])",
"function acceptSoulboundIssuance(uint32)",
"function pendingIssuances(address) external view returns (uint256[] memory,(uint256[] memory,uint256[] memory,uint8[] memory)[] memory)",
"function burnAuth(uint256) external view returns (uint8)",
"function burnAsCollectionOwner(address,uint256[],uint256[])",
The minting of Soulbound tokens is a two-step process. The collection owner creates
a pending issuance via issueSoulbound
. However the burn authority
for a token
must already be set prior to calling issueSoulbound
.
The token is only minted once the token owner calls acceptSoulbound
.
// set the burn auth for a token
await erc1155Precompile
.connect(collectionOwner)
.setBurnAuth(token, BurnAuth.TokenOwner).then(tx => tx.wait());
// issue a token as collection owner
await erc1155Precompile
.connect(collectionOwner)
.issueSoulbound(
tokenOwner.address, // token owner
[token], // list of token ids
[1] // quantities for each token
).then((tx: any) => tx.wait());
// fetch all pending issuances
const [issuanceIds, issuances] = await erc1155Precompile.pendingIssuances(tokenOwner.address);
// accept pending issuance as token owner
await erc1155Precompile
.connect(tokenOwner)
.acceptSoulboundIssuance(issuanceIds[0])
.then(tx => tx.wait());