Skip to content

Props Documentation

Welcome to the Props documentation site. Here you'll find comprehensive guides and documentation to help you start working with Props Diamond Framework and SDK as quickly as possible.

Quick Start

Need Help?

If you need help with Props, you can reach out to our support team or join our community forums.

Diamond-X: Diamond Framework and SDK

Diamond-X is a powerful implementation of the Diamond Standard (EIP-2535) that allows for modular, upgradeable smart contracts with a robust SDK for seamless interaction.

Table of Contents

Overview

The Diamond Framework implements the EIP-2535 Diamond Standard, providing a powerful, modular approach to smart contract development. The Diamond pattern allows a single contract address to have unlimited external functions, offering numerous advantages:

  • Modularity: Organize contract code into facets
  • Upgradeability: Add, replace, or remove functionality without changing the contract address
  • Unlimited Contract Size: Overcome the 24KB contract size limit
  • Gas Efficiency: Optimize for specific use cases

Features

  • Complete implementation of the Diamond Standard (EIP-2535)
  • Factory-based deployment for predictable addresses
  • Support for multiple ERC standards (ERC20, ERC721, ERC1155, ERC7401, ERC6220)
  • Extensive TypeScript SDK for simplified interaction
  • Robust cryptography utilities including ECDSA, EIP712, and MerkleProof
  • Comprehensive testing framework

Installation

Contract Framework

bash
pnpm install @props-labs/props-diamond-protocol

SDK

bash
pnpm install @props-labs/diamond-sdk

Diamond Framework

Core Contracts

The Diamond Framework consists of several core contracts:

  1. Diamond: The main entry point contract that implements the diamond pattern fallback mechanism.
  2. PropsDiamond: Extends the Diamond contract with Props-specific functionality.
  3. PropsDiamondFactory: Factory contract for creating new PropsDiamond instances with predictable addresses.

Facets

Facets are modular pieces of functionality that can be added to a Diamond. The framework includes several categories of facets:

  • ERC2535: Core Diamond standard facets (DiamondCutFacet, DiamondLoupeFacet, OwnershipFacet)
  • ERC20: Facets for ERC20 token functionality
  • ERC721: Facets for NFT functionality
  • ERC1155: Facets for multi-token functionality
  • ERC7649: Facets for token extensions
  • Shared: Common functionality shared across different facet types

Factory Pattern

The PropsDiamondFactory allows for creating new diamonds with predictable addresses:

solidity
function createDiamond(
    bytes32 _salt,
    struct IPropsInitCall.InitCall[] _initCalls,
    struct IPropsPreApprovalCall.PropsPreApprovalCall[] _preApprovalCalls
) external returns (address)

This enables the creation of diamonds with initialization calls for immediate configuration.

Props Diamond SDK

The Props Diamond SDK provides a powerful interface for interacting with Diamond contracts.

SDK Installation

bash
pnpm add @props-labs/diamond-sdk

SDK Initialization

typescript
import { PropsDiamondSDK, FacetCatalog } from '@props-labs/diamond-sdk';
import { ethers } from 'ethers';

// Initialize the SDK
const propsDiamondSDKClient = new PropsDiamondSDK({
  signer: wallet, // ethers wallet
  networkConfiguration: {
    provider: ethers.getDefaultProvider(), // provider
  },
  platformConfiguration: {
    platform: {
      propsDiamondFactory: "0x...", // address of Props Diamond Factory
      facetCatalog: FacetCatalog, // FacetCatalog Type, holds all available facets
    },
  },
});

Managing Diamonds

The SDK provides a DiamondManager class for managing diamond contracts:

typescript
// Deploy a new diamond
const diamondAddress = await propsDiamondSDKClient.diamondManager.deployDiamondClone();

// Get a contract instance for interacting with the diamond
const diamondContract = await propsDiamondSDKClient.diamondManager.getCallableContractForDiamond();

Working with Facets

Select and configure facets to add to your diamond:

typescript
// Get facets from the catalog
const baseFacets = await propsDiamondSDKClient.platformManager.catalogManager.getFacetCatalogFacetsByNames(
  ["DiamondLoupeFacet", "PropsERC1155"]
);

// Create diamond cuts to add the facets
const cuts = await propsDiamondSDKClient.diamondManager.createDiamondCuts(
  FacetCutAction.Add, // Action: Add, Remove, or Replace
  baseFacets,         // Selected facets from the catalog
  [],                 // Include only these functions (empty = all)
  ["uri(uint256)"],   // Exclude these functions
  {}                  // Priority for overlapping functions
);

Contract Interactions

After deploying your diamond with facets, interact with it through the SDK:

typescript
// Get a contract instance
const diamondContract = await propsDiamondSDKClient.diamondManager.getCallableContractForDiamond();

// Call functions on the diamond
const name = await diamondContract.name();
const symbol = await diamondContract.symbol();

// Execute transactions
const tx = await diamondContract.mint(
  recipientAddress,
  tokenId,
  quantity,
  { value: mintCost }
);

Usage Examples

Creating a New Diamond

typescript
// 1. Select facets for your diamond
const facets = await propsDiamondSDKClient.platformManager.catalogManager.getFacetCatalogFacetsByNames(
  ["DiamondLoupeFacet", "DiamondCutFacet", "OwnershipFacet", "PropsERC1155"]
);

// 2. Create diamond cuts
const cuts = await propsDiamondSDKClient.diamondManager.createDiamondCuts(
  FacetCutAction.Add,
  facets,
  [], // Include all functions
  [], // Exclude none
  {}
);

// 3. Deploy the diamond with initialization
const diamondAddress = await propsDiamondSDKClient.diamondManager.deployDiamondCloneWithCuts(
  cuts,
  [
    // Initialize ERC1155 facet
    await propsDiamondSDKClient.diamondManager.createFacetInit(
      "PropsERC1155",
      "init",
      [
        "TOKEN_NAME",
        "SYMBOL",
        "DESCRIPTION",
        "ipfs://baseuri/",
        "ipfs://contracturi",
        0 // royalty basis points
      ]
    )
  ]
);

Adding Facets

typescript
// 1. Get facets to add
const royaltyFacet = await propsDiamondSDKClient.platformManager.catalogManager.getFacetCatalogFacetsByNames(
  ["PropsRoyalty"]
);

// 2. Create diamond cuts
const royaltyCuts = await propsDiamondSDKClient.diamondManager.createDiamondCuts(
  FacetCutAction.Add,
  royaltyFacet,
  ["royaltyInfo(uint256,uint256)", "setTokenRoyalty(uint256,address,uint96)"],
  [],
  {}
);

// 3. Execute the diamond cut
await propsDiamondSDKClient.diamondManager.executeDiamondCut(
  royaltyCuts,
  [
    // Initialize the royalty facet
    await propsDiamondSDKClient.diamondManager.createFacetInit(
      "PropsRoyalty",
      "init",
      [1000] // 10% royalty (1000 basis points)
    )
  ]
);

Removing/Replacing Facets

typescript
// 1. Get the facet to replace
const updatedERC1155Facet = await propsDiamondSDKClient.platformManager.catalogManager.getFacetCatalogFacetsByNames(
  ["PropsERC1155V2"] // Updated version
);

// 2. Create diamond cuts to replace
const replaceCuts = await propsDiamondSDKClient.diamondManager.createDiamondCuts(
  FacetCutAction.Replace,
  updatedERC1155Facet,
  [], // Replace all functions
  [], // Exclude none
  {}
);

// 3. Execute the diamond cut
await propsDiamondSDKClient.diamondManager.executeDiamondCut(
  replaceCuts,
  [] // No initialization needed for replacement
);

Interacting with Diamond Contracts

typescript
// Get a contract instance
const diamond = await propsDiamondSDKClient.diamondManager.getCallableContractForDiamond();

// Read functions
const balance = await diamond.balanceOf(address, tokenId);
const uri = await diamond.uri(tokenId);

// Write functions
const mintTx = await diamond.mint(recipientAddress, tokenId, quantity);
await mintTx.wait();

// Set royalties
const royaltyTx = await diamond.setTokenRoyalty(tokenId, creatorAddress, 500); // 5%
await royaltyTx.wait();

Advanced Features

Hooks and Extensions

The Diamond Framework supports hooks for advanced functionality:

typescript
// Initialize with hooks
const hookMiner = new propsDiamondSDKClient.diamondManager.HookMiner();
const hookCode = await hookMiner.findHookAddress(
  salt,
  [0, 0, 1, 0] // Hook permissions: [beforeInitialize, afterInitialize, beforeSwap, afterSwap]
);

Pre-approval Mechanism

The framework supports pre-approval calls for complex deployments:

typescript
// Create pre-approval calls
const preApprovalCalls = [
  {
    to: approvalContract,
    data: approvalData,
    value: ethers.utils.parseEther("0")
  }
];

// Deploy with pre-approval
await propsDiamondSDKClient.diamondManager.deployDiamondCloneWithCuts(
  cuts,
  initCalls,
  preApprovalCalls
);

Cryptography Utilities

The framework includes cryptography utilities:

  • ECDSA: Secure signature verification
  • EIP712: Typed data signing and verification
  • MerkleProof: Efficient verification of inclusion in large data sets

Documentation

To generate comprehensive documentation for the project, run:

bash
pnpm run docs

This command will generate documentation including API references, component documentation, and other relevant information. It will then launch the apps/docs site for browsing.

Changelog