Skip to content

A cost-efficient standard for fungible assets.

License

Notifications You must be signed in to change notification settings

nifty-oss/sigil

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

50 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

sigil

Sigil

A cost-efficient standard for fungible assets.

Overview

Sigil is a novel fungible token standard and program on Solana that represents fungible tokens on-chain using minimal data, ensuring the lowest possible data storage costs. While off-chain data solutions, such as merkle proofs, could be even cheaper, Sigil's on-chain approach offers the benefits of small transactions without requiring cumbersome proofs. Additionally, token data is directly accessible by other Solana programs via account state. Sigil strikes the optimal balance between on-chain, accessible data and minimal costs, considering the current limitations of account data on Solana's runtime.

The Sigil specification is not intended to replace existing token programs on Solana, which are well-established and feature-rich. Instead, it aims to capture new use cases for which the current standards are prohibitively expensive. For example, in gaming, a game studio may want to create numerous assets for users while subsidizing their rent costs to reduce friction. However, the current costs for creating new token accounts for each asset could become excessively high, given a large user base and multiple assets per user.

To ensure optimal efficiency in terms of compute and memory usage, the Sigil program is implemented with all data structures using zero-copy (bytemuck) implementations.

Design

The specification is currently represented entirely by two types of accounts: Mint and Pocket accounts. Mint accounts uniquely define a type of fungible item and encode the authority and supply data in account state. Pocket accounts are defined per user and contain pairs of mint ticker and amount β€” in other words tokens β€” to encode the user's ownership amounts of various assets.

Mint

Mint accounts are PDAs derived from the seeds "mint", the authority of the mint and a four character ticker (e.g., "USDC"). The authority acts as a namespace for tickers to prevent squatting on valuable tickers that would inevitably happen if tickers were globally namespaced.

The on-chain Mint struct is shown below.

/// Mint data.
///
/// A `Mint` is a PDA with the seeds `["mint", <authority>, <ticker>]`.
#[repr(C)]
#[derive(Clone, Copy, Pod, Zeroable)]
pub struct Mint {
    /// Internal data.
    ///   0. tag
    ///   1. bump
    ///   2. decimals
    ///   3. not in use
    ///   4-7. ticker
    data: [u8; 8],

    /// Authority of the mint.
    pub authority: Pubkey,

    /// Current supply of the mint.
    pub supply: u64,

    /// Maximum supply.
    pub max_supply: u64,
}

Pocket

Pocket are PDAs derived from the seeds "pocket", an authority and user pubkeys. They are defined per-user to allow efficient storing of mint and amount pairs (tokens), but are also namespaced by the authority of mints β€” there will be one Pocket account for each mint authority (namespace). Each Pocket account has a base header which stores the account tag as well as the authority and user pubkeys to allow for efficient indexing.

Important

The innovation of Sigil consists on using a single Pocket account to hold different types of tokens, therefore saving on storage space and costs: creating a new user pocket account requires paying the base rent cost of 68 bytes only once for each user in a given namespace, but adding a new token (mint and amount pair) only costs an additional 8 bytes (4 for the mint ticker and 4 to represent a u32 amount). This is approximately 36x savings when compared to the cost of creating a new SPL Token account for each new user and mint.

The on-chain Pocket struct is shown below.

/// Struct representing an account storing tokens.
///
/// A `Pocket` is a PDA with the seeds `["pocket", <authority>, <user>]`.
pub struct Pocket<'a> {
    /// Base account data.
    pub base: &'a Base,

    /// Tokens stored in the account.
    pub tokens: U32ArraySet<'a, Token>,
}

#[repr(C)]
#[derive(Clone, Copy, Pod, Zeroable)]
pub struct Base {
    /// Internal data.
    ///   0. tag
    ///   1. not in use
    data: [u8; 2],

    /// Authority of the account.
    pub authority: Pubkey,

    /// Owner of the account.
    pub user: Pubkey,
}

Cost Savings

In the SPL Token program, the mint account is 82 bytes in size, plus the standard account info overhead of 128 bytes. It only has to be created once per asset, so typically represents a fixed up-front cost that is paid initially and it does not scale up by number of users. Sigil's mint account is not much smaller, but does save a few bytes coming in at 56 bytes plus the standard 128 account info overhead.

Token accounts however have significant savings, as SPL Token accounts require a new token account per user and mint, which is 128 bytes plus 165 bytes for a total of 293 bytes. In Sigil, there is a fixed cost of 128 bytes plus 68 bytes for a new user token account and then each additional asset only requires 8 bytes without having to pay for extra account header each time as the pairs are simply stored in on the same account.

πŸ“¦ Base Comparisons

Account Data Size (Bytes) Rent Cost @ $200 SOL
SPL Mint 82 $0.29
Sigil Mint 56 $0.26
SPL Token Account (1 asset) 165 $0.41
Sigil Pocket (1 asset) 76 $0.28

πŸ“¦ User w/ 100 Assets

Account Data Size (Bytes) Rent Cost @ $200 SOL
SPL Token Account 16,500 $41
Sigil Pocket 876 $1.40

πŸ“¦ 1000 Users w/ 100 Assets each

Account Data Size (Bytes) Rent Cost @ $200 SOL
SPL Token Account 16,500,000 $41,000
Sigil Pocket 876,000 $1,400

Note

The cost to add a new asset (token) to an existing Sigil pocket account is $0.0111 @ $200 SOL and it takes 8 bytes of account space.

Limitations

The specification currently does not support a delegate system as storing the extra data for that raises the costs significantly. However, delegates could likely be implemented in a cheaper and modular way by using an additional PDA to represent the delegation so that only use-cases that actually require delegates end up paying for them.

Similarly, there is no option to freeze a token but this could be implemented as a bit flag if needed.

Project setup for developers

To get started run the following command

pnpm install

to install the necessary dependencies to set up the project and run pnpm scripts.

Now you can build the program:

pnpm programs:build

generate the clients and IDL:

pnpm generate

start a local validator

pnpm validator:start

and run tests:

pnpm clients:js:test
pnpm clients:rust:test

Managing clients

The following clients are available for the Sigil. You may use the following links to learn more about each client.

Starting and stopping the local validator

The following script is available to start a local validator for testing.

pnpm validator:start

By default, if a local validator is already running, the script will be skipped. You may use the validator:restart script instead to force the validator to restart.

pnpm validator:restart

Finally, you may stop the local validator using the following command.

pnpm validator:stop

License

Copyright (c) 2024 nifty-oss maintainers

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

About

A cost-efficient standard for fungible assets.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published