Skip to content

Deliquified/substream-contracts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Substream: Web3 Subscription Management Platform · npm version

A decentralized subscription management platform built on LUKSO that enables content creators to offer subscription-based services with NFT membership tokens.

ℹ️ This platform allows seamless recurring payments with NFT proof of membership, referral rewards, and full on-chain subscription management.

Table of Contents

Overview

Substream is a subscription management platform built on LUKSO that enables the following:

  1. For Content Creators: Create subscription tiers with different prices and payment frequencies
  2. For Users: Subscribe to content creators with LSP7 tokens, receiving NFT proof of membership
  3. For Referrers: Earn commissions for referring subscribers
  4. For Protocol: Maintain the system with a sustainable fee structure

The platform is built using two main smart contracts:

  • Substream.sol: Core subscription logic, payments, and tier management
  • SubscriptionNFT.sol: LSP8-compatible NFT representing active subscriptions

Architecture

┌───────────────────┐      ┌─────────────────────┐
│                   │      │                     │
│   Substream.sol   │◄────►│  SubscriptionNFT    │
│   (Main Contract) │      │  (LSP8 NFT Contract)│
│                   │      │                     │
└─────────┬─────────┘      └─────────────────────┘
          │
          │ Interacts with
          ▼
┌─────────────────────┐
│                     │
│  LSP7 Digital Asset │
│  (Payment Tokens)   │
│                     │
└─────────────────────┘

The Substream contract manages all subscription logic including payments, tier creation, and renewals. When a user subscribes or renews, the contract mints an NFT via the SubscriptionNFT contract that represents proof of their active subscription.

Key Features

  • Multi-tier Subscriptions: Content creators can offer multiple subscription tiers with different benefits
  • Multi-token Support: Accept multiple LSP7 tokens as payment with customizable prices per token
  • NFT Membership Proof: Each subscription period is represented by an NFT
  • Automated Renewals: Support for manual or third-party renewal of subscriptions
  • Referral System: Built-in referral system with configurable commission rates
  • Revenue Distribution: Automatic splitting of fees between creators, protocol, and referrers
  • Withdrawals: Creators, referrers, and protocol can withdraw accumulated tokens

Subscription Lifecycle

  1. Creation: Content creator creates subscription tier(s)
  2. Discovery: Users browse available subscription tiers
  3. Subscription: User subscribes by paying with an accepted LSP7 token
  4. Membership: User receives NFT representing their subscription
  5. Usage: Content creator can verify active subscriptions on-chain
  6. Renewal: Subscription can be renewed manually or by a third party
  7. Expiration/Cancellation: Subscription expires or gets cancelled

User Perspective

How to Subscribe

  1. Find a content creator's subscription tier that interests you
  2. Ensure you have sufficient LSP7 tokens for payment
  3. Call the subscribe function with:
    • tierId: The ID of the subscription tier
    • paymentToken: Address of the LSP7 token you want to use
    • referrer: Address of who referred you (optional)
// Subscribe to a tier
await substreamContract.subscribe(
  tierId,           // e.g., 1
  paymentTokenAddr, // e.g., "0x123..."
  referrerAddr      // e.g., "0x456..." or address(0) for no referrer
);
  1. Upon successful subscription, you'll receive an NFT representing your active subscription

Managing Your Subscriptions

  • View Subscriptions: Call getUserSubscriptions(yourAddress) to get all your subscription IDs
  • Check Status: Call isSubscriptionActive(subscriptionId) to check if a subscription is active
  • Renew: Call renewSubscription(subscriptionId) before or after expiration
  • Cancel: Call cancelSubscription(subscriptionId) to cancel an active subscription

Content Creator Perspective

Creating Subscription Tiers

  1. Decide on tier details: name, description, accepted tokens, prices, and frequency
  2. Call the createTier function:
// Create a new subscription tier
await substreamContract.createTier(
  "Premium Tier",                  // Name
  "Exclusive content access",      // Description
  [lsp7TokenAddr1, lsp7TokenAddr2],// Accepted tokens
  [tokenPrice1, tokenPrice2],      // Prices for each token
  2592000                          // Frequency in seconds (30 days)
);
  1. The contract returns a tierId that users can subscribe to

Managing Tiers

  • Get Your Tiers: Call getPublisherTiers(yourAddress) to see all your tiers
  • Update Status: Call updateTierStatus(tierId, isActive) to activate/deactivate a tier
  • Check Subscriptions: Use events to monitor new subscribers

Withdrawing Revenue

Content creators can withdraw accumulated tokens:

// Withdraw tokens from the contract
await substreamContract.withdrawTokens(
  tokenAddr, // Address of the token to withdraw
  amount     // Amount to withdraw
);

Protocol Perspective

Fee Structure

  • Protocol Fee: Default 3% (300 basis points) of subscription payments
  • Maximum Limit: Capped at 10% to protect users and creators
  • Fee Management: Only contract owner can modify fee percentages
  • Revenue Collection: Fees accumulate in the contract for owner withdrawal

Security Features

  • Pausable: Contract can be paused in emergency situations
  • Non-custodial: Users always control their NFTs
  • Upgradable: Using UUPS proxy pattern for future improvements
  • Reentrancy Protection: All payment functions have reentrancy guards

Referral System

Substream includes a powerful referral system to encourage growth:

How It Works

  1. Referral Link: Referrers share their address as the referral code
  2. User Subscribes: New subscriber includes referrer's address during subscription
  3. Commission: Referrer earns a percentage of the protocol fee
    • Default: 25% of the protocol fee (effectively 0.75% of subscription price)
  4. Lifetime Value: Referrer continues earning from renewals

Collecting Referral Earnings

Referrers withdraw earnings the same way creators do:

// Check your balance for a specific token
const balance = await substreamContract.getTokenBalance(
  referrerAddr, // Your address
  tokenAddr     // Token address
);

// Withdraw tokens
await substreamContract.withdrawTokens(
  tokenAddr, // Address of the token to withdraw
  amount     // Amount to withdraw
);

Contract Deployment

Prerequisites

  • Node.js and npm installed
  • Private key for deployment
  • LUKSO network connection

Deployment Steps

  1. Clone the repository and install dependencies:
git clone https://github.com/yourusername/substream-contract.git
cd substream-contract
npm install
  1. Create a .env file with your private key:
PRIVATE_KEY=your_private_key
  1. Deploy the contract:
npx hardhat run scripts/deploy.js --network lukso

The deployment process:

  1. Deploys the SubscriptionNFT contract first
  2. Deploys the Substream contract with the SubscriptionNFT address
  3. Sets permissions on the SubscriptionNFT for the Substream contract

Technical Implementation

Substream.sol

Key components of the Substream contract:

  • SubscriptionTier Struct: Stores tier details including accepted tokens and prices
  • Subscription Struct: Tracks subscription status, expiration, and payment details
  • Mappings: Track subscriptions, tiers, and token balances
  • Withdrawal System: Allow stakeholders to withdraw accumulated tokens
  • Access Control: Ensure only authorized users can perform certain actions

SubscriptionNFT.sol

The NFT contract implements the LSP8 standard with specific features:

  • Token Metadata: Stores subscription details (tier, dates) in token metadata
  • Forced Transfers: Allows the main contract to mint tokens directly to subscribers
  • Verification: Enables verification of subscription status via token ownership

Code Examples

Checking Subscription Status

// Function to check if a user has an active subscription
async function hasActiveSubscription(userAddress, publisherAddress) {
  // Get user's subscriptions
  const subscriptionIds = await substreamContract.getUserSubscriptions(userAddress);
  
  // Check each subscription
  for (const id of subscriptionIds) {
    // Check if subscription is active
    const isActive = await substreamContract.isSubscriptionActive(id);
    if (!isActive) continue;
    
    // Get subscription details
    const subscription = await substreamContract.subscriptions(id);
    
    // Get tier details
    const tierId = subscription.tierId;
    const tier = await substreamContract.tiers(tierId);
    
    // Check if this tier belongs to the publisher
    if (tier.publisher === publisherAddress) {
      return true;
    }
  }
  
  return false;
}

Creating a Subscription Tier with Multiple Tokens

async function createMultiTokenTier(
  name,
  description,
  tokenAddresses,
  tokenPrices,
  frequencyInDays
) {
  // Convert days to seconds
  const frequencyInSeconds = frequencyInDays * 24 * 60 * 60;
  
  // Create tier transaction
  const tx = await substreamContract.createTier(
    name,
    description,
    tokenAddresses,
    tokenPrices,
    frequencyInSeconds
  );
  
  // Wait for confirmation
  const receipt = await tx.wait();
  
  // Get tier ID from event
  const event = receipt.events.find(e => e.event === 'TierCreated');
  const tierId = event.args.tierId;
  
  console.log(`Created tier ${tierId}: ${name}`);
  return tierId;
}

Diagrams

Subscription Flow Diagram

┌─────────┐     ┌─────────────┐     ┌──────────────┐     ┌───────────┐
│  User   │     │  Substream  │     │SubscriptionNFT│     │ Publisher │
└────┬────┘     └──────┬──────┘     └──────┬───────┘     └─────┬─────┘
     │                 │                   │                   │
     │  subscribe()    │                   │                   │
     │─────────────────>                   │                   │
     │                 │                   │                   │
     │                 │    mint()         │                   │
     │                 │───────────────────>                   │
     │                 │                   │                   │
     │                 │  NFT transferred  │                   │
     │                 │ <─ ─ ─ ─ ─ ─ ─ ─ ─│                   │
     │                 │                   │                   │
     │  NFT received   │                   │                   │
     │ <─ ─ ─ ─ ─ ─ ─ ─                   │                   │
     │                 │                   │                   │
     │                 │   Fee distributed │                   │
     │                 │ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─>│
     │                 │                   │                   │

Fee Distribution Diagram

Subscription Payment (100%)
│
├─► Protocol Fee (3%)
│   │
│   ├─► Protocol Owner (75% of fee = 2.25% of payment)
│   │
│   └─► Referrer (25% of fee = 0.75% of payment)
│
└─► Content Creator (97% of payment)

Contract Relationship Diagram

User
│
│ owns
▼
LSP7 Tokens ──────► Substream Contract ◄────────┐
                    │                           │
                    │ mints                     │
                    ▼                           │
               SubscriptionNFT             can verify
                    │                           │
                    │ owned by                  │
                    ▼                           │
                   User ◄─────────────────────┘

Want to Contribute?

We welcome contributions to Substream! Check out our contribution guidelines and join our community to help build the future of Web3 subscriptions.

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published