Tradable subscriptions protocol on Solana.

Related tags

Cryptography buoyant
Overview

Buoyant

"Subs not dubs."

Demo (Local)

To demo our app's functionality, we've created a basic control panel/dashboard where you can test out creating and renewing subscriptions. To run it locally, run the following commands:

// clone the repository
git clone https://github.com/IlliniBlockchain/buoyant.git

// go into the demo app's directory
cd buoyant/website

// install dependencies
npm install

// run locally
npm run start

Project Overview

Description

A base protocol implementing recurring payments.

Motivation

Recurring payments are a very common and helpful payments model. They're used for time-bound access to content/services and for consistent streams of revenue. So far we haven't seen anything that really executes on this basic payments primitive, and also at the time of creating this there are <2 weeks left in Solana's Riptide Hackathon and we wanna build.

Primary Features

  • Allow a user to create a new subscription

  • Allow a payer to deposit into a vault

  • Expose a public function that either

    1. Transfers money from vault to payee and renews the subscription if a certain balance is met
    2. Marks the subscription inactive

    and compensates the caller.

  • Make subscription activity/inactivity tied to a token

Design

TL;DR create a subscription with metadata and get a new NFT for each period the subscription is active. Anyone/cranks will be run to renew/deactivate subscriptions and they'll get a fee paid to them to incentivize.

When someone opens up a new subscription, they'll specify an amount of money to be paid and a duration of how long the subscription is active for. This will then initialize a new account with subscription metadata as well as a new token vault account for the payer to deposit to.

On initialization and renewal of a subscription, an new token mint is created and a token is minted to the payer (and a new associated token account for this particular mint is created as needed). A user's subscription is said to be "active" if the user owns a token from the particular mint. The latest mint's public key will be stored and updated in the subscription's metadata so that products built on top of this protocol have easy access to the necessary data needed to check the active/inactive status of a subscription.

With the issuing of many individual tokens for each subscription, products building on this protocol cannot just check the possession of a specific token as each token is from a different mint. However, in this case, they can just check that the metadata of the subscription--most importantly the amount and duration--match their requirements.

When a subscription is renewed, a new mint will be created. If the deposit vault has enough tokens to renew, the amount will be transferred to the payee and a token from the new mint will be minted to the payer.

The renewal instruction will be available for anyone to call. A certain percentage of the amount being transferred to the payee will be sent to the caller of the renewal instruction to incentivize a decentralized participation to enforce the renewal/expiry mechanic of the protocol. In the beginning, a centralized crank will be run to ensure the timely functioning of renewals/expirations. Overtime as usage grows, ideally fee incentives should naturally decentralize this mechanic.

Token Functionality

Because the subscription is represented with a token, it turns them into assets that are tradable on open markets. This not only allows for the simple transfer of a subscription if someone wants to gift it to a friend, but it also allows the ability to sell a subscription for a different duration than the original services' configuration, e.g. if you paid for a month-long subscription and after 20 days you no longer care for it, you could sell it to someone who might be looking for a 10-day trial for cheaper.

Accounts

Flowchart coming soon.

Roadmap

  • Basic instruction implementations
    • Account flow chart
  • Create email, twitter, and gitbook
  • Integrate Metaplex token metadata standard
  • Create a basic API for other projects to build on
    • Javascript/Typescript types and instruction wrappers
    • Rust instruction wrappers
    • Anchor accounts and contexts
  • Crank/public renewal assistance
Comments
  • "Tradable Subscriptions" Messing Up Spacing

    Didn't realize this till it was already up - 2 lines for "tradable subscriptions" makes the cards uneven - fix by making font smaller or smth..? Maybe even change back to "liquid subscriptions"

    image good first issue atomic 
    opened by alecchendev 2
  • ๐ŸŽฅ Create Video Submission

    ๐ŸŽฅ Create Video Submission

    • Maybe do a meme-y intro of us trying to find a project and just picking some random one off the riptide ideas list lol
    • Maybe make some basic slides just for transitions and stuff
    • Use website and/or docs to flow through an overview of what it is and how it works
    • Use frontend demo app to demo functionality/basic product built on the protocol
    opened by alecchendev 1
  • ๐Ÿ˜ Program Test: Test Renew2

    ๐Ÿ˜ Program Test: Test Renew2

    image

    Just has basic test for successful transaction and one small check for active status of a subscription after renewal. Definitely needs further testing/checks to ensure functionality/security.

    Closes #72

    opened by alecchendev 0
  • 0๏ธโƒฃ Zero out subscription data after expiry

    0๏ธโƒฃ Zero out subscription data after expiry

    Closes #36

    Just extra proof that it works: Initialize: https://explorer.solana.com/tx/4ShoLye8rM11rUk54kVYmkX1rtuCesqxEVWQ5FkAP1v8Mbkv3pZBcEbWMRmga9cccRM4b9Q97KkaoY5YjeJCRwmZ?cluster=devnet Deposit: https://explorer.solana.com/tx/3zMN85BkeCCG1yyAVgnaAhLAExn5SX2mEdcdyYM4aeeAbE8P9f6s5iRHUAa8jtT6CvXWSas19w9eNjLaSGMW9xGN?cluster=devnet Renew (activate): https://explorer.solana.com/tx/4jfcuKME4s5Zv3PsTu7GKPHmBUTXNvgUMFKyuugJPXKAocGPFNFAVaYqW6Q6joDUdHUNREq56wGfHTkWEhNQoaUC?cluster=devnet Renew (expire + zero out): https://explorer.solana.com/tx/4Ed6cAFRERiSrHWU33f83cno2bFiMe2TAZ8LsatupvCuX2do83ob9Pqb8s5U5Dwxg2VuxFW4YJbQ1DJqqY74vgW7?cluster=devnet

    To actually test this we'd have to create a separate example program to insert an instruction at the end to test if it could still access the data, but the logic is pretty straightforward so I figured this was unnecessary for the amount of work it would take.

    Honestly don't really think this fix is super important anyway but figured better safe than sorry.

    opened by alecchendev 0
  • โš™๏ธ Rust Program API: Rust Client Setup

    โš™๏ธ Rust Program API: Rust Client Setup

    #53 Is setting up tests within the program whilst implementing instruction wrappers - this PR is setting up an external client that calls/tests our program by actually calling the program on devnet

    Is this necessary? Mmm at the moment not really because most clients will likely be frontends, but in the long-term, rust is faster than node, so when we publish some sort of crank script or cli tooling or just want to have a test client that implements the same types as our program, orrr want to have an end-to-end testing (full external rpc call --> change in state) rather than just program testing, this will come in handy.

    It working: image

    Tx: https://explorer.solana.com/tx/58HMqkBXu8vWpRJ3CMrJJYg7Vk5oWHRLk4Dwx7MEAqxRpXuiUVHc7NiWBAcigamxLAAhcoxVs5QYQKGcRbU8oUw2?cluster=devnet

    opened by alecchendev 0
  • ๐ŸŸฆ Typescript API: Setup

    ๐ŸŸฆ Typescript API: Setup

    • Atomic task for #9
    • Setting up the this API is composed of a few main things
      • Configuring typescript
      • Setting up to publish an npm package - how do you structure things, export things, etc. such that someone can use everything they need to easily when they install note modules
      • How to actually publish to npm package registry

    Possibly helpful resources: General setup: https://www.tsmean.com/articles/how-to-write-a-typescript-library/ Unit testing: https://www.tsmean.com/articles/how-to-write-a-typescript-library/unit-testing/ Example in practice: https://github.com/solana-labs/solana-program-library/tree/master/token/js

    atomic 
    opened by alecchendev 0
  • ๐Ÿ”’ Zero out account data on expiry

    ๐Ÿ”’ Zero out account data on expiry

    • When withdrawing rent upon expiry, we expect the runtime to delete the account, however this is only valid between transactions. If someone where to insert an instruction after this that uses the dormant account data in a malicious way, this could be bad.

    Action: In the renew instruction code, when it expires a subscription (sets lamports to 0), also zero out the data.

    bug atomic 
    opened by alecchendev 0
  • ๐Ÿšง Expiry Incentive and Program Touch-Ups

    ๐Ÿšง Expiry Incentive and Program Touch-Ups

    Closes #21 + restructure program directory to have processor folder

    Transactions:

    1. Initialize: https://explorer.solana.com/tx/aakwgtpaKpxdQZNUwCd4wYFfwy8Bp2rbjrbXLEQWZs2R62LWjA5ofgWdX2SSjMfq6giT5goSperWuhZPm4i1Scj?cluster=devnet
    2. Deposit: https://explorer.solana.com/tx/2i6yGpAHMQMm6RnfQ522LedXp1oUZ288HR6mvA1BtxLC7ciRURzkGn5sT5F9MHYSUitmSb4bEVV4CXUxhy6bW4NL?cluster=devnet
    3. Renew - set active and transfer: https://explorer.solana.com/tx/yajCqyLmzNTrVeRtpQB8iBL7L53CLhFbvwD7Neq9oFLajbBwTWXbgz9Fet39PLFd8ZNtx2nM12CXrrQnHNjZ6Ee?cluster=devnet
    4. Expire - take fee, withdraw rent: https://explorer.solana.com/tx/2en2HAoXetDeTugYoLQUGZ9ZzeywTKpAuWALj7FAmkcQVo9pJqiQp3qKLDjBbGcVJV3UMCUquhZa1aYRTCSs2eF7?cluster=devnet
    5. Accounts are now uninitialized: a. Deposit vault: https://explorer.solana.com/address/7cAUduDzopY9t4uYJ6tYEP9NJkLfRpPoM3NEip1cdhJr?cluster=devnet b. Subscription metadata: https://explorer.solana.com/address/5WZYu85B6kUABnaeusxK7bysmuava98pKHgeukATEjFj?cluster=devnet
    opened by alecchendev 0
  • ๐Ÿšง Missing expiry incentive

    ๐Ÿšง Missing expiry incentive

    Right now people are incentivized to enforce renewals because when funds are transferred, a proportion of that fund is paid to the caller. This is not the case for expiry!

    On expiry, it's possible that there are no funds left in the deposit vault, so the caller can only be paid by withdrawing rent from either the deposit vault account or the metadata account, effectively closing the subscription. See #13

    Actions:

    • Problem: don't want to withdraw rent/close account if there are tokens left, need some way to get paid. Solution...
      • In Renew, if number of tokens in deposit vault is 0, withdraw rent from subscription and call CloseAccount on token program to close deposit vault
      • In Renew, if number of tokens in deposit vault is >0, take same amount of tokens that you would've taken upon a renewal - if there are less than that, just take whatever's left.
    • Problem: expired accounts that had their rent taken from them need/need not be reinitialized?
      • Option 1: don't let people reinitialize them, whenever initialized is called it only initializes new account (default)
      • Option 2: reinitialize old account
        • reinitialize, need user to pass in count seed
        • Don't increment counter

    Also:

    • Add in check_initialized_ata for the payee and caller token accounts if they are already initialized
    opened by alecchendev 0
  • ๐ŸŒˆ Add withdraw restriction

    ๐ŸŒˆ Add withdraw restriction

    With the new initialize and renew (#66), it is required that a minimum of the renewal fee is present in the deposit vault such that callers are still incentivized to expire accounts (and you don't have to withdraw rent to compensate the caller).

    Need to modify withdraw so that the user cannot withdraw past this minimum amount. Should a user want to withdraw the full amount, they can call the Close instruction.

    good first issue atomic 
    opened by alecchendev 0
  • ๐Ÿ˜ Crank script

    ๐Ÿ˜ Crank script

    Example script for cranks to use. Written in Rust.

    Allow two options: 1) run crank for a certain subscription type 2) run crank over registry.

    Ideas for implementation

    Brute force: Basically just loops through registry, for each subscription type, it finds the total count, loops through each address, sends renew instruction Time sensitive: Loops through everything and retrieves next renew times, sorts the next renew times earliest to latest, sleeps until that time, then sends tx.

    atomic 
    opened by alecchendev 0
  • โš™๏ธ Rust Program API: Reorganize

    โš™๏ธ Rust Program API: Reorganize

    Currently a bunch of helpers are defined in rust-client that should be moved to inside program

    rust-client should import the buoyant crate as answered here: https://stackoverflow.com/questions/45519176/how-do-i-use-or-import-a-local-rust-file

    atomic 
    opened by alecchendev 0
  • ๐Ÿ—ป Store bumps and other seeds in PDAs

    ๐Ÿ—ป Store bumps and other seeds in PDAs

    Current status: Added bump for Counter and changed program to validate using bump, haven't deployed, next step is to fix client scripts that interface with counter

    Closes #27

    opened by alecchendev 0
Owner
Illini Blockchain
University of Illinois at Urbana-Champaign's premiere blockchain student organization.
Illini Blockchain
My attempt at learning Solana program (smart contract) development through RareSkill's Solana course.

60-days-of-solana My attempt at learning Solana program (smart contract) development through RareSkill's Solana course. Originally, I was trying to cr

Jasper 3 Feb 25, 2024
Metaplex is a protocol built on top of Solana that allows: Creating/Minting non-fungible tokens;

Metaplex is a protocol built on top of Solana that allows: Creating/Minting non-fungible tokens; Starting a variety of auctions for primary/secondary

Metaplex Foundation 3.2k Jan 4, 2023
โ› An open protocol for launching liquidity mining programs on Solana.

โ› Quarry An open protocol for launching liquidity mining programs on Solana. Background Quarry was built with the intention of helping more Solana pro

Quarry Protocol 207 Dec 19, 2022
The Light Protocol program verifies zkSNARK proofs to enable anonymous transactions on Solana.

Light Protocol DISCLAIMER: THIS SOFTWARE IS NOT AUDITED. Do not use in production! Tests cd ./program && cargo test-bpf deposit_should_succeed cd ./pr

null 36 Dec 17, 2022
โš“ Solana Sealevel Framework

Anchor โš“ Anchor is a framework for Solana's Sealevel runtime providing several convenient developer tools. Rust eDSL for writing Solana programs IDL s

Project Serum 2.6k Jan 2, 2023
A framework for creating PoC's for Solana Smart Contracts in a painless and intuitive way

Solana PoC Framework DISCLAIMER: any illegal usage of this framework is heavily discouraged. Most projects on Solana offer a more than generous bug bo

Neodyme 165 Dec 18, 2022
Generate Nice Solana Address By Template

Yes, I know about GPU generators. https://smith-mcf.medium.com/solana-vanity-address-using-gpus-5a68ad94d1d4 ./solana-nice-address --help solana-nice-

Kirill Fomichev 18 Jun 18, 2022
The Voting example based on MoonZoon and Solana + Anchor framework.

The Voting example based on MoonZoon and Solana + Anchor framework.

Martin Kavรญk 6 Aug 13, 2022
The Solana Program Library (SPL) is a collection of on-chain programs targeting the Sealevel parallel runtime.

Solana Program Library The Solana Program Library (SPL) is a collection of on-chain programs targeting the Sealevel parallel runtime. These programs a

null 6 Jun 12, 2022
sandbox to play around numerous functionalities on Solana

Solana Sandbox This sandbox is for verifying smart contracts(programs) implemented on Solana for a self-study purpose. Programs Currently implemented

Tomoaki Imai 22 May 11, 2022
Solana Escrow Program written by RUST.

Environment Setup Install Rust from https://rustup.rs/ Install Solana from https://docs.solana.com/cli/install-solana-cli-tools#use-solanas-install-to

Blockchain*Lover* 5 Mar 10, 2022
A suite of programs for Solana key management and security.

?? goki Goki is a suite of programs for Solana key management and security. It currently features: Goki Smart Wallet: A wallet loosely based on the Se

Goki Protocol 157 Dec 8, 2022
Testing a smart contract on the Solana blockchain

Environment Setup Install Rust from https://rustup.rs/ Install Solana from https://docs.solana.com/cli/install-solana-cli-tools#use-solanas-install-to

Maurice 1 Oct 25, 2021
Solana NFT generative artwork program

resin Solana NFT generative artwork program Installation Depends on imagemagick for art generation, which can be installed here: https://imagemagick.o

null 4 Jun 24, 2022
Simple template for building smart contract(Rust) and RPC Client(web3.js) on Solana (WIP) โ›๐Ÿ‘ท๐Ÿšงโš ๏ธ

Solana BPF Boilerplate Simple template for building smart contract(Rust) and RPC Client(web3.js) on Solana This boilerplate provides the following. Si

ono 6 Jan 30, 2022
Examples of Solana on-chain programs

spl-examples List of Solana on-chain programs which demonstrate different aspects of Solana architecture. 01__state It's a counter program. Each user

Max Block 51 Dec 6, 2022
๐Ÿง‘โ€โœˆ Version control and key management for Solana programs.

captain ??โ€โœˆ๏ธ Version control and key management for Solana programs. Automatic versioning of program binaries based on Cargo Separation of deployer a

Saber 35 Mar 1, 2022
Synchronized shadow state of Solana programs available for off-chain processing.

Solana Shadow The Solana Shadow crate adds shadows to solana on-chain accounts for off-chain processing. This create synchronises all accounts and the

null 40 Oct 30, 2022
Battery-included Solana/Anchor project skeleton.

Anchor Skeleton Battery-included Solana/Anchor project skeleton. Features Rust test only: All tests (integration, unit) are written in Rust, so the co

Weiyuan Wu 5 Feb 23, 2022