# Welcome to Superstate

Superstate connects financial assets with crypto capital markets through onchain public listings and tokenized securities.

* [Investors](/investors/getting-started): Onboard to Superstate to access tokenized funds and equities.
* [Issuers](/issuers/opening-bell): Tokenize equities or funds using Superstate's tokenization platform.
* [Integration partners](/integration-partners/onboarding-api): Wallets, exchanges, and other partners can give their users access to Superstate's tokenized equities and funds

*View our* [*Terms of Service*](https://superstate.com/terms)

***


# Getting started

Sign up for Superstate to invest in both onchain equities and Superstate funds.

***

## **Create an account**

1. Visit superstate.com/register
2. Provide your email and create a nickname for your organization
3. Check your email, and click the link in the welcome email to confirm your account
4. Fill out your name and create a password
5. Add 2FA to secure your account (recommended)

**Eligibility**

* **Tokenized Equities**: Available to all investors in supported countries
* **Superstate Funds:** Only available to Qualified Purchasers in supported countries with at least $5m in investable assets for individuals, or $25m for institutions.

**Supported countries for Superstate Funds**

United States, Australia, Bermuda, Bahamas, British Virgin Islands, Canada, Cayman Islands, Cyprus, France, Georgia, Germany, Gibraltar, Hong Kong, Italy, Ireland, Jersey, Luxembourg, Marshall Islands, Mexico, Panama, Poland, Seychelles, Singapore, Spain, Saint Kitts and Nevis, South Korea, Switzerland, United Arab Emirates, and United Kingdom.

*Please note that this list is updated regularly.*

***

## **Applications**

After logging into the Investor Portal, you'll be prompted to complete two types of applications:

1. **Investing Entity Application (required)**: This application collects information about your investing entity to verify your eligibility to access either onchain equities or Superstate funds. For a list of documents that we require during this application, please see [Required documents](/investors/getting-started/required-documents)
2. **Fund Applications**: Investors who submit proof of accredited investor status, and who wish to invest in Superstate Funds like USTB or USCC, must complete separate applications for each one to verify your eligibility to invest. Users who do not provide proof of accreditation status cannot apply to these funds.

***

## **Application Review**&#x20;

Once you've submitted either your entity and fund applications, our team will review them carefully. We assess your eligibility based on several factors, including compliance checks, anti-money laundering (AML) screening, and accreditation status. If we need any additional information, we'll reach out to you directly.

Following approval, we'll send you an Investment Agreement that is populated with information provided in the application process for your review and execution. Once this is signed, you're ready to start investing.

***

## **Entity Setup**

Before making your first investment, you'll need to configure your Allowlist and Payouts from the Settings page:

* **Transaction defaults**: Choose the default methods you’ll use to fund purchases and receive payouts.
* **Allowlist**: Choose the wallet addresses authorized to hold your onchain equities or Superstate fund tokens.
* **Payout Destination**: Choose the bank account or wallet address where you can receive payouts when redeeming a Superstate fund.<br>


# Required documents

To complete your Entity Application, you'll need to provide specific documents that we use to assess your eligibility. The required documents will differ depending on whether you are applying on behalf of an Individual or Institutional entity.

**Note**: Gathering these documents can be time consuming. We recommend starting this process *early* to ensure a smooth application.

***

## Institutional Entities

The documents in the first row are required *for all entity types*, and the documents in subsequent rows are only required for that specific entity type.

<table><thead><tr><th width="158">Entity Type</th><th>Required Documents</th><th data-hidden></th></tr></thead><tbody><tr><td><strong>All Entity Types</strong></td><td><ul><li>Taxable status</li><li>A document describing your AML/OFAC policy (if applicable)</li><li><p>Details of individuals or entities who have 25% or more ownership (directly or indirectly)</p><ul><li>For Individuals this includes their name, date of birth, SSN or TIN, email, physical address, and Passport or US Government-issued ID.</li><li>For Entities this includes the entity name, TIN, physical address, and formation documents.</li></ul></li></ul><p></p><p></p><p>To invest in USTB or USCC:</p><ul><li>Proof of Accredited Investor status, either <a href="https://static-portal.angellist.com/22737ea3-255a-457f-992e-e1cb519132da/static-documents/Proving-Accredited-Investor-Status-Options.pdf">Accepted documents</a> or <a href="https://static-portal.angellist.com/22737ea3-255a-457f-992e-e1cb519132da/static-documents/Third-Party-Verification-of-Accredited-Investor-Status.pdf">Third-Party Verification</a></li></ul></td><td></td></tr><tr><td>Corporation</td><td><ul><li>Certificate of due formation and organization</li><li>Articles of Incorporation</li></ul></td><td></td></tr><tr><td>Partnership</td><td><ul><li>Certificate of Partnership or equivalent.</li><li>Certificate of Good Standing.</li><li>A current executed Limited Partnership Agreement or equivalent, identifying the General Partner and/or the persons authorized to sign the Investment Agreement.</li></ul></td><td></td></tr><tr><td>S-Corp</td><td><ul><li>Certificate of due formation and organization</li><li>Articles of Incorporation</li><li>List of officer signatures or signed, certified corporate resolutions identifying the corporate officer(s) authorized to sign the Subscription Documents</li></ul></td><td></td></tr><tr><td>Trust</td><td><ul><li>Trust Agreement or relevant portions thereof, including the grantor declarations page and signature pages, and any other portions showing appointment and authority of trustee(s)</li><li>Individual identification (see above) for all Trustees</li></ul></td><td></td></tr><tr><td>LLC</td><td><ul><li>Certificate of Formation or equivalent</li><li>A current executed Limited Liability Company Agreement, Operating Agreement or equivalent identifying the Managing Member(s) authorized to sign the Subscription Documents</li></ul></td><td></td></tr><tr><td>LLP</td><td><ul><li>Certificate of Formation or equivalent</li><li>A current executed Limited Liability Partnership Agreement, Operating Agreement or equivalent identifying the Managing Member(s) authorized to sign the Subscription Documents</li></ul></td><td></td></tr><tr><td>Other</td><td><ul><li>Certificate of Formation or equivalent;</li><li>Operating documents, Limited Partnership Agreement, or equivalent.</li></ul></td><td></td></tr></tbody></table>

***

## Individual Entities

<table><thead><tr><th width="165">Type</th><th>Required Documents</th><th data-hidden></th></tr></thead><tbody><tr><td>All Individuals</td><td><ul><li>Government-issued photo ID</li></ul><p></p><p>To invest in USTB or USCC:</p><ul><li>Proof of Accredited Investor status, either <a href="https://static-portal.angellist.com/22737ea3-255a-457f-992e-e1cb519132da/static-documents/Proving-Accredited-Investor-Status-Options.pdf">Accepted documents</a> or <a href="https://static-portal.angellist.com/22737ea3-255a-457f-992e-e1cb519132da/static-documents/Third-Party-Verification-of-Accredited-Investor-Status.pdf">Third-Party Verification</a></li></ul></td><td></td></tr></tbody></table>


# Investor portal

Our easy-to-use Investor Portal helps you track and manage your investments in Superstate Funds. In this guide we'll show you how it works.

**Please Note**: This guide shows the portal from the perspective of an Institutional Investor. Individual Investors will see information that is tailored to them.

***

## Overview

The Investor Portal has three sections

1. **Portfolio**: View holdings, view instructions for making transactions like purchases, and view past transactions.
2. **Documents**: Access monthly statements, fund documents, and equity documents.
3. **Settings**: Configure your team, allowlist, and transaction settings.

***

## Signing In

Go to Superstate.com, then select Sign In.&#x20;

#### **Set 2FA**

The first time you create an account you will be prompted to set up Two-Factor Authentication (2FA). If you skip this step, you will not be able to perform any admin-related actions. You can set up 2FA later from your profile in Settings.

#### **Reset 2FA**

If you have lost access to your 2FA device, please reach out to <clients@superstate.co> for assistance.

#### **Sign out**

Click on the user icon at the top right and select Sign Out.

***

## Portfolio

View all holdings and transactions for your organization.

#### **Overall balances**

View a chart of your organization's balance and per-asset fund balances. If you have multiple entities, this balance combines them all.

#### **Investing Entity**

Each investing entity has its own card with a table of assets. You can expand each asset row to reveal any sub-balances across different chains or protocols.

#### **Actions**

Each asset has a set of actions that can be performed. With the exception of book-entry transactions, all of them will be completed outside of the investor portal in your chosen wallet or custodian platform:

* **Purchase**: Instructions for how to purchase a fund.
* **Redeem**: Instructions for how to redeem a fund.
* **DeFi**: Links to all available DeFi protocols for an asset.
* **Tokenize**: Action to convert book-entry shares to tokens
* **Burn**: Instructions to convert tokens to book-entry shares

More information about purchasing and redeeming funds can be found in the [USTB](/investors/tokenized-funds/ustb) and [USCC](/investors/tokenized-funds/uscc) sections of this documentation.

#### **Transaction History**

View your history of purchases, redemptions, tokenizations, sends, and receives. Each item includes the amount, dollar value, net asset value, date, and status. Transactions remain pending until tokens or shares are delivered or payouts are processed.

***

## Documents

Access monthly statements for each Investing Entity along with disclosures and reference materials for Superstate funds.

* **Statements**: If you are an accredited investor who has invested in Superstate funds like USTB or USCC, you will receive monthly statement covering the balances, net income, and transactions for that month across each of your entities. You will not receive statements for equities.
* **Fund Documents**: Disclosures and documents for all Superstate funds.
* **Equity Documents**: Instructions for transferring equities between your brokerage and Superstate.

***

## Settings

Manage your Organization and Investing Entity settings from this page.

#### **Organization**

Manage who has access to all Investing Entities in your organization:

* Admins manage team membership and edit purchase/payout destinations.
* Team Members have read-only access.

#### **Inviting teammates**

Click the "Invite" button on the Team table to invite teammates to your organization. You can set new teammates as either Admins with full edit privileges, or Team Members who have view-only access.

#### **Investing Entity**

Configure the following settings for each Investing Entity:

* Applications: Complete your Investing Entity application or apply for access to Superstate Funds. Applications are hidden once they are approved.
* Transaction Preferences: Select the default destination for fund purchases and redemptions.
* Allowlist: Add and manage addresses that can hold tokenized assets.
* Payout Destinations: Manage addresses and bank accounts that can receive payouts from redemptions.
* Mailing Address: Manage the legal address of your Investing Entity.

#### **Changing Settings**

Use an Admin account with 2FA enabled to make changes. Some changes, such as updating purchase destinations, take effect immediately. Others, such as modifying allowlists, payout addresses, or bank information, require a 24-hour hold. Any Admin may cancel these pending changes in **Settings** during the hold period.


# Tokenized funds

Superstate currently offers two funds: [USTB](https://superstate.com/assets/ustb) and[ USCC](https://superstate.com/assets/uscc) (collectively, “Superstate Funds” or individually “Fund”). Shares of these Superstate Funds are issued as tokens on Ethereum, Solana, Plume, or in book-entry form. To access Superstate Funds, eligible Qualified Purchasers must onboard as an investor to each  Superstate Fund. Once onboarded they will have access to the Superstate Investor Portal where they can view information about the Superstate Funds, their account holdings, and instructions for purchasing and redeeming.

*This document should not be relied upon or be used as a substitute for the Fund Offering Documents, which are controlling and supersede any information provided here. Prospective investors are urged to seek the advice of their own counsel, tax consultants and business advisors with respect to the legal, tax, and business aspects of investing in the Fund prior to making an investment decision. Note, this document will be updated periodically.*

***

## Key Facts

| Item                    | USTB                                                | USCC                                                |
| ----------------------- | --------------------------------------------------- | --------------------------------------------------- |
| NAV/S, AUM, Yield       | See [USTB page](https://superstate.com/assets/ustb) | See [USCC page](https://superstate.com/assets/uscc) |
| Purchase and Redemption | Instant\*                                           | T+1\*                                               |
| Minimum investment      | $100k                                               | $100k                                               |
| Networks                | <p>Ethereum<br>Solana<br>Plume</p>                  | <p>Ethereum<br>Solana<br>Plume</p>                  |
| Contracts               | See [Smart contracts](/investors/smart-contracts)   | See [Smart contracts](/investors/smart-contracts)   |

\*Timing may be impacted by purchase and redemption method, plus market holidays

***

## Fund Holidays

The Funds recognize the following U.S. market holidays:

* New Year's Day – January 1
* Birthday of Martin Luther King, Jr. – January 15
* Washington's Birthday – February 19
* Good Friday – March 29
* Memorial Day – May 27
* Juneteenth National Independence Day – June 19
* Independence Day – July 4
* Labor Day – September 2
* Columbus Day – October 14
* Veterans Day – November 11
* Thanksgiving Day – November 28
* Christmas Day – December 25

#### USTB

For USTB, purchases and redemptions in USDC may still be made, but no Treasury Bills will be bought or sold. The traditional Cash Needs processes will not take place.

#### USCC

For USCC, purchases and redemptions will be calculated at the following market day NAV/share (T+1), with tokens or redemptions proceeds issued on the next market day (T+2).


# USCC

Superstate Crypto Carry Fund

The Superstate Crypto Carry Fund (the “Fund”) offers Qualified Purchasers access to crypto basis (differential between the spot and future price) strategies. The Fund optimizes the yield and risk of crypto cash-and-carry trades across the Bitcoin basis, Ether basis (including staking Ether), and U.S. Treasury securities. Shares of the Fund are issued as USCC tokens on Ethereum, Solana, and Plume, or held in book‑entry form. Subscriptions and redemptions are facilitated through USD or USDC, with liquidity each market day.

#### More info

* [Income, Fees & Yield](/investors/tokenized-funds/uscc/income-fees-and-yield)
* [Purchasing USCC](/investors/tokenized-funds/uscc/purchasing-uscc)
* [Redeeming USCC](/investors/tokenized-funds/uscc/redeeming-uscc)
* [Legal Structure](/investors/tokenized-funds/uscc/legal-structure)
* [Historical NAV/S, AUM, and Yield](https://superstate.com/assets/uscc)
* [Current holdings, supported networks, DeFi integrations, and service providers](https://superstate.com/assets/uscc)


# Income, Fees & Yield

***

## Income

The Fund invests in crypto basis positions (spot and futures on the same underlying crypto commodity), staking and/or U.S. Treasury securities. Interest income from these securities is recognized each Market Day and is reflected in the Fund's NAV.&#x20;

A market day is each day that both the New York Stock Exchange and the Federal Reserve Bank of Philadelphia are open. Each market day starts at 5:00pm ET and continues until 4:59pm ET on the following day, on a given day that NYSE and FRBP are open.

***

## Fees

The Fund incurs certain expenses necessary for daily operations, including custodial, administrative, and audit fees, and pays a 75bps management fee to the Investment Manager. These expenses are accrued each market day and are reflected in the Fund's NAV.&#x20;

The Investment Manager has elected to waive the management fee and cover all fund expenses until the Fund's AUM exceeds $50MM. Until that threshold is reached, investors incur no expenses.

***

## NAV per share

#### **How is USCC NAV calculated?**

USCC’s Net Asset Value per Share (NAV/S) is calculated as total assets minus total liabilities, divided by outstanding shares. NAV/S fluctuates daily based on accrued income and mark-to-market movements across all portfolio positions. While the 30-day yield reflects performance over a trailing period, the daily NAV/S captures snapshots of the economic value of the portfolio.

USCC’s NAV is calculated each business day using 4:00 PM ET market marks across all holdings. Each position is valued at its respective closing or reference price at the daily mark, and these values are aggregated to determine total fund assets. Outstanding shares are determined based on prior-day balances adjusted for subscriptions and redemptions.

Marking Methodology:

* Spot Assets (BTC, ETH, SOL, XRP): 4:00 PM ET Coinbase closing price
* CME Futures: 4:00 PM ET CME settlement price
* Liquid Staking Tokens (lsETH, weETH, JitoSOL): 4:00 PM ET conversion rate
* Staking Income: Accrued rewards from 5:00 PM ET (prior trading day) to 5:00 PM ET
* OTC Forwards and Options: Dealer-provided OTC marks

Daily mark-to-market adjustments ensure that NAV accurately reflects current portfolio valuations, providing transparency and enabling subscriptions and redemptions even when positions experience temporary valuation fluctuations.

#### **Why does the USCC NAV sometimes decline?**

Daily NAV reflects mark-to-market gains and losses, including unrealized valuation changes that have not been realized through trade execution. When market prices move between daily valuation points, those changes flow through NAV even if the economic value of the strategy remains intact.

For example, on December 1st, the fund enters a basis trade by purchasing 100 SOL spot at $130 and selling 100 November SOL futures at $131. By December 2nd, spot rises to $135 (+$500), while the futures price increases to $136.5 (−$550 on the short) as the basis widens from $1.00 to $1.50. This results in a $50 mark-to-market NAV decline driven by basis expansion.

This loss is unrealized, as no positions have been closed, and reflects temporary mark-to-market basis movement, which can cause the NAV to decline even though the expected value of the trade remains the collection of the $500 basis as the futures contract converges to spot at expiry.

***

## Interest accrual

USCC works in a similar way to [Lido's wstETH](https://help.lido.fi/en/articles/5231836-what-is-lido-s-wsteth). You are minted a static amount of tokens and your token balance stays the same unless you mint, burn, or transfer. The NAV increases over time, allowing you to redeem a share of USCC for an increasing amount of U.S. Dollars or USDC.

#### **How is USCC yield calculated?**

USCC’s 30-day yield is calculated based on the change in NAV over the applicable period and incorporates all realized and unrealized income, including basis accrual, staking rewards, and mark-to-market effects. The yield reflects the economic performance of the portfolio rather than cash distributions alone.


# Purchasing USCC

## Transaction settings

Before initiating a purchase, go to Settings and configure your Purchase Destination. Shares may be delivered as tokens to an allowlist address of your choosing, or as shares held in book-entry by Superstate. The minimum initial investment is $100,000, unless waived by Superstate (e.g. to test the flow of funds).

***

## Instructions

1. View instructions by navigating to the Portfolio page and clicking the Purchase button next to USCC.
2. Toggle the "Pay with" dropdown to view instructions for paying with U.S. dollars, USDC on Ethereum, or USDC on Solana.
3. Initiate a purchase by sending funds using your preferred method.
4. USCC will be delivered according to your Purchase Destination settings for your Investing Entity. You may elect to receive either tokens at your preferred allowlist address, or shares held in book-entry at Superstate.

Purchases are viewable in the Investor Portal, and you will receive confirmation emails when a purchase has been initiated and completed.

***

## Timing

* Funds received by 5 pm ET on a market day will receive USCC at that market day’s closing NAV/S shortly after 9:00 am ET on the following market day (T+1)
* Funds received after 5 pm ET on a market day will receive USCC at the next market day’s NAV/S (T+1). USCC shares will be issued shortly after 9:00 am ET on the market day following the NAV/S date (T+2).
* See [Fund Holidays](/investors/tokenized-funds#fund-holidays) for exceptions

***

## Fees

Gas fees to transfer USDC or bank fees to wire U.S. Dollars for purchases are the responsibility of the investor.


# Redeeming USCC

## Transaction settings

Before initiating a redemption, go to Settings and configure your Payout Destination. Proceeds from a redemption may be delivered as U.S. Dollars or USDC on selected networks. There is no minimum redemption amount, and you can redeem the full amount of their portfolio at any time.

***

## Instructions

1. View instructions by navigating to the Portfolio page and clicking the Redeem button next to USCC.
2. Toggle the Redeem dropdown to view instructions for redeeming USCC tokens, or USCC shares held in book-entry.
3. To redeem USCC tokens, send them to the redemption address shown in the portal. Or for Ethereum tokens, call the offchainRedeem() function on the USCC token contract. Either method will initiate a redemption.
4. To redeem USCC shares held in book-entry, click the Redeem button on the portfolio page, select your book-entry shares, and enter the amount you wish to redeem.
5. Payout will be delivered according to your Payout Destination settings for your Investing Entity. You may elect to receive U.S. Dollars at a bank account, USDC to an Ethereum address, or USDC to a Solana address.

You will receive a confirmation email when a redemption has been initiated, and you can track its status in the Transactions table on the Portfolio page.

***

## Timing

* Requests received before 5 pm ET on a market day will receive payment using that market day’s closing NAV/S on a T+1 basis.
* Requests received after 5 pm ET on a market day will receive payment using the next market day’s closing NAV/S (T+1) on a T+2 basis.
* See [Fund Holidays](/investors/tokenized-funds#fund-holidays) for exceptions

***

## Fees

Gas fees to burn or transfer USCC are the responsibility of the investor.<br>


# Legal Structure

The Fund is organized as a series of Superstate Asset Trust, a Delaware statutory trust. Superstate Advisers LLC serves as the Investment Manager for the Fund. The Delaware Statutory Trust structure means the shareholder’s investment in the Fund is in a separate legal entity which is bankruptcy remote from Superstate Advisers LLC. Additionally, this structure affords shareholders with inter-series liability limitation, meaning shareholders will not be subject to potential liability that arises against Superstate Advisers LLC.

The Fund is exempt from registration with the U.S. Securities and Exchange Commission (SEC) as a private fund per Section 3(c)(7) of the Investment Company Act and is only available to a limited subset of potential investors that meet certain criteria as outlined in the Private Placement Memorandum. The Fund is offered pursuant to 506(c) exemption of Regulation D of the Securities Act of 1933 and has filed Form D available [here](https://www.sec.gov/Archives/edgar/data/2030263/000094562124000588/xslFormDX01/primary_doc.xml).

The Fund is classified as a partnership for U.S. Federal income tax purposes and is not subject to Federal income tax liability. Shareholders are responsible for reporting their distributive share of the Fund's taxable income or loss on their own annual tax returns. Monthly unaudited reports of the Fund's performance will be provided to all shareholders. After the end of a calendar year, audited financial statements and K-1s will be provided to all shareholders.


# USTB

Superstate Short Duration US Government Securities Fund

The Superstate Short Duration US Government Securities Fund invests in short-duration U.S. Treasury Bills and targets returns in line with the federal funds rate. Shares of the Fund are issued as USTB tokens on Ethereum, Solana, and Plume, or held in book‑entry form. USTB is freely transferable between wallet addresses on the Allowlist. Purchases and redemptions are facilitated through USD or USDC, with liquidity each market day.&#x20;

#### More info

* [Income, Fees & Yield](/investors/tokenized-funds/ustb/income-fees-and-yield)
* [Purchasing USTB](/investors/tokenized-funds/ustb/purchasing-ustb)
* [Redeeming USTB](/investors/tokenized-funds/ustb/redeeming-ustb)
* [Legal Structure](/investors/tokenized-funds/ustb/legal-structure)
* [Historical NAV/S, AUM, and Yield](https://superstate.com/assets/ustb)
* [Current holdings, supported networks, DeFi integrations, and service providers](https://superstate.com/assets/ustb)


# Income, Fees & Yield

***

## Income

The Fund invests exclusively in short-duration U.S. Government Securities, including investments in U.S. Treasury Bills.  Interest income from these securities is recognized each market day and is reflected in the Fund's NAV.

A market day is each day that both the New York Stock Exchange and the Federal Reserve Bank of Philadelphia are open. Each market day starts at 9:00am ET on a given day that NYSE and FRBP are open and continues until 8:59am ET the next day that NYSE and FRBP are open.

***

## Fees

The Fund incurs certain expenses necessary for daily operations, including custodial, administrative, and audit fees, and pays up to 15bps management fee to the Investment Manager.  These expenses are accrued each market day and are reflected in the Fund's NAV.

Management Fee and other Fund expenses will not accrue until the Fund reaches a $200 million Net Asset Value; once reached, the management fee and other fees and expenses that may be incurred by investing in the Fund will accrue daily. Clients with less than $25 million Net Asset Value will be charged a 0.15% management fee. Clients with over $25 million Net Asset Value will be charged a 0.15% management fee on $25 million Net Asset Value and a 0.05% management fee on the Net Asset Value above $25 million.

***

## NAV per share

The Net Asset Value per share (or NAV/S) is the price per share of USTB, and represents the value of a share, after accounting for all investor cash flows, interest income, and fund expenses. The NAV/S of USTB is recorded with 6 decimal places of accuracy.

NAV/S started at $10.000000, and increments continuously as the Fund's investments accrue interest. NAV/S is calculated by taking the total Assets Under Management (AUM) in the Fund and dividing by the total number of shares in the Fund.

#### Continuous NAV/S

USTB features a **Continuous NAV/S** that updates every second, 24 hours a day, 365 days of the year. This is achieved by using the day-over-day growth rate of the Fund's NAV/S to extrapolate the price at any given time, with the growth rate recalculated based on data from our NAV Calculation Agent partner. Purchases and Redemptions are priced using the Continuous NAV/S at the time a transaction is initiated.

***

## Interest accrual

USTB works in a similar way to Lido's[ wstETH](https://help.lido.fi/en/articles/5231836-what-is-lido-s-wsteth). You are minted a static amount of tokens and your token balance stays the same unless you mint, burn, or transfer. The NAV increases over time, allowing you to redeem a share of USTB for an increasing amount of U.S. Dollars or USDC.


# Purchasing USTB

## Transaction settings

Before initiating a purchase go to Settings and configure your Purchase Destination. Shares may be delivered as tokens to an allowlisted address, or as shares held in Book-Entry at Superstate. The minimum initial investment is $100,000, unless waived by Superstate (e.g. to test the flow of funds).

***

## Instructions

1. View purchase instructions by navigating to the Portfolio page and clicking the Purchase button next to USTB.
2. Toggle the "Pay with" dropdown to view instructions for paying with U.S. dollars or USDC on a supported network.
3. Initiate a purchase by sending funds using your preferred method.
4. USTB features Continuous Pricing, meaning that your Purchase will be priced at the NAV/S at the time your funds are received.&#x20;
5. USTB will be delivered according to your Purchase Destination settings for your Investing Entity. You may elect to receive either tokens at your preferred allowlist address, or shares held in book-entry at Superstate.

You will receive a confirmation email when a purchase has been initiated, and you can track its status in the Transactions table on the Portfolio page.

For **protocol purchase** instructions please see <https://docs.superstate.co/introduction-to-superstate/smart-contracts#subscribe-function>

## Timing

* Purchases made with USDC are attributed instantly, and tokens or book-entry shares are delivered within minutes.
* Purchases made with US dollar wires are processed whenever they are received. Wires are typically received same-day if initiated before 1pm ET and next day if initiated later. Tokens or book-entry shares are delivered within minutes of receipt.
* See [Fund Holidays](/investors/tokenized-funds#fund-holidays) for exceptions

## Fees

Gas fees to transfer USDC or bank fees to wire U.S. Dollars for purchases are the responsibility of the investor.


# Redeeming USTB

## Transaction settings

Before initiating a redemption, go to Settings and configure your Payout Destination. Proceeds from a redemption may be delivered as U.S. Dollars or USDC on select networks. There is no minimum redemption amount, and you can redeem the full amount of your holdings at any time.

***

## Instructions

1. View instructions by navigating to the Portfolio page and clicking the Redeem button next to USTB.
2. Toggle the Redeem dropdown to view instructions for redeeming USTB tokens, or USTB shares held in book-entry.
3. To redeem USTB tokens, send them to the redemption address shown in the portal. Or for Ethereum tokens, call the offchainRedeem() function on the USTB token contract. Either method will initiate a redemption.
4. To redeem USTB shares held in book-entry, click the Redeem button on the portfolio page, select your Book-Entry shares, and enter the amount you wish to redeem.
5. USTB features Continuous Pricing, meaning that your redemption will be priced at the NAV/S at the time your shares are received.
6. Payout will be delivered according to your Payout Destination settings for your Investing Entity. You may elect to receive U.S. Dollars at a bank account, USDC to an Ethereum address, or USDC to a Solana address.

You will receive a confirmation email when a redemption has been initiated, and you can track its status in the Transactions table on the Portfolio page.

For Protocol Redemption instructions please see: <https://docs.superstate.com/introduction-to-superstate/smart-contracts#redemptionidle-contract>

***

## Timing

* Redemptions with a USDC payout are processed immediately when there is liquidity available. Please see the [liquidity API](https://api.superstate.com/v1/funds/liquidity) for more information, or the tooltip on the redemption modal in the investor portal.
* Redemptions with a US dollar payout are processed the same day if the request is received before 1pm ET. Requests after 1pm ET are paid out T+1
* See [Fund Holidays](/investors/tokenized-funds#fund-holidays) for exceptions

***

## Fees

Gas fees to burn or transfer USTB are the responsibility of the investor.


# Legal Structure

The Fund is organized as a series of Superstate Asset Trust, a Delaware statutory trust. Superstate Advisers LLC serves as the Investment Manager for the Fund. The Delaware Statutory Trust structure means the shareholder’s investment in the Fund is in a separate legal entity which is bankruptcy remote from Superstate Advisers LLC. Additionally, this structure affords shareholders with inter-series liability limitation, meaning shareholders will not be subject to potential liability that arises against Superstate Advisers LLC.

The Fund is exempt from registration with the U.S. Securities and Exchange Commission (SEC) as a private fund per Section 3(c)(7) of the Investment Company Act and is only available to a limited subset of potential investors that meet certain criteria as outlined in the Private Placement Memorandum. The Fund is offered pursuant to 506(c) exemption of Regulation D of the Securities Act of 1933 and has filed Form D available [here](https://www.sec.gov/Archives/edgar/data/2004367/000200436724000001/xslFormDX01/primary_doc.xml).

The Fund is classified as a partnership for U.S. Federal income tax purposes and is not subject to Federal income tax liability. Shareholders are responsible for reporting their distributive share of the Fund's taxable income or loss on their own annual tax returns. Monthly unaudited reports of the Fund's performance will be provided to all shareholders. After the end of a calendar year, audited financial statements and K-1s will be provided to all shareholders.


# Tokenized equities

With Superstate Opening Bell, investors can access tokenized shares on Solana and Ethereum. These aren't derivatives or synthetic tokens. These are legal shares of public companies, tokenized onchain.

***

## Available equities

See <https://superstate.com/assets> for a full list of equities tokenized by Superstate.

***

## Onboarding

Tokenized shares are available to all investors in supported jurisdictions and do **not** require accredited investor status.

* New users can register a Superstate account at [superstate.com/register](https://superstate.com/register).
* Existing investors can simply log into their existing account to view available equities.

For a more detailed walkthrough of onboarding please see [Getting started](/investors/getting-started)

***

## Equity Allowlist&#x20;

In order to hold tokenized shares in your third party wallet, you must first add that address to the allowlist.&#x20;

1. Before adding a wallet address to your allowlist, confirm which networks are supported for a given equity. Do this by visiting each equity page from [superstate.com/opening-bell](https://superstate.com/opening-bell)
2. To add your wallet to the allowlist, go to Settings → Allowlist → Add
3. Select the network, enter your wallet address, and give it a nickname

Once an address is added to the allowlist it can hold a token for that equity.&#x20;

***

## Transferring existing shares

Holders of supported shares can transfer shares from their traditional brokerage to Superstate.&#x20;

1. Go to Document → Equity Documents
2. Download the transfer form for the company shares you wish to transfer
3. Follow the instructions in the form to initiate a DRS transfer from your brokerage
4. Once shares are transferred from your brokerage to the underlying transfer agent, you can submit the transfer authorization form to the emails on the form

Once complete, shares will appear in your Superstate account in book-entry form. Depending on your brokerage this can take between 2-3 business days from start to finish.

***

## Tokenizing existing shares

If you hold book-entry shares at Superstate, you can convert them into tokens.

1. Go to Portfolio and click on Tokenize next to your book-entry balance
2. Select an amount and a previously added allowlist address
3. Click Tokenize

Your book-entry shares will be converted to tokens and delivered to your wallet.

***

## Trading tokenized shares

Unlike Superstate Funds, shares cannot be directly bought or sold on Superstate. Instead investors can visit a supported DEXs to buy or sell.

1. Go to Portfolio and click Trade
2. In the Trade modal, you can view a list of links to supported DEXs to trade that asset
3. Once you are in the DEX, make sure that you are connected to the same wallet that you added to the allowlist.

***

## Redeeming tokens to book-entry

Tokens can be converted back into book-entry shares. Some investors may choose to do this in order to then transfer them back into their traditional brokerage.

1. Go to Portfolio and click Redeem
2. In the Redeem modal, you can see instructions for how to burn your tokens by sending them to a redemption address
3. Send the tokens from your third party wallet to the address to burn them
4. After the transaction has confirmed onchain, you'll see an updated book-entry balance in the portfolio

To transfer the shares back to your traditional brokerage, you can find the corresponding instructions and transfer authorization form for that equity in Documents.


# Security

***

## Overview

Superstate's highest priority is the protection of investor assets; [USTB and USCC](/investors/smart-contracts) have been designed holistically with security in mind. We work with world-class service providers, and have robust internal security policies designed to minimize operational risks.

The assets that back our funds are stored offchain with qualified custodians, and Superstate has overlapping, redundant records of ownership of our funds, including at our fund calculation agent, internally, and on-chain. In the unusual event in which an investor's Allowlist address is compromised, there are procedures in place capable of restoring your investment.\
\
Each core component of our platform has been audited, and safeguards have been put in place to protect all investor funds.

***

## Fund Custodians

<table><thead><tr><th width="243">Fund</th><th>Custodian</th></tr></thead><tbody><tr><td>USTB</td><td><a href="https://www.umb.com/institutional-banking/institutional-custody">UMB Bank, N.A.</a></td></tr><tr><td>USCC</td><td>Fund digital assets and cash are held at <a href="https://www.anchorage.com/">Anchorage Digital Bank N.A.</a>, with futures positions and margin maintained at the Trading Venues.</td></tr></tbody></table>

For investors that purchase and redeem using USDC, cash and USDC are temporarily custodied at Circle.

***

## Private Key Management

Facilitated by Turnkey. See their documentation [here](https://docs.turnkey.com/home).

***

## Bug Bounty Program

Superstate encourages the community to audit our contracts and security; we also encourage the responsible disclosure of any issues. This program is intended to recognize the value of working with the community of independent security researchers.&#x20;

#### Rewards

Superstate does not have a formal reward policy. Researchers should not expect compensation for discovering vulnerabilities. However, we are grateful for all legitimate vulnerability discoveries and will acknowledge researchers after a fix has been widely deployed.

#### Disclosure

Submit all bug bounty disclosures to <security@superstate.co>. The disclosure must include clear and concise steps to reproduce the discovered vulnerability in either written or video format. We will follow up promptly with acknowledgement of the disclosure.

#### What to Expect from Us

When working with us according to this policy, you can expect us to:

* Extend Safe Harbor protection for your vulnerability research related to this policy;
* Work with you to understand and validate your report, including providing a timely initial response to the submission;
* Work to remediate discovered vulnerabilities in a timely manner; and
* Recognize your contribution if you're the first to report a unique vulnerability that triggers a code or configuration change.

#### Ground Rules for Researchers

To encourage vulnerability research and to avoid any confusion between good-faith hacking and malicious attack, we ask that you:

* Follow this policy and any other relevant agreements.
* Report discovered vulnerabilities promptly.
* Avoid violating privacy, disrupting systems, destroying data, or harming user experience.
* Use only specified reporting method and official communication channels.
* Keep vulnerability details confidential until fixed, as per the Disclosure Policy.
* Test only in-scope systems and respect out-of-scope systems and activities.
* Limit data access when demonstrating a Proof of Concept, and immediately report any accidental access to sensitive data.
* Interact only with test accounts you own or have explicit permission to use.
* Do not engage in extortion.

#### Safe Harbor

When conducting vulnerability research in full compliance with this policy and all applicable laws, we consider this research to be:

* Authorized in accordance with the Computer Fraud and Abuse Act (CFAA) (and/or similar state laws), and we will not initiate or support legal action against you for accidental, good faith violations of this policy;
* Exempt from the Digital Millennium Copyright Act (DMCA), and we will not bring a claim against you for circumvention of technology controls;
* Exempt from restrictions in our Terms & Conditions that would interfere with conducting security research, and we waive those restrictions on a limited basis for work done under this policy; and
* Lawful, helpful to the overall security of the Internet, and conducted in good faith.

If you're unsure whether your research is consistent with this policy, please report through our official channels before proceeding.


# Smart contracts

***

## EVM contracts

{% tabs %}
{% tab title="Ethereum Mainnet" %}

* AllowlistV3 Proxy - <https://etherscan.io/address/0x02f1fa8b196d21c7b733eb2700b825611d8a38e5>
* USTB Token Proxy - <https://etherscan.io/address/0x43415eB6ff9DB7E26A15b704e7A3eDCe97d31C4e>
* USCC Token Proxy - <https://etherscan.io/address/0x14d60e7fdc0d71d8611742720e4c50e7a974020c>
* USTB RedemptionIdle Proxy - <https://etherscan.io/address/0x4c21b7577c8fe8b0b0669165ee7c8f67fa1454cf>
* Superstate USTB Continuous Price Oracle - <https://etherscan.io/address/0xe4fa682f94610ccd170680cc3b045d77d9e528a8>
* Chainlink USTB Oracle - <https://etherscan.io/address/0x289B5036cd942e619E1Ee48670F98d214E745AAC>
* Chainlink USCC Oracle - [https://etherscan.io/address/0xAfFd8F5578E8590665de561bdE9E7BAdb99300d9](<https://etherscan.io/address/0xAfFd8F5578E8590665de561bdE9E7BAdb99300d9&#xA;>)
  {% endtab %}

{% tab title="Sepolia Testnet" %}

* AllowlistV3 Proxy - <https://sepolia.etherscan.io/address/0x4b056c23abf9a4c94ec10821b731ced73601a845>
* USTB Token Proxy -<https://sepolia.etherscan.io/address/0x39727692cF58137Bd8c401eFE87Cc8A190D62ead>
* USCC Token Proxy - <https://sepolia.etherscan.io/address/0xebba0e36545903f64291c4ba6d2c3b51c57a812e>
* USTB RedemptionIdle Proxy - <https://sepolia.etherscan.io/address/0xd33d340cdbef8e879c827199bd7d9705b21e18c9>
* Superstate USTB Continuous Price Oracle - <https://sepolia.etherscan.io/address/0xba595155585b3572f17ee1050d8c6fb9653fcb93>
* Chainlink USTB Oracle - <https://sepolia.etherscan.io/address/0x732d3C7515356eAB22E3F3DcA183c5c65102d518>
* Chainlink USCC Oracle - [https://sepolia.etherscan.io/address/0xE38b0917888d0d5d8d03B7371d5214A1aF8e1892](<https://sepolia.etherscan.io/address/0xE38b0917888d0d5d8d03B7371d5214A1aF8e1892&#xA;>)
  {% endtab %}

{% tab title="Plume Mainnet" %}

* AllowlistV3 Proxy - <https://phoenix-explorer.plumenetwork.xyz/address/0x06ed3c1cfd09e3665f72928517c86f6a87e8c35d>
* USTB Token Proxy - <https://phoenix-explorer.plumenetwork.xyz/address/0xe4fa682f94610ccd170680cc3b045d77d9e528a8>
* USCC Token Proxy - <https://phoenix-explorer.plumenetwork.xyz/address/0x4c21b7577c8fe8b0b0669165ee7c8f67fa1454cf>
  {% endtab %}

{% tab title="Plume Testnet" %}

* AllowlistV3 Proxy - <https://testnet-explorer.plumenetwork.xyz/address/0x4b056c23abf9a4c94ec10821b731ced73601a845>
* USTB Token Proxy - <https://testnet-explorer.plumenetwork.xyz/address/0x39727692cf58137bd8c401efe87cc8a190d62ead>
* USCC Token Proxy - <https://testnet-explorer.plumenetwork.xyz/address/0xebba0e36545903f64291c4ba6d2c3b51c57a812e>
  {% endtab %}
  {% endtabs %}

Our smart contracts are upgradable and various functions are gated behind the Superstate Admin Address calling them. This includes all minting, adding or removing users from the allowlist, and forcibly burning an investor’s tokens (if required by exogenous legal circumstances, for example).

#### Code Repositories

* [Github - USTB](https://github.com/superstateinc/ustb/tree/main)
* [Github - on-chain redemptions](https://github.com/superstateinc/onchain-redemptions)

#### Audits

* <https://chainsecurity.com/security-audit/compound-suptb/>
* <https://0xmacro.com/library/audits/superstate-1>
* <https://0xmacro.com/library/audits/superstate-2>
* <https://0xmacro.com/library/audits/superstate-3>
* <https://0xmacro.com/library/audits/superstate-4>
* <https://0xmacro.com/library/audits/superstate-5>
* <https://0xmacro.com/library/audits/superstate-6>
* <https://0xmacro.com/library/audits/superstate-7>
* <https://0xmacro.com/library/audits/superstate-8>
* <https://0xmacro.com/library/audits/superstate-9>
* <https://0xmacro.com/library/audits/superstate-10>
* <https://0xmacro.com/library/audits/superstate-11>

{% file src="/files/iBrehX5OPLl9D7AnlDUS" %}

***

## SVM contracts

{% tabs %}
{% tab title="Solana Mainnet" %}

* Allowlist - <https://explorer.solana.com/address/HFkKyweJDUuGer5KaCst5qZSYD5aapKaD7xzdNaoRtfA>
* USTB Token 2022 - <https://explorer.solana.com/address/CCz3SGVziFeLYk2xfEstkiqJfYkjaSWb2GCABYsVcjo2>
* USCC Token 2022 - <https://explorer.solana.com/address/BTRR3sj1Bn2ZjuemgbeQ6SCtf84iXS81CS7UDTSxUCaK>
* Burn Address - <https://explorer.solana.com/address/2u8YwJTykTreziHBN5QwE7Bi2SyN8M2MicCscthtph9E>
* Pyth USTB Oracle - <https://explorer.solana.com/address/EqggHKbjePzmXAX6MW3EsgjiJ4mhkbb8j5s5KfGs1gLq>
* Pyth USCC Oracle - <https://explorer.solana.com/address/823Y4cV7XH2TzkB9NdHfTRoCKLrqXv8EgQP5nzEG43Hp>
* Pyth FWDI Superstate Oracle (for DeFi protocols) - <https://insights.pyth.network/price-feeds/Crypto.Index.FWDI%2FUSD>
* Pyth FWDI Nasdaq Oracle - <https://insights.pyth.network/price-feeds/Equity.US.FWDI%2FUSD>
* Pyth GLXY Superstate Oracle (for DeFi protocols) - <https://insights.pyth.network/price-feeds/Crypto.Index.GLXY%2FUSD>
* Pyth GLXY Nasdaq Oracle - <https://insights.pyth.network/price-feeds/Equity.US.GLXY%2FUSD>
  {% endtab %}

{% tab title="Solana Devnet" %}

* Allowlist - <https://explorer.solana.com/address/Fdq29GdM8sZtbL9xrLLKwFEo3GuGHo6C2r4VKEWATqQW?cluster=devnet>
* USTB Token 2022 - <https://explorer.solana.com/address/2mBiupxRpJQKnWEDvUmiuPpGyKrmPqsKLeeHdL4JUvRM?cluster=devnet>
* USCC Token 2022 - <https://explorer.solana.com/address/CmfVS7ucShR4hgVESvjJpPE4k4b6Zv4AoTzT8rEipvrP?cluster=devnet>
* Burn Address - <https://explorer.solana.com/address/7pt81Zc8ywxdhfBzV9d8uLe5YU27MNoJh8ZGA7iJmEBE?cluster=devnet>
* Pyth USTB Oracle - <https://explorer.solana.com/address/EqggHKbjePzmXAX6MW3EsgjiJ4mhkbb8j5s5KfGs1gLq?cluster=devnet>
* Pyth USCC Oracle - <https://explorer.solana.com/address/823Y4cV7XH2TzkB9NdHfTRoCKLrqXv8EgQP5nzEG43Hp?cluster=devnet>
  {% endtab %}
  {% endtabs %}

Our Allowlist program is upgradeable. To simplify integrations, it has both a [Rust SDK](https://crates.io/crates/superstate-allowlist-interface) and a [Typescript SDK](https://www.npmjs.com/package/@superstateinc/allowlist).

***

## Allowlist Audits

{% file src="/files/Bd8PXKZtcG1JDz16chd1" %}

{% file src="/files/WzC0z0G1Fe3mfXR25n80" %}

* Macro Audit - <https://0xmacro.com/library/audits/superstate-7>

***

## **USTB and USCC Shared Functionality**

#### EVM Design

A standard Upgradable OpenZeppelin ERC-20 implementation with a few changes:

1. USTB/USCC check that all holders are on the Superstate controlled Allowlist contract and are authorized for that token.
2. Redeem - Investors can call the `offchainRedeem`function or transfer their USTB/USCC to the contract address to kick off a standard redemption
3. Mint - Superstate can call the `mint` function to mint new shares of USTB/USCC when investors subscribe to the fund

#### SVM Design

Our tokens use the [SPL Token 2022 Program](https://spl.solana.com/token-2022) with the following extensions:

* [Default Account State](https://solana.com/developers/courses/token-extensions/default-account-state) (set to Frozen)
* [Permanent Delegate](https://solana.com/developers/courses/token-extensions/permanent-delegate)
* [ScaledUi](https://solana.com/docs/tokens/extensions/scaled-ui-amount)
* [Immutable Owner](https://solana.com/developers/courses/token-extensions/immutable-owner)
* [Metadata and Metadata Pointer](https://solana.com/developers/courses/token-extensions/token-extensions-metadata)

The tokens are permissioned by a novel and first of its kind Allowlist Program that allows for seamless integration with DeFi protocols.

#### Transfers

USTB/USCC is freely transferrable between addresses that are on the Allowlist.

* **EVM:** This is via `transfer` or `transferFrom`. Each function checks that the sender and receiver are both on the Allowlist and authorized for that specific token.
* **SVM:** This is done the `Transfer` or `TransferChecked` Instructions. Once an account has been thawed by the Allowlist program, that account is able to freely transfer between other addresses that have been thawed.<br>

#### Burn to book-entry

It is possible to convert tokenized shares into shares held in book-entry:

* **EVM:** This is done by calling the `bridgeToBookEntry` function onchain.
* **SVM**: Burn to book-entry is not supported for shares of funds held as SVM tokens. Instead investors can redeem shares held as SVM tokens, set their purchase destination to book-entry, and re-purchase the same fund.<br>

#### Bridging

* **EVM:** This is done by calling the `bridge` function. It allows users to burn their tokens on the source chain, and receive the specified number of tokens on supported destination chains. This functionality makes it easy for users of all types to move their tokens cheaply and efficiently across chains. As mentioned in the burn to book-entry section, the helper function `bridgeToBookEntry` allows users to burn their tokens and hold their shares in book entry with Superstate, instead of onchain as an ERC-20.
* **SVM:** Bridging is not supported for shares of funds held as SVM tokens. Instead investors can redeem shares held as SVM tokens, set their purchase destination to another chain, and re-purchase the same fund.<br>

#### EVM Allowlist

Adds/Removes Ethereum addresses to/from the allowlist with certain permissions. Fund tickers are used with `privateInstrumentPermissionByEntityId` determine if an entity is allowed to interact with a specific fund's token or not\
\
Ethereum addresses are also grouped by their Entity Id. Entity Ids are how Superstate identifies investors.\
\
The USTB/USCC token contract calls `isAddressAllowedForPrivateInstrument` on the Allowlist contract to see if the sender and receiver of USTB are allowed to hold it.\
\
Only the Superstate Admin Address can make any changes to the allowlist, using the following functions `setEntityAllowedForPrivateInstrument`, `setProtocolAddressPermission`, `setProtocolAddressPermissions`, `setEntityIdForAddress`, `setEntityIdForMultipleAddresses`, `setEntityPermissionsAndAddresses.`

We call these functions when onboarding or offboarding an investor.\
\
We only add Ethereum addresses for investors that have made it through our KYC / Investment Agreement processes. However, Superstate Inc. audited DeFi protocols may be added to the allowlist at our discretion.

#### SVM Allowlist

On the SVM, Superstate adds/removes addresses via the [admin\_add\_public\_allowed\_account](https://docs.rs/superstate-allowlist-interface/0.1.0/superstate_allowlist_interface/instruction/fn.admin_add_public_allowed_account.html) or [admin\_add\_private\_allowed\_account](https://docs.rs/superstate-allowlist-interface/0.1.0/superstate_allowlist_interface/instruction/fn.admin_add_private_allowed_account.html) instructions.

The Allowlist Program is the Freeze Authority for Superstate Tokens, and [provides a permissionless Thaw instruction](https://docs.rs/superstate-allowlist-interface/0.1.0/superstate_allowlist_interface/instruction/fn.thaw.html) for DeFi protocols can call to seamlessly integrate and onboard users within existing flows.

Both the Rust and Typescript SDKs provide helper methods for clients to read the Allowlist Program's internal state. This can be used to determine if an address is on the allowlist, for example.

***

## **USTB Specific Functionality**&#x20;

#### Subscribe function (Ethereum only)

Protocols can mint USTB by calling the `subscribe` function on the Ethereum USTB contract. This function atomically transfers the investor’s USDC to Superstate, and newly minted USTB into the investor’s wallet in one transaction. The price per share is read from the Superstate USTB Continuous Price oracle contract. There are no limits for subscriptions.

Users must call `approve` on the USDC contract before calling `subscribe` on the USTB contract.

DeFi Protocols will be interested in the `calculateSuperstateTokenOut(uint256 inAmount, address stablecoin) returns (uint256 superstateTokenOutAmount, uint256 stablecoinInAmountAfterFee, uint256 feeOnStablecoinInAmount)` function, also on the USTB contract. Given an `inAmount` of stablecoin it will give you the `superstateTokenOutAmount` you should expect to receive back accounting for fees.\
\
There is also a `subscribe` function variant that takes a `to` address argument. The `to` address can be any of your entity's Allowlisted Ethereum addresses and USTB is sent to it.&#x20;

At time of writing, fees are set to 0 and only USDC is supported. For more information, please visit [superstate.com/ustb](http://superstate.com/ustb).

#### RedemptionIdle Contract (Ethereum only)

The RedemptionIdle contract holds USDC liquidity while waiting to facilitate USTB redemptions. Investors can call the `redeem` function on the contract to burn USTB from the investor’s wallet and receive USDC in one transaction. USDC liquidity will be replenished in this contract regularly to facilitate protocol redemptions. The `redeem` function will revert if there is not enough USDC in the contract to match the `superstateTokenInAmount`.

Users must call `approve` on the USTB contract before calling `redeem` on the RedemptionIdle contract.

DeFi Protocols will be interested in the `calculateUstbIn(uint256 usdcOutAmount) returns (uint256 ustbInAmount, uint256 usdPerUstbChainlinkRaw)` function. This function takes a desired amount of USDC and returns how much USTB is needed for the `superstateTokenInAmount` argument of the `redeem` function to reach the `usdcOutAmount`. This function always rounds up, so the user will always hit or exceed the `usdcOutAmount`.

There is also a redeem function variant that takes a `to` address argument. The `to` address can be any Ethereum address and USDC is sent to it.&#x20;

At time of writing, fees are set to 0 and only USDC is supported or more information please visit [superstate.com/ustb](http://superstate.com/ustb).

#### Superstate USTB Continuous Price Oracle (Ethereum only)

A custom onchain oracle to facilitate continuous pricing onchain, which powers Atomic Subscriptions and Redemptions. The oracle receives pricing updates from Superstate every time a new Net Asset Value per Share (NAV/S) is calculated by our NAV Calculation Agent partner. When a continuous price is requested, the Oracle does linear extrapolation using the two newest NAV/S checkpoints to calculate it.

\
Any smart contract can request a continuous price onchain. The Oracle contract uses the Chainlink `AggregatorV3Interface`, so it works out of the box with any Chainlink data feed integrations. <https://docs.chain.link/data-feeds/api-reference#functions-in-aggregatorv3interface>

#### Chainlink USTB/USCC Oracle

Chainlink puts the USTB/USCC Net Asset Value per Share price onchain once per day. The Oracle contract uses the AggregatorV3Interface.<https://docs.chain.link/data-feeds/api-reference#functions-in-aggregatorv3interface>&#x20;

This oracle has the daily USTB/USCC NAV/S price and can be used like any other Chainlink oracle.

***


# API

***

## Overview

Superstate offers APIs for all information about our tokens/funds including Net Asset Value per Share, AUM, total outstanding shares, pricing, and yield. &#x20;

| Fund | Fund ID |
| ---- | ------- |
| USTB | 1       |
| USCC | 2       |

#### Key examples

The full API Spec can be found here: <https://api.superstate.com/swagger-ui/>.&#x20;

<table><thead><tr><th width="234.4453125">Endpoint</th><th>Request URL</th></tr></thead><tbody><tr><td>USTB Daily NAV</td><td><a href="https://api.superstate.com/v1/funds/1/nav-daily">https://api.superstate.com/v1/funds/1/nav-daily</a></td></tr><tr><td>USTB Yield</td><td><a href="https://api.superstate.com/v1/funds/1/yield">https://api.superstate.com/v1/funds/1/yield</a></td></tr><tr><td>USTB Holdings</td><td><a href="https://api.superstate.com/v2/funds/1/holdings">https://api.superstate.com/v2/funds/1/holdings</a></td></tr><tr><td>USCC Daily NAV</td><td><a href="https://api.superstate.com/v1/funds/2/nav-daily">https://api.superstate.com/v1/funds/2/nav-daily</a></td></tr><tr><td>USCC Yield</td><td><a href="https://api.superstate.com/v1/funds/2/yield">https://api.superstate.com/v1/funds/2/yield</a></td></tr><tr><td>USCC Holdings</td><td><a href="https://api.superstate.com/v2/funds/2/holdings">https://api.superstate.com/v2/funds/2/holdings</a></td></tr></tbody></table>

***

## Authenticated endpoints

There are two types of authenticated endpoints:

1. JWT authenticated endpoints
2. API key authenticated endpoints

#### Using JWT authenticated endpoints

Endpoints authenticated by a JWT can be used by first logging into your Superstate account on the [Superstate website](https://superstate.com/). Once you've logged in, you can call that endpoint in Swagger.

#### Using API key authenticated endpoints

We also provide certain endpoints that require an API key to access. To receive an API key for your entity or organization, please [contact us](https://superstate.com/contact-us).

Once you have your API keypair, you can use our [API key request npmjs package](https://www.npmjs.com/package/@superstateinc/api-key-request) to send a request using Typescript/Javascript:

```
npm install @superstateinc/api-key-request
```

If you prefer to build the request yourself, or are using a different language, the source code and instructions are located here:

<https://github.com/superstateinc/request-with-api-key>


# Transactions API

This document describes the available query parameters for filtering transactions via the `/v2/transactions` endpoint.&#x20;

***

## Authentication

This endpoint requires API key authentication with the `TransactionViewer` role. Contact Superstate for an API key.&#x20;

***

## Sending a request

For information on how to send a request, please see the [API key section on the API page](/investors/api#using-api-key-authenticated-endpoints).

#### Example

```typescript
import { superstateApiKeyRequest, TransactionStatus } from '@superstateinc/api-key-request';

const transactions = await superstateApiKeyRequest({
  apiKey: SUPERSTATE_API_KEY,
  apiSecret: SUPERSTATE_API_SECRET,
  endpoint: "/v2/transactions",
  method: "GET",
  queryParams: {
    from_timestamp: "2024-10-01T00:00:00Z",
    transaction_status: TransactionStatus.Pending,
    transaction_type: "Purchase,Redeem",
  },
});

console.log(transactions);
```

***

## Query parameters

#### transaction\_status

Filter transactions by their current status.

| Property       | Value                                    |
| -------------- | ---------------------------------------- |
| Type           | `string`                                 |
| Required       | No                                       |
| Allowed Values | `Pending`, `PaymentPending`, `Completed` |

**Status Descriptions:**

* `Pending` - Transaction has been initiated but not yet completed
* `PaymentPending` - Payment has been initiated (e.g., USDC transfer) but awaiting confirmation (approximately 12 blocks)
* `Completed` - Transaction has been fully processed

**Example:**

```
GET /v2/transactions?transaction_status=Completed
```

#### transaction\_type

Filter transactions by one or more transaction types. Multiple types can be specified as a comma-separated list.

| Property | Value                           |
| -------- | ------------------------------- |
| Type     | `string` (comma-separated list) |
| Required | No                              |

**Important:** Comma-separated values must NOT contain spaces, otherwise HMAC signatures will not match.

**Allowed Values:**

| Category     | Types                                                                                                                                                                 |
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **General**  | `OnchainTransfer`, `Tokenize`, `Bridge`, `ProtocolTransfer`, `AdminAdjustment`                                                                                        |
| **Funds**    | `UsdPurchase`, `UsdcPurchase`, `Purchase`, `Redeem`, `Burn`, `ProtocolMint`, `ProtocolRedeem`, `MintRequest`, `RedemptionRequest`                                     |
| **Equities** | `Issuance`, `Vest`, `Unlock`, `Release`, `Lockup`, `TaTransfer`, `BookEntryTransfer`, `BookEntryBuyback`, `DipPurchase`, `OnchainDeFiLpIssuance`, `OnchainDeFiLpBurn` |

**Example:**

```
GET /v2/transactions?transaction_type=Purchase,Redeem
```

#### from\_timestamp

Filter transactions created on or after this UTC timestamp.

| Property | Value                        |
| -------- | ---------------------------- |
| Type     | `string` (ISO 8601 datetime) |
| Required | No                           |

**Example:**

```
GET /v2/transactions?from_timestamp=2024-01-01T00:00:00Z
```

#### until\_timestamp

Filter transactions created on or before this UTC timestamp.

| Property | Value                        |
| -------- | ---------------------------- |
| Type     | `string` (ISO 8601 datetime) |
| Required | No                           |

**Example:**

```
GET /v2/transactions?until_timestamp=2024-12-31T23:59:59Z
```

#### from\_price\_timestamp

Filter transactions with a price timestamp on or after this UTC timestamp.

| Property | Value                        |
| -------- | ---------------------------- |
| Type     | `string` (ISO 8601 datetime) |
| Required | No                           |

**Note:** Only transactions that have a `price_timestamp` value will be included when this filter is applied.

**Example:**

```
GET /v2/transactions?from_price_timestamp=2024-06-01T00:00:00Z
```

#### until\_price\_timestamp

Filter transactions with a price timestamp on or before this UTC timestamp.

| Property | Value                        |
| -------- | ---------------------------- |
| Type     | `string` (ISO 8601 datetime) |
| Required | No                           |

**Note:** Only transactions that have a `price_timestamp` value will be included when this filter is applied.

**Example:**

```
GET /v2/transactions?until_price_timestamp=2024-06-30T23:59:59Z
```

#### transaction\_hash

Filter transactions by a specific blockchain transaction hash.

| Property | Value    |
| -------- | -------- |
| Type     | `string` |
| Required | No       |

**Example:**

```
GET /v2/transactions?transaction_hash=0x1234567890abcdef...
```

#### from\_address

Filter transactions by the source/sender blockchain address.

| Property | Value                         |
| -------- | ----------------------------- |
| Type     | `string` (blockchain address) |
| Required | No                            |

**Example:**

```
GET /v2/transactions?from_address=0xabc123...
```

#### to\_address

Filter transactions by the destination/recipient blockchain address.

| Property | Value                         |
| -------- | ----------------------------- |
| Type     | `string` (blockchain address) |
| Required | No                            |

**Example**

```
GET /v2/transactions?to_address=0xdef456...
```

#### source\_chain\_id

Filter transactions by the source blockchain chain ID.

| Property | Value     |
| -------- | --------- |
| Type     | `integer` |
| Required | No        |

**Common Chain IDs:**

* `1` - Ethereum Mainnet
* `11155111` - Ethereum Sepolia
* `98866` - Plume Mainnet
* `98867` - Plume Testnet
* `900` - Solana MainnetBeta (internal representation chain ID)
* `901` - Solana Devnet (internal representation chain ID)

**Example:**

```
GET /v2/transactions?source_chain_id=1
```

#### destination\_chain\_id

Filter transactions by the destination blockchain chain ID.

| Property | Value     |
| -------- | --------- |
| Type     | `integer` |
| Required | No        |

**Example:**

```
GET /v2/transactions?destination_chain_id=11155111
```

#### source\_chain\_name

Filter transactions by the source blockchain name.

| Property | Value    |
| -------- | -------- |
| Type     | `string` |
| Required | No       |

**Example:**

```
GET /v2/transactions?source_chain_name=ethereum
```

#### destination\_chain\_name

Filter transactions by the destination blockchain name.

| Property | Value    |
| -------- | -------- |
| Type     | `string` |
| Required | No       |

**Example:**

```
GET /v2/transactions?destination_chain_name=sepolia
```

#### dip\_market\_id

Filter transactions by a specific DIP (Direct Issuance Program) market ID.

| Property | Value           |
| -------- | --------------- |
| Type     | `string` (UUID) |
| Required | No              |

**Example:**

```
GET /v2/transactions?dip_market_id=550e8400-e29b-41d4-a716-446655440000
```

#### entity\_id

Filter transactions to only those associated with a specific entity.

| Property | Value     |
| -------- | --------- |
| Type     | `integer` |
| Required | No        |

**Note:** This filter is applied within the scope of the API key's permissions. An organization-scoped API key can filter by any entity within that organization.

**Example:**

```
GET /v2/transactions?entity_id=12345
```

#### subaccount\_id

Filter transactions to only those associated with a specific subaccount.

| Property | Value     |
| -------- | --------- |
| Type     | `integer` |
| Required | No        |

**Example:**

```
GET /v2/transactions?subaccount_id=67890
```

***

## Combining filters

Multiple filters can be combined in a single request. All filters are applied using AND logic.

**Example - Get all completed purchases in Q4 2024:**

```
GET /v2/transactions?transaction_status=Completed&transaction_type=Purchase,UsdcPurchase&from_timestamp=2024-10-01T00:00:00Z&until_timestamp=2024-12-31T23:59:59Z
```

**Example - Get transactions for a specific entity on Ethereum:**

```
GET /v2/transactions?entity_id=123&source_chain_id=1
```

***

## Response

Returns an array of `TransactionV2` objects sorted by `created_at` in descending order (newest first).

```json
[
  {
    "entity_id": 123,
    "entity_name": "Example Corp",
    "ticker": "USTB",
    "instrument_domain": "Funds",
    "operation_type": "Purchase",
    "status": "Completed",
    "share_amount": "1000.00",
    "dollar_amount": "10000.00",
    "created_at": "2024-12-01T12:00:00Z",
    "completed_at": "2024-12-01T12:05:00Z",
    "from_address": "0x...",
    "to_address": "0x...",
    "source_details": {
      "chain_id": 1,
      "chain_name": "ethereum",
      "transaction_hash": "0x..."
    },
    ...
  }
]
```

#### Error responses

| Status Code | Description                               |
| ----------- | ----------------------------------------- |
| 400         | Invalid request parameters                |
| 401         | Unauthorized - invalid or missing API key |
| 500         | Internal server error                     |


# Balances API

The Balances API allows you to retrieve balance information for all instruments held by your organization or a specific entity via the `/v1/balances` endpoint.

***

## Authentication

This endpoint requires an API key with either the `FundManager` or `TransactionViewer` role. Contact Superstate for an API key.&#x20;

***

## Sending a Request

For information on how to send a request, please see the [API key section on the API page](/investors/api#using-api-key-authenticated-endpoints).

Example

```typescript
import { superstateApiKeyRequest } from '@superstateinc/api-key-request';

const balances = await superstateApiKeyRequest({
  apiKey: SUPERSTATE_API_KEY,
  apiSecret: SUPERSTATE_API_SECRET,
  endpoint: "/v1/balances",
});

console.log(balances);
```

***

## Query Parameters

#### entity\_id

Filter the response to only include balances for a specific entity. Contact Superstate to get entity ID(s) associated with your organization.

| Property | Value   |
| -------- | ------- |
| Type     | integer |
| Required | No      |

**Note:** When using an entity-scoped API key, the `entity_id` parameter must match the entity ID associated with the API key.

***

## Response

The response contains balance information organized by entity, with optional organization-level aggregations.

#### Response Structure

| Field                   | Type   | Description                                                                               |
| ----------------------- | ------ | ----------------------------------------------------------------------------------------- |
| `entities`              | object | Map of entity IDs to their balance data                                                   |
| `total_portfolio_value` | object | Total portfolio value across all entities (organization-scoped keys only)                 |
| `org_balances`          | object | Aggregated balances by instrument across the organization (organization-scoped keys only) |

#### Entity Balance Data

Each entity in the `entities` map contains:

| Field         | Type    | Description                                            |
| ------------- | ------- | ------------------------------------------------------ |
| `entity_id`   | integer | The entity's unique identifier                         |
| `entity_name` | string  | The entity's display name                              |
| `balances`    | object  | Map of instrument symbols to balance details           |
| `subaccounts` | object  | (Optional) Map of subaccount IDs to their balance data |

#### Asset Balance Details

Each instrument in the `balances` map contains:

| Field               | Type   | Description                                        |
| ------------------- | ------ | -------------------------------------------------- |
| `instrument_symbol` | string | The instrument ticker (e.g., "USTB", "USCC")       |
| `instrument_domain` | string | Category: "Funds", "Equities", or "FiatCurrencies" |
| `total_shares`      | string | Total shares/units held                            |
| `total_notional`    | object | Total value in USD (when available)                |
| `price`             | object | Current price per share (when available)           |
| `balances`          | array  | Detailed breakdown by balance type                 |

#### Balance Entry Types

Each entry in the `balances` array represents a specific type of holding:

| Label                 | Description                                             |
| --------------------- | ------------------------------------------------------- |
| `BookEntryAvailable`  | Book-entry shares available for transactions            |
| `BookEntryRestricted` | Book-entry shares with transfer restrictions            |
| `Token`               | On-chain tokenized shares                               |
| `Protocol`            | Shares deposited in DeFi protocols (Aave, Morpho, etc.) |

#### Example Response

```json
{
  "entities": {
    "123": {
      "entity_id": 123,
      "entity_name": "Acme Corp",
      "balances": {
        "USCC": {
          "instrument_symbol": "USCC",
          "instrument_domain": "Funds",
          "total_shares": "0.460719",
          "total_notional": "5.267199",
          "price": "11.432564",
          "balances": [
            {
              "label": "Token",
              "instrument_symbol": "USCC",
              "instrument_domain": "Funds",
              "chain_id": 11155111,
              "subaccount_id": 222,
              "chain_address": "0x1234567890abcdef1234567890abcdef12345678",
              "name": "MyAddressNickname",
              "total_shares": "0.460719",
              "notional_balance": "5.267199",
              "notional_price": "11.432564",
              "yield_value": null,
              "restrictive_legend": null
            }
          ]
        },
        "TEST": {
          "instrument_symbol": "TEST",
          "instrument_domain": "Equities",
          "total_shares": "400.000000",
          "total_notional": null,
          "price": null,
          "balances": [
            {
              "label": "BookEntryAvailable",
              "instrument_symbol": "TEST",
              "instrument_domain": "Equities",
              "chain_id": null,
              "subaccount_id": 222,
              "chain_address": null,
              "name": null,
              "total_shares": "400.000000",
              "notional_balance": null,
              "notional_price": null,
              "yield_value": null,
              "restrictive_legend": null
            }
          ]
        },
        "USTB": {
          "instrument_symbol": "USTB",
          "instrument_domain": "Funds",
          "total_shares": "10.939991",
          "total_notional": "119.875793",
          "price": "10.957577",
          "balances": [
            {
              "label": "Token",
              "instrument_symbol": "USTB",
              "instrument_domain": "Funds",
              "chain_id": 11155111,
              "subaccount_id": 222,
              "chain_address": "0x1234567890abcdef1234567890abcdef12345678",
              "name": "MyAddressNickname",
              "total_shares": "10.939991",
              "notional_balance": "119.875793",
              "notional_price": "10.957577",
              "yield_value": null,
              "restrictive_legend": null
            }
          ]
        }
      }
    }
  },
  "total_portfolio_value": "125.142992",
  "org_balances": {
    "USCC": {
      "instrument_symbol": "USCC",
      "instrument_domain": "Funds",
      "total_shares": "0.460719",
      "total_notional": "5.267199",
      "price": "11.432564",
      "balances": [
        {
          "label": "Token",
          "instrument_symbol": "USCC",
          "instrument_domain": "Funds",
          "chain_id": 11155111,
          "subaccount_id": 222,
          "chain_address": "0x1234567890abcdef1234567890abcdef12345678",
          "name": "MyAddressNickname",
          "total_shares": "0.460719",
          "notional_balance": "5.267199",
          "notional_price": "11.432564",
          "yield_value": null,
          "restrictive_legend": null
        }
      ]
    },
    "USTB": {
      "instrument_symbol": "USTB",
      "instrument_domain": "Funds",
      "total_shares": "10.939991",
      "total_notional": "119.875793",
      "price": "10.957577",
      "balances": [
        {
          "label": "Token",
          "instrument_symbol": "USTB",
          "instrument_domain": "Funds",
          "chain_id": 11155111,
          "subaccount_id": 222,
          "chain_address": "0x1234567890abcdef1234567890abcdef12345678",
          "name": "MyAddressNickname",
          "total_shares": "10.939991",
          "notional_balance": "119.875793",
          "notional_price": "10.957577",
          "yield_value": null,
          "restrictive_legend": null
        }
      ]
    },
    "TEST": {
      "instrument_symbol": "TEST",
      "instrument_domain": "Equities",
      "total_shares": "400.000000",
      "total_notional": null,
      "price": null,
      "balances": [
        {
          "label": "BookEntryAvailable",
          "instrument_symbol": "TEST",
          "instrument_domain": "Equities",
          "chain_id": null,
          "subaccount_id": 222,
          "chain_address": null,
          "name": null,
          "total_shares": "400.000000",
          "notional_balance": null,
          "notional_price": null,
          "yield_value": null,
          "restrictive_legend": null
        }
      ]
    }
  }
}
```

***

### Error Responses

| Status Code | Description                                                                            |
| ----------- | -------------------------------------------------------------------------------------- |
| 401         | Invalid or missing API key                                                             |
| 403         | API key does not have the required permissions (FundManager or TransactionViewer role) |
| 404         | The specified entity was not found or is not accessible with this API key              |
| 500         | Internal server error                                                                  |


# Opening Bell

Superstate Opening Bell enables companies to issue publicly registered shares directly on blockchain networks like Solana and Ethereum.

***

## Onboarding

Ready to bring your company's shares onchain? Follow these steps to get started:

1. Contact us at <clients@superstate.co> and we'll guide you through the onboarding and setup process
2. Create a superstate account for your company at superstate.com/register
3. Submit an entity application
4. Once your application is approved, we will send you a Digital Transfer Agent Agreement to be signed. From there you will introduce us to your existing transfer agent, and finalize details about your tokenized shares like the supported chains and protocols.
5. Once all the details and timelines are finalized, Superstate will deploy your token on the various supported blockchains.
6. On launch day, we will allowlist supported protocols that may include exchanges.
7. Use the Superstate Issuer Portal to view and manage all details of your offering.

***

## Tokenizing

Existing shareholders like retail investors, institutions, and market makers can migrate shares from their existing brokerages or transfer agents into Superstate. Investors can find these instructions in the Documents section of the investor portal.

Shares arrive in book-entry form, and investors can tokenize them as soon as they have set up a compatible allowlist address from the portal For more information about the investor experience see [Tokenized equities](/investors/tokenized-equities)

***

## Trading

As soon as decentralized exchanges are added for a token, trading can begin. Investors cannot trade directly on Superstate, but instead can find links to the supported decentralized exchanges from the investor portal.

***

## Tracking

Superstate maintains an SEC-compliant shareholder registry across book-entry holdings, tokenized holdings, and integrated DeFi protocols. Navigate to the Issuance dashboard in the Superstate investor portal to view real-time data on the total number of tokenized shares, the number of shareholders, and to download reports.

***

## Direct Issuance

A Direct Issuance Program allows SEC-registered public company to issue new shares directly to eligible investors through a transfer agent to raise capital. Superstate's digital transfer agent technology allows issuers to administer this program using real-time market prices, settled in stablecoins, and with real shares delivered as tokens directly to an investors onchain wallet.

Eligible retail and institutional investors can purchase newly issued shares directly from the issuer at or below the Nasdaq or NYSE price, with tokenized shares settling immediately in their wallets. These shares are recorded in the investor’s name and carry the same economic and governance rights as traditional shares, with the added utility of being usable across onchain applications where permitted.


# Onboarding API

The Onboarding API allows external partners to onboard users to Superstate by submitting KYC-verified user data along with the user's wallet addresses to the be added to Superstate's onchain allowlist

***

## Authentication

All endpoints require API key authentication with the `OnboardingApi` role. Contact Superstate for an API key.

***

## Sending a Request

For information on how to send a request, please see the [API key section on the API page](/investors/api#using-api-key-authenticated-endpoints).

***

## Endpoints

| Method | Path                                     | Description                      |
| ------ | ---------------------------------------- | -------------------------------- |
| POST   | `/v1/accounts/onboard/svm`               | Create a new entity on Solana    |
| POST   | `/v1/accounts/onboard/svm/mock`          | Mock create on Solana (testing)  |
| POST   | `/v1/accounts/onboard/svm/add-allowlist` | Add allowlist address on Solana  |
| POST   | `/v1/accounts/onboard/evm`               | Create a new entity on EVM       |
| POST   | `/v1/accounts/onboard/evm/mock`          | Mock create on EVM (testing)     |
| POST   | `/v1/accounts/onboard/evm/add-allowlist` | Add allowlist address on EVM     |
| PUT    | `/v1/accounts/onboard/update`            | Update an existing entity's data |

***

## Create Individual - SVM

`POST /v1/accounts/onboard/svm`

Creates a new entity and adds the user's Solana wallet address to the allowlist. Returns a JSON-serialized partially-signed transaction that the user must sign and broadcast to complete the allowlist addition.

#### Request Body

| Field           | Type    | Required | Description                                                                                                       |
| --------------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------- |
| `version`       | integer | Yes      | The version of this API call (currently `1`)                                                                      |
| `userData`      | object  | No       | User's KYC data. If not provided, the KYC provider will be queried. See Individual User Data and Entity User Data |
| `cluster`       | string  | Yes      | The Solana cluster. Allowed values: `MainnetBeta`, `Devnet`                                                       |
| `walletAddress` | string  | Yes      | The user's Solana wallet address (base58-encoded public key)                                                      |
| `kycProvider`   | string  | Yes      | The KYC provider used to verify the user. See KYC Providers                                                       |
| `kycProviderId` | string  | Yes      | The unique identifier or share token from the KYC provider's verification result                                  |
| `forInstrument` | string  | No       | Reserved for private allowlist onboarding. Must be omitted or `null`                                              |

#### Example Request

```json
{
  "version": 1,
  "userData": {
    "firstName": "John",
    "middleName": "Michael",
    "lastName": "Doe",
    "ssnOrTin": "123-45-6789",
    "emailAddress": "john.doe@example.com",
    "streetAddress": "123 Main Street",
    "city": "New York",
    "state": "NY",
    "zipcode": "10010",
    "country": "US"
  },
  "cluster": "Devnet",
  "walletAddress": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
  "kycProvider": "Sumsub",
  "kycProviderId": "01234567890123456789"
}
```

#### Response

**Success (200)**

```json
{
  "entityId": 598,
  "walletAddress": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
  "encodedTransaction": "<JSON-serialized partially-signed Solana transaction>"
}
```

| Field                | Type    | Description                                                                                                  |
| -------------------- | ------- | ------------------------------------------------------------------------------------------------------------ |
| `entityId`           | integer | The newly created (or existing) entity ID                                                                    |
| `walletAddress`      | string  | The wallet address that was added to the allowlist                                                           |
| `encodedTransaction` | string  | JSON-serialized Solana transaction. The user must sign and broadcast this to complete the allowlist addition |

#### Validation Rules

* Wallet address must be a valid Solana public key (base58)
* Wallet address must not already be on the allowlist for the selected cluster
* Wallet address must not be a program/contract address
* If the email address already exists in Superstate's system, the existing entity will be reused

***

## Create Individual - EVM

`POST /v1/accounts/onboard/evm`

Creates a new entity and adds the user's EVM wallet address to the allowlist. Returns JSON-serialized EIP-712 signature parameters for the `setUserPermissionForInstrument` contract function.

#### Request Body

| Field           | Type    | Required | Description                                                                                                       |
| --------------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------- |
| `version`       | integer | Yes      | The version of this API call (currently `1`)                                                                      |
| `userData`      | object  | No       | User's KYC data. If not provided, the KYC provider will be queried. See Individual User Data and Entity User Data |
| `chainId`       | integer | Yes      | The EVM chain ID. See Supported Chain IDs                                                                         |
| `walletAddress` | string  | Yes      | The user's EVM wallet address (0x-prefixed hex)                                                                   |
| `kycProvider`   | string  | Yes      | The KYC provider used to verify the user. See KYC Providers                                                       |
| `kycProviderId` | string  | Yes      | The unique identifier or share token from the KYC provider's verification result                                  |
| `forInstrument` | string  | No       | Reserved for private allowlist onboarding. Must be omitted or `null`                                              |

#### Example Request

```json
{
  "version": 1,
  "userData": {
    "firstName": "Jane",
    "lastName": "Smith",
    "ssnOrTin": "987-65-4321",
    "emailAddress": "jane.smith@example.com",
    "streetAddress": "456 Oak Avenue",
    "city": "Los Angeles",
    "state": "CA",
    "zipcode": "90210",
    "country": "US"
  },
  "chainId": 1,
  "walletAddress": "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6",
  "kycProvider": "Sumsub",
  "kycProviderId": "98765432109876543210"
}
```

#### Response

**Success (200)**

```json
{
  "entityId": 598,
  "walletAddress": "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6",
  "encodedTransaction": "<JSON-serialized EIP-712 signature parameters for setUserPermissionForInstrument>"
}
```

| Field                | Type    | Description                                                                                                                |
| -------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------- |
| `entityId`           | integer | The newly created (or existing) entity ID                                                                                  |
| `walletAddress`      | string  | The wallet address that was added to the allowlist                                                                         |
| `encodedTransaction` | string  | JSON-serialized EIP-712 signature parameters. Use these to call `setUserPermissionForInstrument` on the allowlist contract |

#### Validation Rules

Same as SVM, but for EVM addresses:

* Wallet address must be a valid EVM address (0x-prefixed, 40 hex characters)
* Wallet address must not already be on the allowlist for the specified chain
* Wallet address must not be a smart contract address
* Chain ID must be a supported EVM chain

***

## Mock Endpoints

`POST /v1/accounts/onboard/svm/mock`

`POST /v1/accounts/onboard/evm/mock`

Mock endpoints for testing your integration. They accept the same request bodies as their non-mock counterparts but:

* **Skip all database operations** — no entities, users, or organizations are created
* **Skip input validation** — wallet address and chain checks are bypassed
* **Return mock data** — `entityId` is always `0`

**SVM mock**: Returns a JSON-serialized Solana transaction with an invalid blockhash (all zeros) and unsigned signatures. This transaction cannot be broadcast.

**EVM mock**: Returns JSON-serialized `setUserPermissionForInstrument` parameters with `deadline` set to `0` (expired) and zero-value signatures. This cannot be used on-chain.

#### Example Response (SVM Mock)

```json
{
  "entityId": 0,
  "walletAddress": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
  "encodedTransaction": "<JSON-serialized mock Solana transaction>"
}
```

#### Example Response (EVM Mock)

```json
{
  "entityId": 0,
  "walletAddress": "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6",
  "encodedTransaction": "<JSON-serialized mock EIP-712 parameters with expired deadline>"
}
```

***

## Add Allowlist Address - SVM

`POST /v1/accounts/onboard/svm/add-allowlist`

Adds a new Solana wallet address to the allowlist for an existing user. The user is identified by either their email address or an existing allowlisted wallet address.

#### Request Body

| Field                   | Type    | Required    | Description                                                                                       |
| ----------------------- | ------- | ----------- | ------------------------------------------------------------------------------------------------- |
| `version`               | integer | Yes         | The version of this API call (currently `1`)                                                      |
| `email`                 | string  | Conditional | Email of the user. Mutually exclusive with `existingWalletAddress` — exactly one must be provided |
| `existingWalletAddress` | string  | Conditional | An existing allowlisted wallet address to identify the user. Mutually exclusive with `email`      |
| `walletAddress`         | string  | Yes         | The new wallet address to add to the allowlist                                                    |
| `forInstrument`         | string  | No          | Reserved for private allowlist onboarding. Must be omitted or `null`                              |

**Note:** The SVM chain is determined automatically from the server's configured environment. There is no `cluster` field on this endpoint.

#### Example Request (using email)

```json
{
  "version": 1,
  "email": "john.doe@example.com",
  "walletAddress": "BKgGvQR3TmEy8zNBJfwDEVGZmt7dRUXVZDiPKYCFaLWd"
}
```

#### Example Request (using existing wallet address)

```json
{
  "version": 1,
  "existingWalletAddress": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
  "walletAddress": "BKgGvQR3TmEy8zNBJfwDEVGZmt7dRUXVZDiPKYCFaLWd"
}
```

#### Response

**Success (200)**

```json
{
  "entityId": 598,
  "walletAddress": "BKgGvQR3TmEy8zNBJfwDEVGZmt7dRUXVZDiPKYCFaLWd",
  "encodedTransaction": "<JSON-serialized partially-signed Solana transaction>"
}
```

#### Authorization

The requesting partner must be the same partner that originally onboarded the entity. If a different partner attempts to add an allowlist address, the request will be rejected with `403 Forbidden`.

***

## Add Allowlist Address - EVM

`POST /v1/accounts/onboard/evm/add-allowlist`

Adds a new EVM wallet address to the allowlist for an existing user. The user is identified by either their email address or an existing allowlisted wallet address.

#### Request Body

| Field                   | Type    | Required    | Description                                                                                       |
| ----------------------- | ------- | ----------- | ------------------------------------------------------------------------------------------------- |
| `version`               | integer | Yes         | The version of this API call (currently `1`)                                                      |
| `email`                 | string  | Conditional | Email of the user. Mutually exclusive with `existingWalletAddress` — exactly one must be provided |
| `existingWalletAddress` | string  | Conditional | An existing allowlisted wallet address to identify the user. Mutually exclusive with `email`      |
| `chainId`               | integer | Yes         | The EVM chain ID for the new address. See Supported Chain IDs                                     |
| `walletAddress`         | string  | Yes         | The new EVM wallet address to add to the allowlist                                                |
| `forInstrument`         | string  | No          | Reserved for private allowlist onboarding. Must be omitted or `null`                              |

#### Example Request

```json
{
  "version": 1,
  "email": "jane.smith@example.com",
  "chainId": 1,
  "walletAddress": "0x1234567890abcdef1234567890abcdef12345678"
}
```

#### Response

**Success (200)**

```json
{
  "entityId": 598,
  "walletAddress": "0x1234567890abcdef1234567890abcdef12345678",
  "encodedTransaction": "<JSON-serialized EIP-712 signature parameters>"
}
```

#### Authorization

Same as SVM — the requesting partner must be the same partner that originally onboarded the entity.

***

## Update Entity

`PUT /v1/accounts/onboard/update`

Updates an existing entity's onboarding data. Only the fields provided in the request will be updated — all other fields remain unchanged (partial update). The request body must include a `type` field to indicate whether this is an individual or entity update. An individual cannot be converted to an entity and vice versa. Only the company who onboarded the user initially can update the user's data.

#### Request Body

| Field      | Type    | Required | Description                                                                   |
| ---------- | ------- | -------- | ----------------------------------------------------------------------------- |
| `entityId` | integer | Yes      | The entity ID to update                                                       |
| `userData` | object  | Yes      | The fields to update. Must include `type` set to `"individual"` or `"entity"` |

**Individual Update Fields**

All fields are optional. Only provided fields will be updated.

| Field           | Type   | Description                                              |
| --------------- | ------ | -------------------------------------------------------- |
| `type`          | string | Must be `"individual"`                                   |
| `firstName`     | string | First name (1-100 characters)                            |
| `middleName`    | string | Middle name (1-100 characters)                           |
| `lastName`      | string | Last name (1-100 characters)                             |
| `ssnOrTin`      | string | SSN or Tax ID (digits and hyphens only, 1-20 characters) |
| `emailAddress`  | string | Valid email address                                      |
| `streetAddress` | string | Street address (1-100 characters)                        |
| `city`          | string | City (1-40 characters)                                   |
| `state`         | string | State or province abbreviation (1-3 characters)          |
| `zipcode`       | string | ZIP or postal code (1-11 characters)                     |
| `country`       | string | ISO 3166-1 alpha-2 country code (exactly 2 characters)   |

**Entity Update Fields**

All fields are optional. Only provided fields will be updated.

| Field           | Type   | Description                                                                |
| --------------- | ------ | -------------------------------------------------------------------------- |
| `type`          | string | Must be `"entity"`                                                         |
| `entityName`    | string | Entity name (1-100 characters)                                             |
| `entityType`    | string | Investor type (e.g., `"Corporation"`, `"LLC"`, `"Partnership"`, `"Trust"`) |
| `ssnOrTin`      | string | Tax ID (digits and hyphens only, 1-20 characters)                          |
| `emailAddress`  | string | Valid email address                                                        |
| `streetAddress` | string | Street address (1-100 characters)                                          |
| `city`          | string | City (1-40 characters)                                                     |
| `state`         | string | State or province abbreviation (1-3 characters)                            |
| `zipcode`       | string | ZIP or postal code (1-11 characters)                                       |
| `country`       | string | ISO 3166-1 alpha-2 country code (exactly 2 characters)                     |

#### Example Request (Individual)

```json
{
  "entityId": 598,
  "userData": {
    "type": "individual",
    "firstName": "Jonathan",
    "streetAddress": "789 New Street"
  }
}
```

#### Example Request (Entity)

```json
{
  "entityId": 599,
  "userData": {
    "type": "entity",
    "entityName": "Updated Corp LLC"
  }
}
```

#### Response

**Success (200)**

Returns an empty response body on success.

#### Authorization

The requesting partner must be the same partner that originally onboarded the entity. If a different partner attempts to update the entity, the request will be rejected with `403 Forbidden`.

***

## Reference

#### Individual User Data

Used in the `userData` field of create endpoints when onboarding an individual.

| Field           | Type   | Required | Validation                                             |
| --------------- | ------ | -------- | ------------------------------------------------------ |
| `firstName`     | string | Yes      | 1-100 characters                                       |
| `middleName`    | string | No       | 1-100 characters                                       |
| `lastName`      | string | Yes      | 1-100 characters                                       |
| `ssnOrTin`      | string | Yes      | Digits and hyphens only (`^[0-9-]+$`), 1-20 characters |
| `emailAddress`  | string | Yes      | Valid email address                                    |
| `streetAddress` | string | Yes      | 1-100 characters                                       |
| `city`          | string | Yes      | 1-40 characters                                        |
| `state`         | string | No       | 1-3 characters (state/province abbreviation)           |
| `zipcode`       | string | Yes      | 1-11 characters                                        |
| `country`       | string | Yes      | Exactly 2 characters (ISO 3166-1 alpha-2 country code) |

#### Entity User Data

Used in the `userData` field of create endpoints when onboarding a non-individual entity (corporation, LLC, etc.).

| Field           | Type   | Required | Validation                                                                 |
| --------------- | ------ | -------- | -------------------------------------------------------------------------- |
| `entityName`    | string | Yes      | 1-100 characters                                                           |
| `entityType`    | string | Yes      | Investor type (e.g., `"Corporation"`, `"LLC"`, `"Partnership"`, `"Trust"`) |
| `ssnOrTin`      | string | Yes      | Digits and hyphens only (`^[0-9-]+$`), 1-20 characters                     |
| `emailAddress`  | string | Yes      | Valid email address                                                        |
| `streetAddress` | string | Yes      | 1-100 characters                                                           |
| `city`          | string | Yes      | 1-40 characters                                                            |
| `state`         | string | No       | 1-3 characters (state/province abbreviation)                               |
| `zipcode`       | string | Yes      | 1-11 characters                                                            |
| `country`       | string | Yes      | Exactly 2 characters (ISO 3166-1 alpha-2 country code)                     |

**Note:** The `userData` field on create endpoints uses untagged deserialization. The API will attempt to parse as an individual first, then as an entity. Ensure your payload matches one of the two schemas above.

#### Supported EVM Chain IDs

| Chain ID | Network                  |
| -------- | ------------------------ |
| 1        | Ethereum Mainnet         |
| 11155111 | Ethereum Sepolia Testnet |
| 98866    | Plume Mainnet            |
| 98867    | Plume Testnet            |

For SVM, use the `cluster` field with values `MainnetBeta` or `Devnet` instead of a chain ID.

#### Error Responses

| Status Code | Description                                                                                          |
| ----------- | ---------------------------------------------------------------------------------------------------- |
| 400         | Bad request — invalid input, validation failure, wallet already on allowlist, or API key not enabled |
| 401         | Unauthorized — invalid or missing API key                                                            |
| 403         | Forbidden — partner did not onboard this entity (for update and add-allowlist endpoints)             |
| 500         | Internal server error                                                                                |


# Direct Issuance Program

A Direct Issuance Program allows a public company to issue new tokenized shares directly to eligible investors, with purchases executed using real-time market prices and settled in stablecoins.

***

## 1. Overview

The Direct Issuance Program (DIP) enables discounted token purchases of Superstate equity instruments at oracle-derived pricing. It is composed of three on-chain contracts and a set of off-chain APIs for user onboarding and allowlist management.

**What partners can do with this integration:**

* Onboard users (individuals or entities) via API, passing KYC data
* Get users allowlisted for specific equity instruments
* Enable users to purchase equity tokens at a market-configured discount via `buyTheDip`

***

## 2. Architecture

```
                           Partner Backend
                          ┌─────────────────┐
                          │  KYC + Wallet   │
                          │  Collection     │
                          └────────┬────────┘
                                   │
                   ┌───────────────┼───────────────┐
                   │ HTTP API      │               │ On-chain
                   ▼               │               ▼
          ┌────────────────┐       │      ┌──────────────────┐
          │ Superstate     │       │      │ Ethereum Mainnet │
          │ Onboard API    │       │      │                  │
          │                │       │      │  ┌────────────┐  │
          │ POST /onboard  │       │      │  │ Allowlist  │  │
          │ POST /add-     │       │      │  │ (V4.0)     │  │
          │   allowlist    │       │      │  └────────────┘  │
          │ PUT /update    │       │      │         ▲        │
          └────────────────┘       │      │         │ reads  │
                                   │      │  ┌──────┴─────┐  │
                                   │      │  │ EquityToken│  │
                                   │      │  │ (Dippable) │──┼── User calls
                                   │      │  └──────┬─────┘  │     buyTheDip()
                                   │      │         │        │
                                   │      │  ┌──────▼─────┐  │
                                   │      │  │ DIP        │  │
                                   │      │  │ Contract   │  │
                                   │      │  └────────────┘  │
                                   │      └──────────────────┘
                                   │
                          ┌────────▼─────────┐
                          │  Partner User    │
                          │  (EOA Wallet)    │
                          └──────────────────┘
```

**Contract interaction flow for a purchase:**

```
User EOA ──► EquityToken.buyTheDip(marketId, paymentAmount, minOutAmount, USDC)
                │
                ├─► DIP.buyTheDip(marketId, buyer, paymentAmount, minOutAmount, USDC)
                │       │── Fetch Pyth oracle price
                │       │── Apply discount
                │       │── Validate circuit breakers
                │       │── Calculate output tokens
                │       │── Validate slippage (minOutAmount)
                │       │── Update totalPaymentReceived
                │       │── Auto-close market if capacity exhausted
                │       └── Return (actualPaymentAmount, instrumentAmount, recipient)
                │
                ├─► USDC.safeTransferFrom(buyer, recipient, actualPaymentAmount)
                └─► _mint(buyer, instrumentAmount)
```

***

## 3. Prerequisites & Setup

#### 3.1 API Key & Request Signing

Contact Superstate to receive an API key and secret for the External Onboard API. Partners will be registered as an `ExternalOnboardPartner`.

**Authentication uses HMAC-SHA256 request signing.** To implement request signing, either:

* Use the npm package: `@superstateinc/api-key-request`
* Or implement manually using the reference implementation: <https://github.com/superstateinc/request-with-api-key>

#### 3.2 Contract Addresses

Contract addresses for the specific equity instrument will be provided by Superstate at integration time. You will need:

<table><thead><tr><th width="236.7578125">Contract</th><th>Description</th></tr></thead><tbody><tr><td><strong>EquityToken (Proxy)</strong></td><td>The token contract users interact with for <code>buyTheDip</code> and <code>isAllowed</code></td></tr><tr><td><strong>DIP Contract</strong></td><td>Pricing engine for <code>calculateOutput</code> (users do not call <code>buyTheDip</code> on this directly)</td></tr><tr><td><strong>USDC</strong></td><td><code>0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48</code> (Ethereum Mainnet)</td></tr></tbody></table>

#### 3.3 Supported KYC Providers

When submitting onboarding requests, specify which KYC provider was used:

```
LexisNexis | Moodys | Sumsub | Persona | Seon | Jumio
Truiloo | Onfido | ComplyAdvantage | HyperVerge | FullCircl | Prove
```

***

## 4. User Onboarding API

The External Onboard API allows partners to create user entities in Superstate's system and get them allowlisted in a single flow.

**Full API documentation:** [Onboarding API](/integration-partners/onboarding-api)

**Base URL:** Provided by Superstate

**Authentication:** HMAC-SHA256 signed requests (see Section 3.1)

The sections below summarize the key endpoints. Refer to the API documentation above for the authoritative reference.

#### 4.1 Available Endpoints

<table><thead><tr><th width="111.5703125">Method</th><th>Endpoint</th><th>Purpose</th></tr></thead><tbody><tr><td><code>POST</code></td><td><code>/v1/accounts/onboard/evm</code></td><td>Create user entity and initiate allowlisting</td></tr><tr><td><code>POST</code></td><td><code>/v1/accounts/onboard/evm/add-allowlist</code></td><td>Add additional wallet to an existing user</td></tr><tr><td><code>PUT</code></td><td><code>/v1/accounts/onboard/update</code></td><td>Update user KYC information</td></tr><tr><td><code>POST</code></td><td><code>/v1/accounts/onboard/evm/mock</code></td><td>Test endpoint (no database writes, returns mock data)</td></tr></tbody></table>

#### 4.2 Key Concepts

* **`forInstrument`**: Pass the equity instrument symbol to get users allowlisted for that specific token. Required for DIP equity tokens.
* **`userData`**: User PII (name, address, SSN/TIN, email). If omitted, Superstate queries the KYC provider directly using `kycProviderId`.
* **`kycProvider` + `kycProviderId`**: Reference to the user's completed KYC verification in your provider's system.
* **Response**: All creation endpoints return `{ entityId, walletAddress, encodedTransaction }`. Store `entityId` for future API calls.
* **Add-allowlist**: Identify the existing user by either `email` or `existingWalletAddress` (exactly one, mutually exclusive). Only the partner that originally onboarded the entity can add wallets.
* **Mock endpoint**: Same request format as the real endpoint. Returns `entityId: 0` and an unbroadcastable transaction. Useful for integration testing.

***

## 5. Allowlisting

#### 5.1 How Allowlisting Works

Before a user can hold or purchase equity tokens, their wallet address must be allowlisted. Allowlisting is handled by Superstate's infrastructure as part of the onboarding flow (Section 4). Partners do not need to interact with the Allowlist contract directly.

#### 5.2 Checking Allowlist Status

Call `isAllowed` on the **EquityToken** contract to check if a user is ready to purchase:

```typescript
// viem
const isAllowed = await publicClient.readContract({
  address: EQUITY_TOKEN_ADDRESS,
  abi: parseAbi(['function isAllowed(address addr) external view returns (bool)']),
  functionName: 'isAllowed',
  args: [userAddress],
});

// ethers.js v6
const isAllowed = await equityToken.isAllowed(userAddress);
```

#### 5.3 Allowlist Integration with Onboarding

When using the External Onboard API with `forInstrument` specified:

1. Superstate creates the entity and initiates allowlisting
2. The response includes an `encodedTransaction` for the on-chain allowlist update
3. Once the allowlist transaction is confirmed, the user can interact with the token

The allowlist transaction is submitted by Superstate's infrastructure. Partners should poll `equityToken.isAllowed(userAddress)` to confirm readiness before enabling purchases.

***

## 6. DIP Contract Specification

#### 6.1 Market Lifecycle

```
                    createMarket()
                         │
                         ▼
                   ┌─────────────┐
                   │ Initialized │
                   └──────┬──────┘
                          │ setMarketState(Active)
                          ▼
         ┌──────── ┌─────────┐ ────────┐
         │         │  Active │         │
         │         └────┬────┘         │
         │              │              │
    setMarketState   auto-close   setMarketState
      (Paused)     (target met)   (Cancelled)
         │              │              │
         ▼              ▼              ▼
    ┌────────┐    ┌──────────┐   ┌───────────┐
    │ Paused │    │  Closed  │   │ Cancelled │
    └───┬────┘    │(terminal)│   │ (terminal)│
        │         └──────────┘   └───────────┘
        │ setMarketState(Active)
        └───────► Active
```

**States:**

<table><thead><tr><th width="186.2734375">State</th><th width="113.21875">Value</th><th>Description</th></tr></thead><tbody><tr><td><code>Initialized</code></td><td>0</td><td>Created but not yet accepting purchases</td></tr><tr><td><code>Active</code></td><td>1</td><td>Live. One active market per instrument enforced.</td></tr><tr><td><code>Paused</code></td><td>2</td><td>Temporarily suspended. Can be reactivated.</td></tr><tr><td><code>Closed</code></td><td>3</td><td>Terminal. Target reached or manually closed.</td></tr><tr><td><code>Cancelled</code></td><td>4</td><td>Terminal. Admin-terminated.</td></tr></tbody></table>

**Rules:**

* Only one market per instrument can be `Active` at any time
* Cannot transition to the same state
* Cannot transition back to `Initialized`
* `Closed` and `Cancelled` are terminal (no further transitions)
* Market auto-closes when remaining capacity < `minPayment`

#### 6.2 Market Configuration

```solidity
struct Config {
    string description;         // Human-readable market description
    address recipient;          // Address that receives payment tokens
    uint16 discountRate;        // Discount in basis points (0-10000 = 0%-100%)
    uint256 minPayment;         // Minimum payment per purchase (PAYMENT_TOKEN_DECIMALS)
    uint256 totalPaymentTarget; // Total raise goal (PAYMENT_TOKEN_DECIMALS)
    uint64 minPriceClamp;       // Circuit breaker lower bound (8 decimals)
    uint64 maxPriceClamp;       // Circuit breaker upper bound (8 decimals)
}
```

#### 6.3 Market Data Structure

```solidity
struct Market {
    bytes32 marketId;                        // Unique identifier
    bytes32 oraclePriceFeedId;              // Pyth price feed ID
    IERC20 paymentToken;                    // e.g., USDC
    uint8 oracleLatencyToleranceInSeconds;  // Max oracle staleness
    State state;                            // Current lifecycle state
    uint16 discountRate;                    // Basis points
    uint64 minPriceClamp;                   // 8 decimals
    IERC20 instrument;                      // The equity token
    uint64 maxPriceClamp;                   // 8 decimals
    address recipient;                      // Payment destination
    uint256 totalPaymentReceived;           // Cumulative (PAYMENT_TOKEN_DECIMALS)
    uint256 minPayment;                     // Per-purchase minimum
    uint256 totalPaymentTarget;             // Raise goal
    string description;                     // Market description
}
```

#### 6.4 Constants

<table><thead><tr><th width="246.0078125">Constant</th><th width="116.5234375">Value</th><th>Description</th></tr></thead><tbody><tr><td><code>BASIS_POINTS</code></td><td>10000</td><td>100% in basis points</td></tr><tr><td><code>PRICE_CLAMP_DECIMALS</code></td><td>8</td><td>Decimal precision for price clamp values</td></tr><tr><td><code>PAYMENT_TOKEN_DECIMALS</code></td><td>6</td><td>Decimal precision for USDC (set at deployment)</td></tr></tbody></table>

***

## 7. Executing a Purchase (`buyTheDip`)

#### 7.1 User-Facing Function

The user calls `buyTheDip` on the **EquityToken** contract (not the DIP contract directly):

```solidity
function buyTheDip(
    bytes32 marketId,      // Market to purchase from
    uint256 paymentAmount, // Amount of USDC to spend (6 decimals for USDC)
    uint256 minOutAmount,  // Minimum tokens to receive (slippage protection)
    IERC20 paymentToken    // USDC contract address
) external
```

#### 7.2 Step-by-Step Integration

{% stepper %}
{% step %}

#### Check allowlist status

```typescript
const isAllowed = await equityToken.read.isAllowed([userAddress]);
if (!isAllowed) {
  // User must be onboarded and allowlisted first
  throw new Error("User not allowlisted");
}
```

{% endstep %}

{% step %}

#### Get the active market ID

```typescript
const marketId = await dipContract.read.currentMarketForInstrument([
  equityTokenAddress
]);
if (marketId === "0x" + "0".repeat(64)) {
  throw new Error("No active market");
}
```

{% endstep %}

{% step %}

#### Preview the purchase (optional but recommended)

```typescript
const [actualPayment, outputTokens] = await dipContract.read.calculateOutput([
  marketId,
  paymentAmount,  // e.g., 1000_000000n for 1000 USDC
  6               // USDC decimals
]);
```

{% endstep %}

{% step %}

#### Approve USDC spending

The user must approve the **EquityToken contract** (not the DIP contract) to spend their USDC:

```typescript
const approveTx = await usdcContract.write.approve([
  equityTokenAddress,
  paymentAmount  // or type(uint256).max for infinite approval
]);
await waitForTransactionReceipt(approveTx);
```

{% endstep %}

{% step %}

#### Execute the purchase

```typescript
const purchaseTx = await equityToken.write.buyTheDip([
  marketId,
  paymentAmount,   // USDC amount (6 decimals)
  minOutAmount,    // Minimum tokens (apply slippage tolerance)
  usdcAddress
]);
const receipt = await waitForTransactionReceipt(purchaseTx);
```

{% endstep %}
{% endstepper %}

#### 7.3 Slippage Protection

Calculate `minOutAmount` using the preview and a slippage tolerance:

```typescript
const SLIPPAGE_BPS = 50; // 0.5%

const [_, expectedOutput] = await dipContract.read.calculateOutput([
  marketId, paymentAmount, 6
]);

const minOutAmount = expectedOutput * (10000n - BigInt(SLIPPAGE_BPS)) / 10000n;
```

The DIP contract will revert with `InsufficientOutput(actual, minRequired)` if the calculated output falls below `minOutAmount`.

#### 7.4 Partial Fills

If the `paymentAmount` exceeds the market's remaining capacity, the DIP contract automatically reduces it:

```
remaining = totalPaymentTarget - totalPaymentReceived
actualPaymentAmount = min(paymentAmount, remaining)
```

The user only pays `actualPaymentAmount` and only that amount of USDC is transferred. The excess stays in the user's wallet.

#### 7.5 Auto-Close Behavior

After each purchase, if the remaining capacity drops below `minPayment`, the market automatically transitions to `Closed`:

```
if totalPaymentReceived + minPayment > totalPaymentTarget:
    state = Closed
```

***

## 8. Querying Market State

#### 8.1 Read Functions

```solidity
// Get the active market ID for an instrument
function currentMarketForInstrument(IERC20 instrument) external view returns (bytes32);

// Get full market data (auto-generated from public mapping)
function markets(bytes32 marketId) external view returns (Market memory);

// Preview purchase output
function calculateOutput(
    bytes32 marketId,
    uint256 paymentAmount,
    uint8 paymentDecimals
) external view returns (uint256 actualPaymentAmount, uint256 outputAmount);

// Contract version
function version() external view returns (string memory);  // "1.0.1"
```

#### 8.2 Useful Derived Values

```typescript
// Remaining capacity
const market = await dipContract.read.markets([marketId]);
const remaining = market.totalPaymentTarget - market.totalPaymentReceived;

// Is market active?
const isActive = market.state === 1; // State.Active

// Progress percentage
const progress = (market.totalPaymentReceived * 10000n) / market.totalPaymentTarget;
```

***

## 9. Events & Indexing

#### 9.1 DIP Contract Events

**Purchase** — Emitted on every successful purchase:

```solidity
event Purchase(
    bytes32 indexed marketId,
    address indexed buyer,
    uint256 instrumentAmount,    // Tokens minted
    uint256 paymentAmount,       // USDC paid
    uint256 discountedPrice,     // Price after discount
    uint16 discountRate,         // Discount in bps
    uint256 minOutAmount         // Slippage parameter
);
```

**MarketCreated** — Emitted when a new market is created:

```solidity
event MarketCreated(
    bytes32 marketId,
    IERC20 indexed instrument,
    IERC20 indexed paymentToken
);
```

**MarketStateUpdated** — Emitted on state transitions (including auto-close):

```solidity
event MarketStateUpdated(
    bytes32 indexed marketId,
    State indexed prev,
    State indexed curr
);
```

**MarketConfigUpdated** — Emitted when market parameters change:

```solidity
event MarketConfigUpdated(
    bytes32 indexed marketId,
    Config config
);
```

#### 9.2 Token Events

Standard ERC20 `Transfer` events are emitted on the EquityToken when tokens are minted:

```solidity
event Transfer(address indexed from, address indexed to, uint256 value);
// from = address(0) for mints
```

#### 9.3 Indexing Recommendations

To track DIP purchases, index the `Purchase` event on the DIP contract. The `buyer` field is indexed for efficient filtering by user.

To detect market closures (including auto-close), watch for `MarketStateUpdated` events where `curr = 3` (Closed).

***

## 10. Error Reference

#### 10.1 DIP Contract Errors

| Error                                                     | When                 | Description                                               |
| --------------------------------------------------------- | -------------------- | --------------------------------------------------------- |
| `NotCurrentMarket()`                                      | `buyTheDip`          | Caller is not the instrument token of the active market   |
| `NotPaymentToken()`                                       | `buyTheDip`          | Payment token doesn't match market config                 |
| `InsufficientPayment()`                                   | `buyTheDip`          | Payment amount (after normalization) < `minPayment`       |
| `PriceOutOfBounds()`                                      | `buyTheDip`          | Discounted price outside `[minPriceClamp, maxPriceClamp]` |
| `InsufficientOutput(uint256 actual, uint256 minRequired)` | `buyTheDip`          | Output tokens < `minOutAmount` (slippage)                 |
| `PriceFeedExceedsMaxLatency()`                            | `buyTheDip`          | Oracle price is stale                                     |
| `PriceFeedInvalidOutput()`                                | `buyTheDip`          | Oracle returned invalid data                              |
| `ZeroActualPayment()`                                     | `buyTheDip`          | Calculated payment is zero after normalization            |
| `InvalidMarketId()`                                       | Various              | Market ID does not exist                                  |
| `AlreadyMarketClosedOrCancelled()`                        | Config/State changes | Market is in terminal state                               |

#### 10.2 EquityToken (Dippable) Errors

| Error                 | When        | Description                         |
| --------------------- | ----------- | ----------------------------------- |
| `ZeroPaymentAmount()` | `buyTheDip` | `paymentAmount` is 0                |
| `ZeroMinOutAmount()`  | `buyTheDip` | `minOutAmount` is 0                 |
| `DipContractNotSet()` | `buyTheDip` | DIP contract address not configured |

#### 10.3 Common ERC20 Errors

| Error                        | When        | Description                                          |
| ---------------------------- | ----------- | ---------------------------------------------------- |
| `ERC20InsufficientAllowance` | `buyTheDip` | User hasn't approved enough USDC for the EquityToken |
| `ERC20InsufficientBalance`   | `buyTheDip` | User doesn't have enough USDC                        |

#### 10.4 Allowlist Errors

| Error                     | When                   | Description                                                               |
| ------------------------- | ---------------------- | ------------------------------------------------------------------------- |
| `InsufficientPermissions` | `buyTheDip` / transfer | User's wallet is not allowlisted. Onboard via External Onboard API first. |

***

## 11. Decimal & Pricing Math

#### 11.1 Decimal Conventions

| Token/Value   | Decimals        | Example                                |
| ------------- | --------------- | -------------------------------------- |
| USDC          | 6               | 1000 USDC = `1000000000` (1000 \* 1e6) |
| EquityToken   | 6               | 100 tokens = `100000000` (100 \* 1e6)  |
| Price clamps  | 8               | $1.00 = `100000000` (1e8)              |
| Oracle price  | Variable (Pyth) | Normalized internally                  |
| Discount rate | Basis points    | 500 = 5% discount                      |

#### 11.2 Pricing Formula

```
1. oraclePrice = Pyth.getPriceUnsafe(oraclePriceFeedId).price
2. discountedPrice = oraclePrice * (BASIS_POINTS - discountRate) / BASIS_POINTS
3. Validate: minPriceClamp <= discountedPrice(8 decimals) <= maxPriceClamp
4. instrumentAmount = actualPaymentAmount * 10^instrumentDecimals / discountedPrice
```

**Example:**

* Oracle price: $10.00 per token
* Discount rate: 500 bps (5%)
* Discounted price: $10.00 \* (10000 - 500) / 10000 = $9.50
* Payment: 1000 USDC
* Tokens received: 1000 / 9.50 = \~105.26 tokens

#### 11.3 Payment Normalization

All payment amounts are normalized to `PAYMENT_TOKEN_DECIMALS` (6) internally:

* If USDC (6 decimals): no conversion needed
* If DAI (18 decimals): truncation occurs when normalizing down to 6 decimals

The `actualPaymentAmount` returned to the caller is denormalized back to the payment token's native decimals.

***

## 12. End-to-End Examples

#### 12.1 Full Integration Flow (TypeScript / viem)

```typescript
import { createPublicClient, createWalletClient, http, parseAbi } from 'viem';
import { mainnet } from 'viem/chains';

// --- Configuration (provided by Superstate) ---
const EQUITY_TOKEN_ADDRESS = '0x...';
const DIP_CONTRACT_ADDRESS = '0x...';
const USDC_ADDRESS = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
const SUPERSTATE_API_BASE = 'https://api.superstate.co';

// --- ABIs (minimal for integration) ---
const equityTokenAbi = parseAbi([
  'function buyTheDip(bytes32 marketId, uint256 paymentAmount, uint256 minOutAmount, address paymentToken) external',
  'function isAllowed(address addr) external view returns (bool)',
  'function balanceOf(address account) external view returns (uint256)',
]);

const dipAbi = parseAbi([
  'function currentMarketForInstrument(address instrument) external view returns (bytes32)',
  'function calculateOutput(bytes32 marketId, uint256 paymentAmount, uint8 paymentDecimals) external view returns (uint256 actualPaymentAmount, uint256 outputAmount)',
  'function markets(bytes32 marketId) external view returns (bytes32, bytes32, address, uint8, uint8, uint16, uint64, address, uint64, address, uint256, uint256, uint256, string)',
]);

const erc20Abi = parseAbi([
  'function approve(address spender, uint256 amount) external returns (bool)',
  'function allowance(address owner, address spender) external view returns (uint256)',
  'function balanceOf(address account) external view returns (uint256)',
]);

// --- Step 1: Onboard user via API ---
async function onboardUser(userData: object, walletAddress: string, kycProviderId: string) {
  const body = JSON.stringify({
    version: 1,
    userData,
    chainId: { id: 1 },
    walletAddress,
    kycProvider: 'Sumsub',
    kycProviderId,
    forInstrument: 'EQUITY_SYMBOL',
  });

  // Build HMAC-signed request using @superstateinc/api-key-request
  // See: https://github.com/superstateinc/request-with-api-key
  const response = await signedFetch(`${SUPERSTATE_API_BASE}/v1/accounts/onboard/evm`, {
    method: 'POST',
    body,
    apiKey: API_KEY,
    apiSecret: API_SECRET,
  });
  return await response.json();  // { entityId, walletAddress, encodedTransaction }
}

// --- Step 2: Wait for allowlisting ---
async function waitForAllowlist(userAddress: string): Promise<void> {
  while (true) {
    const isAllowed = await publicClient.readContract({
      address: EQUITY_TOKEN_ADDRESS,
      abi: equityTokenAbi,
      functionName: 'isAllowed',
      args: [userAddress],
    });
    if (isAllowed) return;
    await new Promise(r => setTimeout(r, 5000));  // Poll every 5s
  }
}

// --- Step 3: Execute DIP purchase ---
async function executePurchase(userAddress: string, usdcAmount: bigint) {
  const SLIPPAGE_BPS = 50n; // 0.5%

  // Get active market
  const marketId = await publicClient.readContract({
    address: DIP_CONTRACT_ADDRESS,
    abi: dipAbi,
    functionName: 'currentMarketForInstrument',
    args: [EQUITY_TOKEN_ADDRESS],
  });

  // Preview output
  const [actualPayment, expectedOutput] = await publicClient.readContract({
    address: DIP_CONTRACT_ADDRESS,
    abi: dipAbi,
    functionName: 'calculateOutput',
    args: [marketId, usdcAmount, 6],
  });

  const minOutAmount = expectedOutput * (10000n - SLIPPAGE_BPS) / 10000n;

  // Check & approve USDC
  const currentAllowance = await publicClient.readContract({
    address: USDC_ADDRESS,
    abi: erc20Abi,
    functionName: 'allowance',
    args: [userAddress, EQUITY_TOKEN_ADDRESS],
  });

  if (currentAllowance < usdcAmount) {
    const approveTx = await walletClient.writeContract({
      address: USDC_ADDRESS,
      abi: erc20Abi,
      functionName: 'approve',
      args: [EQUITY_TOKEN_ADDRESS, usdcAmount],
    });
    await publicClient.waitForTransactionReceipt({ hash: approveTx });
  }

  // Execute purchase
  const purchaseTx = await walletClient.writeContract({
    address: EQUITY_TOKEN_ADDRESS,
    abi: equityTokenAbi,
    functionName: 'buyTheDip',
    args: [marketId, usdcAmount, minOutAmount, USDC_ADDRESS],
  });

  const receipt = await publicClient.waitForTransactionReceipt({ hash: purchaseTx });
  return receipt;
}
```

#### 12.2 Full Integration Flow (ethers.js v6)

```typescript
import { ethers } from 'ethers';

// --- Step 3 equivalent in ethers ---
async function executePurchaseEthers(
  signer: ethers.Signer,
  usdcAmount: bigint
) {
  const SLIPPAGE_BPS = 50n;

  const equityToken = new ethers.Contract(EQUITY_TOKEN_ADDRESS, equityTokenAbi, signer);
  const dipContract = new ethers.Contract(DIP_CONTRACT_ADDRESS, dipAbi, signer);
  const usdc = new ethers.Contract(USDC_ADDRESS, erc20Abi, signer);

  // Get active market
  const marketId = await dipContract.currentMarketForInstrument(EQUITY_TOKEN_ADDRESS);

  // Preview
  const [actualPayment, expectedOutput] = await dipContract.calculateOutput(
    marketId, usdcAmount, 6
  );
  const minOutAmount = expectedOutput * (10000n - SLIPPAGE_BPS) / 10000n;

  // Approve
  const allowance = await usdc.allowance(await signer.getAddress(), EQUITY_TOKEN_ADDRESS);
  if (allowance < usdcAmount) {
    const approveTx = await usdc.approve(EQUITY_TOKEN_ADDRESS, usdcAmount);
    await approveTx.wait();
  }

  // Purchase
  const tx = await equityToken.buyTheDip(marketId, usdcAmount, minOutAmount, USDC_ADDRESS);
  return await tx.wait();
}
```

{% hint style="info" %}
**Note on smart contract integration:** The `buyTheDip` function on EquityToken uses `msg.sender` as the buyer for both the USDC `transferFrom` and the token `mint`. This means users must call `buyTheDip` directly from their EOA wallet — router or proxy contracts are not supported. Partners should build their integration as a frontend that constructs and submits transactions on behalf of the user's wallet.
{% endhint %}

***

## Appendix A: Market Management (Reference)

These functions are **owner-only** (Superstate-managed) but documented here for completeness.

#### Create Market

```solidity
function createMarket(
    bytes32 marketId,
    IERC20 paymentToken,
    IERC20 instrument,
    bytes32 oraclePriceFeedId,
    uint8 oracleLatencyToleranceInSeconds,
    Config calldata config
) external onlyOwner
```

#### Update Market Config

```solidity
function setMarketConfig(bytes32 marketId, Config calldata newConfig) external onlyOwner
```

Cannot be called on `Closed` or `Cancelled` markets.

#### Transition Market State

```solidity
function setMarketState(bytes32 marketId, State nextState) external onlyOwner
```

Valid transitions:

* `Initialized → Active`
* `Active → Paused | Closed | Cancelled`
* `Paused → Active | Closed | Cancelled`


