# 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 on-chain 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.*

### Fund administrator created accounts

Some shareholders will be onboarded directly by the fund administrator of a fund they have subscribed to outside of the Superstate portal. In those cases, the fund administrator may have already created a Superstate account for you.&#x20;

If an account was created for you, you can access it by going to [Forgot Password](https://superstate.com/forgot_password) and entering the same primary email address you used to register with the administrator (for CUSHY, that's Northern Trust). You'll then be prompted to create a password and set up 2FA, after which you can sign in.

***

## **Applications**

Sign in to the Investor Portal and you'll be prompted to complete two types of applications:

1. **Investing Entity Application (required)**: This application collects information about you as an individual investor or your entity, to verify your eligibility to access either tokenized equities or 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 may apply to access tokenized funds like USTB or USCC. You may complete applications for each fund to verify your eligibility to invest. Depending on the fund, these applications are either completed directly in the Superstate portal, or from a third-party website of the fund issuer or admin.

***

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

Once you've submitted your entity applications a review process will begin. All entity applications are evaluated based on compliance checks, anti-money laundering (AML) screening, and accreditation status.

Fund applications are also reviewed carefully for eligibility. The status of fund applications submitted through Superstate can be found in the portal. For fund applications submitted outside of the Superstate portal, please reach out to the corresponding investment manager if you need more information or a status update.

Following approval, you will receive an email containing the Investment Agreement for final review and signature. 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 tokenized equities or tokenized funds.
* **Payout Destination**: Choose the bank account or wallet address where you can receive payouts when redeeming eligible tokenized 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://drive.google.com/file/d/1-gQPOU7n9Q4eKlgs-quEnylHpQcrjKI6/edit">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></p></td><td></td></tr><tr><td>Accredited investors</td><td><p></p><p>To invest in funds like USTB or USCC:</p><ul><li>Proof of Accredited Investor status, either <a href="https://drive.google.com/file/d/1-gQPOU7n9Q4eKlgs-quEnylHpQcrjKI6/edit">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 tokenized equities and fund.

1. [Overview](/investors/investor-portal/overview)
2. [Managing addresses](/investors/investor-portal/managing-addresses)
3. [Tokenizing shares](/investors/investor-portal/tokenizing-book-entry-shares)


# Overview

{% hint style="info" %}
This guide shows the portal from the perspective of an Institutional Investor. Individual Investors will see information that is tailored to them.
{% endhint %}

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;

#### **Two-factor authentication**

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.

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 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**: Subscribe to a fund. [View](/investors/tokenized-funds/subscribe).
* **Redeem**: Redeem book-entry or tokenized fund shares to USDC or USD. [View](/investors/tokenized-funds/redeem).
* **DeFi**: Links to all available DeFi protocols for an asset.
* **Tokenize**: Action to convert book-entry shares to tokens. [View](/investors/investor-portal/tokenizing-book-entry-shares).
* **Burn**: Convert tokenized equities to book-entry shares. [View](/investors/tokenized-equities#burning-tokens-to-book-entry).

More information about purchasing and redeeming funds can be found in the [USTB](/investors/tokenized-funds/available-funds/invesco-ustb), [USCC](/investors/tokenized-funds/available-funds/bitwise-uscc) and [CUSHY](/investors/tokenized-funds/available-funds/coinbase-cushy) 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 tokenized funds.

* **Statements**: If you are an accredited investor who has invested in tokenized 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. For other funds, your statements will be delivered by the fund admin. You will not receive statements for equities.
* **Fund Documents**: Disclosures and documents for all tokenized 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, change settings, and perform actions.
* Operators can perform actions.
* Viewers have read-only access.

#### **Inviting teammates**

Click the "Invite" button on the Team table to invite teammates to your organization. You can set the new teammates role.

#### **Investing Entity**

Configure the following settings for each Investing Entity:

* Transaction defaults: Select the default destination for fund purchases and redemptions (see [Configuring transaction defaults](/investors/investor-portal/managing-addresses#configuring-transaction-defaults)).
* Allowlist: Add and manage addresses that can hold tokenized assets (see [Adding an allowlist address](/investors/investor-portal/managing-addresses#adding-an-allowlist-address)).
* Payout Destinations: Manage addresses and bank accounts that can receive payouts from fund redemptions (see [Adding a payout destination](/investors/investor-portal/managing-addresses#adding-a-payout-destination)).
* Applications: Complete your entity or fund applications. Applications are hidden once they are approved.
* 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.


# Managing addresses

### Adding an allowlist address

An address must be on the allowlist before it can hold tokens for any fund or equity.&#x20;

To add an address:

1. Confirm which networks are supported for the instrument (see the [instrument's asset page](https://superstate.com/assets))
2. Go to Settings → Allowlist → Add
3. Select the network, enter the wallet address, and give it a nickname

Once added, the address can hold tokens for that instrument on the selected network.

### Adding a payout destination

A Payout Destination is a wallet address that can receive USDC payouts, or bank account that can receive USD payouts. Only one payout address per chain can be added for a specific entity. In special situations where you may want to have multiple payout destinations for the same chain, please reach out to the Superstate team to provision sub-accounts for your entity.

To set a payout destination:

1. Go to Settings -> Payout destinations -> Add
2. Select the network or bank account, and enter your address
3. At any time you can edit the address or bank account information for your payout destination

There is a 24 hour thaw period after adding or edit before this address can be used to receive a redemption payment.&#x20;

**Note**: Addresses can be added as both a payout destination and an allowlist address. However adding to one list does not automatically add it to the other.

### Configuring transaction defaults

Transaction defaults are the default destinations and delivery methods for purchases and redemption payouts:

* **Purchases**: Where an entity receives shares from fund subscriptions or tokenizations. This can be either book-entry, or an allowlist address.
* **Payouts:** Where an entity receives payouts from fund redemptions. This can be either a wallet address for USDC payouts, or a bank account for USD payouts.

These must be selected at the time of execution.

#### **Changing Settings**

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


# Tokenizing book-entry shares

Book-entry shares of funds or equities can be converted into tokenized shares and delivered to your allowlisted wallet. Each asset has a different set of available networks. Check the [instrument's page](https://superstate.com/assets) for the networks where it is supported.

Before tokenizing, add an eligible address for that asset to your allowlist (see [Adding an allowlist address](/investors/investor-portal/managing-addresses#adding-an-allowlist-address) above). After an address has been added, there is a 6-hour delay until it can be used to tokenize book-entry shares.

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

Book-entry shares are converted to tokens and delivered to selected address, usually within a few minutes. Track the status in Transaction History.


# Tokenized funds

Superstate gives investors access to tokenized funds from leading asset managers. Each fund is run by its own third-party investment manager. Superstate provides the tokenization, transfer-agent, and Investor Portal infrastructure that lets investors hold and transact in the fund on-chain or in book-entry. Shares for supported funds are available as tokens on various blockchains including Ethereum, Solana, and Plume, or held in book-entry by Superstate.

### How it works

1. **Get approved:** Submit your entity application, including Accredited Investor status. See [Getting started](/investors/getting-started).
2. **Apply to a fund:** Apply to each fund individually. Some funds allow direct application in the Investor Portal, while others require applying through the fund's administrator or issuer.
3. **Subscribe:** Send payment and receive shares to your default transaction destination. See [Subscription](/investors/tokenized-funds/subscribe)
4. **Hold shares:** As tokens in an allowlisted wallet, or in book-entry held by Superstate.
5. **Redeem**:  Burn tokens by sending them to a burn address, or initiate a book-entry redemption directly from the investor portal. See [Redemption](/investors/tokenized-funds/redeem).&#x20;

### Eligibility

Investors must be Qualified Purchasers and pass KYC/AML screening, and must be approved before applying to a fund. See [Getting started](/investors/getting-started).

### Available funds

See the [fund directory](/investors/tokenized-funds/available-funds) or <https://superstate.com/assets> for a full list of available funds.

### Transactions

* [Subscription](/investors/tokenized-funds/subscribe)
* [Redemption](/investors/tokenized-funds/redeem)
* [Tokenizing](/investors/investor-portal/tokenizing-book-entry-shares)
* [How NAV, income & yield work](/investors/tokenized-funds/nav-income-and-yield)

### Market days & 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**

Subscriptions 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**

Subscriptions 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).

**CUSHY**

Subscriptions and redemptions are managed by Northern Trust. Redemptions are paid out on Redemption Dealing Days (the end of the next quarter) and subscriptions are executed on the last market day of each month, so timing is not affected by holidays.

### Disclaimers

*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.*


# Subscribe

A subscription purchases fund shares with U.S. Dollars or USDC. Each fund has different available chains, timing, and pricing. See [Available Funds](/investors/tokenized-funds/available-funds)

### Before subscribing

Investors must be approved for the fund, [add an eligible allowlist address](/investors/investor-portal/managing-addresses), and [set their default purchase destination](/investors/investor-portal/managing-addresses#configuring-transaction-defaults).&#x20;

### How to subscribe <a href="#how-to-subscribe" id="how-to-subscribe"></a>

In the portal:

1. Go to the Portfolio page and click **Purchase** next to the fund.
2. In the **Pay with** dropdown, choose USD (wire) or USDC (on a supported network).
3. Send funds following the displayed instructions.
4. Shares are delivered according to your default purchase destination. Either as tokens to the allowlisted address or as book-entry shares. Confirmation emails are sent on initiation and completion, and status can be tracked in the Transactions table.

### When it's priced <a href="#when-it-s-priced" id="when-it-s-priced"></a>

A purchase is priced on the fund's schedule. See the fund's page for more information.

> **Example: Invesco USTB:** USTB is continuously priced, so a purchase is priced at the NAV/S when funds are received. USDC is attributed and delivered within minutes; a USD wire is received same-day if sent before 1pm ET (otherwise the next market day), then delivered shortly after.
>
> **Example: Bitwise USCC:** USCC is priced once per market day. Funds received before 5pm ET are priced at that market day's closing NAV/S and delivered T+1; funds received after 5pm ET price at the next market day's NAV/S (T+2).

### Subscribing through a fund administrator <a href="#subscribing-through-a-fund-administrator" id="subscribing-through-a-fund-administrator"></a>

Subscription instructions for some funds are provided through the fund administrator rather than in the Superstate portal. For those funds, complete the administrator's onboarding and submit the subscription request to them. Shares will continue to be delivered based on the default purchase destination for your entity.

### Methods & fees

Accepted methods (USD wire, USDC on Ethereum, USDC on Solana) vary by fund. Gas fees on USDC transfers and bank fees on USD wires are the investor's responsibility.

### Terms

Accepted methods, pricing cadence and cutoff, and minimums vary by fund. See the [Fund directory](/investors/tokenized-funds/available-funds) or the fund's page.


# Redeem

Redeeming burns fund shares, and returns proceeds as either U.S. Dollars or USDC. The specific steps depend on the fund's configuration.&#x20;

### Before redeeming

Investors must own shares in the fund, add a payout destination, and set a default payout destination.&#x20;

### How to redeem

1. Go to the Portfolio page and click **Redeem** next to the fund
2. In the **Redeem** dropdown select whether you want to view instructions for tokens or shares held in book-entry.
3. In the **Receive** input, select where to receive redemption payout. Options include U.S. Dollars at a bank account or USDC to a supported blockchain network address.
4. To redeem tokens, send them to the redemption address shown in the portal. Or for Ethereum tokens, call the offchainRedeem() function on the token contract. Either method will initiate a redemption.
5. To redeem shares held in book-entry, select Book-Entry shares and enter the amount to redeem.
6. Confirmation emails are sent on initiation and completion, and status can be tracked in the Transactions table on the portfolio page.

#### **Protocol redemptions**

For developers building smart contracts that interact with on Ethereum, refer to these [redemption instructions](/investors/smart-contracts#ustb-and-uscc-shared-functionality).

### When it settles <a href="#when-it-settles" id="when-it-settles"></a>

A redemption is priced and paid out follows the fund's schedule. See the fund's page for more information.

> **Example: Invesco USTB:** USTB features continuous pricing, so a redemption is priced at the NAV/S at the time the shares are received. Proceeds are delivered according to the investor's Payout Destination as either U.S. Dollars to a bank account, or USDC to an Ethereum or Solana address

### Fees

Gas fees to burn or transfer tokens, and bank fees on USD wires, are the investor's responsibility.

### Terms

Redemption frequency, cutoff times, and payout options vary by fund. See the [fund's asset page](https://superstate.com/assets).


# NAV, income, and yield

### NAV per share (NAV/S)

The Net Asset Value per share (NAV/S) is the price of one share. It is the value of the fund after accounting for all investor cash flows, income, and fund expenses.

### Accumulating NAV (no distributions)

Funds use an accumulating-NAV model rather than paying cash distributions. An investor is minted a fixed number of tokens, and the token balance does not change unless the investor subscribes, redeems, or transfers. Instead, the **NAV/S increases over time** as the fund earns income, so the same number of tokens becomes redeemable for more value.

### How income accrues

Income accrues on **market days** (days the relevant markets are open). It is reflected in the NAV/S rather than paid out. The fund's management fee accrues into the NAV/S as well, reducing NAV growth.

### When the price (NAV/S) updates <a href="#when-the-price-nav-s-updates" id="when-the-price-nav-s-updates"></a>

A fund's NAV/S is set on one of two schedules:

* **Continuous:** the NAV/S updates around the clock. A subscription or redemption is priced at the NAV/S at the moment funds or shares are received (e.g. Invesco USTB).
* **Daily or periodic:** the NAV/S is set once per period at a cutoff time. Orders received before the cutoff are priced at that period's NAV/S; orders after the cutoff are priced at the next one (e.g. Bitwise USCC, set daily at 5pm ET).

The fund's page states which schedule it uses and its cutoff time.

### On-chain price

The fund's NAV/S is published on-chain through a price oracle (Superstate's Continuous Oracle and Chainlink-compatible feeds), so each token has an on-chain reference price that DeFi protocols and integrators can read. See [Smart contracts for oracle addresses and details.](/investors/smart-contracts)

### Yield

A fund's 30-day yield is calculated from the change in NAV/S over the period, incorporating all realized and unrealized income for that fund. What that income is varies by strategy, so see the fund's page (for example, T-bill interest for USTB, or basis accrual, staking rewards, and mark-to-market effects for USCC).

### Per-fund specifics

More information on each fund including NAV/S, fees, historical performance is on each [fund's page](https://superstate.com/assets).


# Available Funds

| Fund                                                                        | Manager                   | Strategy                                                        |
| --------------------------------------------------------------------------- | ------------------------- | --------------------------------------------------------------- |
| [Invesco USTB](/investors/tokenized-funds/available-funds/invesco-ustb)     | Invesco                   | Short-duration U.S. Treasury Bills                              |
| [Bitwise USCC](/investors/tokenized-funds/available-funds/bitwise-uscc)     | Bitwise                   | Crypto basis + staking + Treasuries                             |
| [Coinbase CUSHY](/investors/tokenized-funds/available-funds/coinbase-cushy) | Coinbase Asset Management | Stablecoin private credit / direct lending (SOFR + 400-700bps+) |

See <https://superstate.com/assets> for a full list of available funds.


# Invesco USTB

Invesco Short Duration US Government Securities Fund

> New to Superstate? Start with [Getting started](/investors/getting-started) and the [Investor Portal](/investors/investor-portal).

The Invesco Short Duration US Government Securities Fund (USTB) invests in short-duration U.S. Treasury Bills. Shares of the Fund are issued as USTB tokens on Ethereum, Solana, and Plume, or held in book‑entry by Superstate. USTB is freely transferable between wallet addresses on the Allowlist. Purchases and redemptions are facilitated through USD or USDC, with liquidity each market day.

### Fund information

USTB invests in short-duration U.S. Treasury Bills. Return accrues as interest income, reflected in a continuously increasing NAV per share rather than distributions. Its NAV/S started at $10.000000 and updates continuously.&#x20;

To learn more please refer to [Invesco's fund overview](https://www.invesco.com/us/en/institutional/strategies/money-market-and-liquidity/ustb.html), the [USTB fund page](https://superstate.com/assets/ustb) and [How NAV, income & yield work](/investors/tokenized-funds/nav-income-and-yield) for shared fund income mechanics.

### Subscribing

Investors can view subscription instructions in the Superstate portal. Subscriptions can be sent with a USD wire or USDC (on Ethereum, Solana, or Plume). USTB is continuously priced, so a purchase is priced at the NAV/S when funds are received: shares are delivered immediately for orders paid in USDC (including non-business days), or same-day for USD wires received before 5pm ET. Shares are delivered as tokens to an allowlisted address or as book-entry. The minimum initial investment is $100,000 unless waived by Superstate.

See [Subscription](/investors/tokenized-funds/subscribe) for the step-by-step.

### Redeeming

Investors can view redemption instructions in the Superstate portal. Proceeds are paid as U.S. Dollars to a bank account, or USDC to an Ethereum, Solana, or Plume address. Proceeds are delivered immediately (including non-business days, subject to available liquidity) for payout requests in USDC, or same-day for USD if received before 1pm ET.

See [Redemption](/investors/tokenized-funds/redeem) for the step-by-step.

### Tokenizing book-entry shares

Investors can convert book-entry USTB shares into tokens on Ethereum, Solana, or Plume. Tokenization works the same across all Superstate funds; only the supported networks differ.&#x20;

See [Tokenizing book-entry shares](/investors/investor-portal#tokenizing-book-entry-shares) for the step-by-step.

### Market days & holidays

On U.S. market holidays, USDC purchases and redemptions may still be made, but no Treasury Bills are bought or sold. See the [holiday calendar](/investors/tokenized-funds#market-days-and-holidays).

### Addresses

Token contracts and oracles by chain: see [Smart contracts.](/investors/smart-contracts)

### Documents

Fund documents and statements are available in the [Investor Portal](https://superstate.com/assets/ustb).

### More info

* [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).

For **Disclosures and Risk Factors** related to the Invesco Short Duration US Government Securities Fund visit [superstate.com/assets/ustb#disclaimers](https://superstate.com/assets/ustb#disclaimers)


# Bitwise USCC

Bitwise Crypto Carry Fund

> New to Superstate? Start with [Getting started](/investors/getting-started) and the [Investor Portal](/investors/investor-portal).

The Bitwise Crypto Carry Fund (USCC) pursues crypto basis and carry strategies. Shares of the fund are issued as USCC tokens on Ethereum, Solana, and Plume, or held in book-entry by Superstate. USCC is freely transferable between wallet addresses on the Allowlist. Purchases and redemptions are facilitated through USD or USDC, with liquidity each market day.

### Fund information

USCC seeks yield from crypto basis strategies (the differential between spot and futures prices) across Bitcoin and Ether, including staking, alongside U.S. Treasury securities. Return accrues as interest income, reflected in a continuously increasing NAV per share rather than distributions. Its NAV/S started at $10.000000 and updates on a daily basis. Its 30-day yield reflects the change in NAV/S, including basis accrual, staking rewards, and mark-to-market effects.

To learn, please refer to [Bitwise's fund overview](https://bitwiseinvestments.com/crypto-funds/uscc), the [USCC fund page](https://superstate.com/assets/uscc) and [How NAV, income & yield work](/investors/tokenized-funds/nav-income-and-yield) for shared fund income mechanics.

### Subscribing

Investors can view subscription instructions in the Superstate portal. Subscriptions can be sent with a USD wire or USDC (on Ethereum, Solana, or Plume). USCC is priced once per market day at 5pm ET: shares are delivered T+1 for orders received before 5pm ET, or T+2 after. The minimum initial investment is $100,000 unless waived by Superstate. Shares are delivered as tokens to an allowlisted address or as book-entry.

See [Subscription](/investors/tokenized-funds/subscribe) for the step-by-step.

### Redeeming

Investors can view redemption instructions in the Superstate portal. Proceeds are paid as U.S. Dollars to a bank account, USDC to an Ethereum address, or USDC to a Solana address. Proceeds are delivered T+1 for requests received before 5pm ET, or T+2 after.

See [Redemption](/investors/tokenized-funds/redeem) for the step-by-step.

### Tokenizing book-entry shares

Investors can convert book-entry USCC shares into tokens on Ethereum, Solana, or Plume. Tokenization works the same across all Superstate funds; only the supported networks differ.&#x20;

See [Tokenizing book-entry shares](/investors/investor-portal/tokenizing-book-entry-shares) for the step-by-step.

### 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 closing 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.

### Market days & holidays

See [the holiday calendar](/investors/tokenized-funds#market-days-and-holidays).

### Addresses

Token contracts and oracles by chain: [see Smart contracts](/investors/smart-contracts).

### Documents

Fund documents and statements are available in the [Investor Portal](https://superstate.com/assets/uscc).

#### More info

* [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)

For **Disclosures and Risk Factors** related to the Bitwise Crypto Carry Fund visit [superstate.com/assets/uscc#disclaimers](https://superstate.com/assets/uscc#disclaimers)


# Coinbase CUSHY

Coinbase USD Stablecoin Yield Fund

> New to Superstate? Start with [Getting started](/investors/getting-started) and the [Investor Portal](/investors/investor-portal).

The Coinbase USD Stablecoin Yield Fund (CUSHY), managed by Coinbase Asset Management (CBAM), seeks yield from stablecoin private credit and direct lending. Subscriptions and redemptions are handled by the fund administrator, Northern Trust. Shares are available as tokens on Solana or in book-entry. CUSHY is freely transferable between wallet addresses on the Allowlist. Purchases and redemptions are handled by the fund administrator, Northern Trust, and facilitated through USD or USDC with liquidity offered at monthly end.

### Fund information

CUSHY seeks to generate yield from high-quality stablecoin private credit, direct lending, and tokenized credit opportunities. CUSHY targets yield similar to the Secured Overnight Financing Rate SOFR + 400-700bps+. While the strategy may expand over time, the credit exposure primarily comes from three core areas, including: Liquid Public Credit; Senior Secured, Direct Lending & Asset Backed Finance; and Opportunistic Credit & Structural Alpha. Its NAV/S started at $100.000000 and updates on a monthly basis.&#x20;

To learn more, please refer to [CBAM's fund overview](https://cbam.coinbase.com/cushy-details), the [CUSHY fund page](https://superstate.com/assets/cushy) and [How NAV, income & yield work](/investors/tokenized-funds/nav-income-and-yield) for shared fund income mechanics.

### Subscribing

CUSHY subscriptions are handled by the fund administrator. Investors must complete onboarding with Northern Trust and Coinbase Asset Management (in addition to Superstate portal onboarding), and then submit the subscription request. Subscriptions can be requested as either issuance as tokens to an allowlisted Solana address or as book-entry shares. Shares are delivered on the Subscription Dealing Day for orders received in the previous calendar month. The minimum initial investment is $100,000.

See [Subscription](/investors/tokenized-funds/subscribe) for the step-by-step.

### Redeeming

Investors can view redemption instructions in the Superstate portal. CUSHY redemptions are periodic. Proceeds are delivered on the Redemption Dealing Day for requests received in the previous calendar quarter.

See [Redemption](/investors/tokenized-funds/redeem) for the step-by-step.

### Tokenizing book-entry shares

Investors can convert book-entry CUSHY shares into tokens on Solana. Tokenization works the same across all Superstate funds; only the supported networks differ.&#x20;

See [Tokenizing book-entry shares](/investors/investor-portal/tokenizing-book-entry-shares) for the step-by-step.

### Market days & holidays

See [the holiday calendar](/investors/tokenized-funds#market-days-and-holidays).

### Addresses

Token contracts and oracles by chain: [see Smart contracts](/investors/smart-contracts).

### Documents

Fund documents and statements are available in the [Investor Portal](https://superstate.com/assets/uscc).

For **Disclosures and Risk Factors** related to the Coinbase USD Stablecoin Yield Fund visit <https://superstate.com/assets/cushy#disclaimers>


# 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)and [Investor Portal](/investors/investor-portal).

***

## Equity Allowlist&#x20;

In order to hold tokenized shares in your third party wallet, you must first add that address to the allowlist. 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). After, follow the [instructions here](/investors/investor-portal/managing-addresses#adding-an-allowlist-address).

***

## 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. Follow the instructions [here](/investors/investor-portal/tokenizing-book-entry-shares) to do so.&#x20;

***

## Using tokenized shares in DeFi

Tokenized equites are available in select DeFi protocols for trading, borrowing, lending, and more.&#x20;

1. Go to Portfolio and click the DeFi button
2. In the DeFi modal, you can view a list of links to supported protocols.
3. Once you are in the protocol, make sure that you are connected to the same that is added to your allowlist, and/or contains your tokenized equities.

***

## Burning 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.

**Important**: Unlike funds, burning equity tokens does not trigger a payout. To sell your tokens you must use a supported DEX (if available).

1. Go to Portfolio, expand the equity row, and click Burn
2. In the Burn to book-entry 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 on-chain, 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>The Bank of New York Mellon</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><tr><td>CUSHY</td><td>Coinbase Custody Trust Company, LLC and other qualified custodians</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" %}

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

***

## 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 on-chain.
* **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 on-chain 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).

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

A custom on-chain oracle to facilitate continuous pricing on-chain, 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 on-chain. 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 on-chain 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`, `Processed`, `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)
* `Processed` — processing has occurred but the transaction is not yet complete.
* `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**    | `Purchase`, `Redeem`, `Burn`, `ProtocolMint`, `ProtocolRedeem`, `MintRequest`, `UsdPurchase`, `UsdcPurchase`, `RedemptionRequest`                                     |
| **Equities** | `Issuance`, `Vest`, `Unlock`, `Release`, `Lockup`, `TaTransfer`, `BookEntryTransfer`, `BookEntryBuyback`, `DipPurchase`, `OnchainDeFiLpIssuance`, `OnchainDeFiLpBurn` |

> **NOTE:** `UsdPurchase` and `UsdcPurchase` represent temporary inbound-payment records, not completed subscriptions. Once a payment is allocated to a subscription, that payment row is removed. To detect completed subscriptions, filter for `transaction_type=Purchase` and `transaction_status=Completed`. USTB realtime subscriptions do not emit a `UsdPurchase` row.

**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 purchase and redeems in Q4 2025:**

```
GET /v2/transactions?transaction_status=Completed&transaction_type=Purchase,Redeem&from_timestamp=2025-10-01T00:00:00Z&until_timestamp=2025-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).

**Completed on-chain subscriptions**

For a standard USD subscription delivered on-chain:

* The completed subscription record has `operation_type: "Purchase"` and `status: "Completed"`.
* Use `source_details.transaction_hash` as the on-chain USTB mint transaction hash.
* `destination_details` and `to_address` are `null` for this transaction shape.
* The receiving Ethereum address is returned in `from_address` and `source_details.contract_address`.
* `share_amount` is the amount of USTB issued.
* `dollar_amount` is the subscription notional, calculated from the issued shares and subscription price. It is not a separately reconciled wire-settlement field.

```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": null,
    "source_details": {
      "chain_id": 1,
      "chain_name": "ethereum",
      "contract_address": "0x...",
      "transaction_hash": "0x..."
    },
    "destination_details": null
    ...
  }
]
```

#### 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 on-chain? 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 on-chain 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 on-chain applications where permitted.


# Onboarding API

The Onboarding API allows external partners to onboard users to Superstate by submitting KYC-verified user data along with wallet addresses to the be added to Superstate's on-chain 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 bincode + base64 encoded 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 |
| `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"
  },
  "walletAddress": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
  "kycProvider": "Sumsub",
  "kycProviderId": "01234567890123456789"
}
```

#### Response

**Success (200)**

```json
{
  "entityId": 598,
  "walletAddress": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
  "encodedTransaction": "<bincode + base64 encoded partially-signed Solana transaction>",
  "to": null,
}
```

| 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  | Encoded (bincode, then base64-string), partially-signed Solana transaction. The user must sign and broadcast this to complete the allowlist addition |
| `to`                 | null    | Will be `null` for SVM since the target is encoded in the `encodedTransaction` already                                                               |

#### Validation Rules

* Wallet address must be a valid Solana public key (base58)
* Wallet address must not already be on the allowlist for the environment (production, staging, etc)
* 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 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": "<ABI-encoded function data for setUserPermissionForInstrument>",
  "to": "0x812092D54BE1840F52816a0e0E1310635315Fd67"
}
```

| 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  | ABI-encoded function data that can be used directly in the transaction `data` field |
| `to`                 | string  | Address of the Superstate Allowlist proxy 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 bincode + base64 encoded Solana transaction with an invalid blockhash (all zeros) and unsigned signatures. This transaction cannot be broadcast.

**EVM mock**: Returns ABI-encoded `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": "<encoded mock Solana transaction>",
  "to": null
}
```

#### Example Response (EVM Mock)

```json
{
  "entityId": 0,
  "walletAddress": "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6",
  "encodedTransaction": "<ABI-encoded mock function data with expired deadline>",
  "to": "0x812092D54BE1840F52816a0e0E1310635315Fd67"
}
```

***

## 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`      |
| `entityId`              | integer | Conditional | An existing `entityId` of a previously API-onboarded entity.                                      |
| `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.

#### Example Request (using email)

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

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

<pre class="language-json"><code class="lang-json"><strong>{
</strong>  "version": 1,
  "existingWalletAddress": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
  "walletAddress": "BKgGvQR3TmEy8zNBJfwDEVGZmt7dRUXVZDiPKYCFaLWd"
}
</code></pre>

#### Example Request (using entity ID)

```json
{
  "version": 1,
  "entityId": 598,
  "walletAddress": "BKgGvQR3TmEy8zNBJfwDEVGZmt7dRUXVZDiPKYCFaLWd"
}
```

#### Response

**Success (200)**

```json
{
  "entityId": 598,
  "walletAddress": "BKgGvQR3TmEy8zNBJfwDEVGZmt7dRUXVZDiPKYCFaLWd",
  "encodedTransaction": "<bincode + base64 encoded partially-signed Solana transaction>",
  "to": null
}
```

#### 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`      |
| `entityId`              | integer | Conditional | An existing `entityId` of a previously API-onboarded entity.                                      |
| `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 (using email)

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

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

```json
{
  "version": 1,
  "existingWalletAddress": "0x1234567890abcdef1234567890abcdef12345678",
  "chainId": 1,
  "walletAddress": "0x0987654321abcdef1234567890abcdef87654321"
}
```

#### Example Request (using entity ID)

```json
{
  "version": 1,
  "entityId": 598,
  "chainId": 1,
  "walletAddress": "0x0987654321abcdef1234567890abcdef87654321"
}
```

#### Response

**Success (200)**

```json
{
  "entityId": 598,
  "walletAddress": "0x1234567890abcdef1234567890abcdef12345678",
  "encodedTransaction": "<ABI-encoded function data for setUserPermissionForInstrument>",
  "to": "0x812092D54BE1840F52816a0e0E1310635315Fd67"
}
```

#### 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 (US only) | Digits and hyphens only (`^[0-9-]+$`), 1-20 characters. Required for US only. |
| `emailAddress`  | string | Yes           | Valid email address                                                           |
| `streetAddress` | string | Yes           | 1-100 characters                                                              |
| `city`          | string | Yes           | 1-40 characters                                                               |
| `state`         | string | No            | 1-40 characters (state abbreviation for US, freeform for ex-US)               |
| `zipcode`       | string | No            | 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              | <p>Available values:<br><code>Individual</code>,<br><code>Corporation</code>,<br><code>LimitedPartnership</code>,<br><code>GeneralPartnership</code>,<br><code>SCorp</code>,<br><code>Trust</code>,<br><code>Llc</code>,<br><code>Llp</code>,<br><code>Other</code></p> |
| `ssnOrTin`                   | string | Yes (US only)    | Digits and hyphens only (`^[0-9-]+$`), 1-20 characters. Required for US only.                                                                                                                                                                                           |
| `businessRegistrationNumber` | string | Yes (ex-US only) | Digits and hyphens only (`^[0-9-]+$`), 1-20 characters. Required for ex-US only.                                                                                                                                                                                        |
| `emailAddress`               | string | Yes              | Valid email address                                                                                                                                                                                                                                                     |
| `streetAddress`              | string | Yes              | 1-100 characters                                                                                                                                                                                                                                                        |
| `city`                       | string | Yes              | 1-40 characters                                                                                                                                                                                                                                                         |
| `state`                      | string | No               | 1-40 characters (state abbreviation for US, freeform for ex-US)                                                                                                                                                                                                         |
| `zipcode`                    | string | No               | 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, we will automatically use `MainnetBeta` or `Devnet` based on the environment on which the API was sent.    &#x20;

#### 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`


