Skip to main content


Program data#

The protocol needs a place to store persistent data. Most of it is stored inside the State structure, that is passed to methods just like any other account.

Structure of state#

State is structured like this:

pub struct State {
pub admin: Pubkey,
pub halted: bool,
pub nonce: u8,
pub debt_shares: u64,
pub assets_list: Pubkey,
pub health_factor: Decimal,
pub max_delay: u32,
pub fee: Decimal,
pub swap_tax_ratio: Decimal,
pub swap_tax_reserve: Decimal,
pub liquidation_rate: Decimal,
pub penalty_to_liquidator: Decimal,
pub penalty_to_exchange: Decimal,
pub liquidation_buffer: u32,
pub debt_interest_rate: Decimal,
pub accumulated_debt_interest: Decimal,
pub last_debt_adjustment: i64,
pub staking: Staking,
pub exchange_authority: Pubkey,
pub bump: u8,
pub padding: [u8; 1620],

Respectively, these fields are :

  • admin - pubkey of the admin. Only admin can modify state using setters
  • halted - if set to true, access to methods is blocked
  • nonce - one of the seeds of the exchangeAuthority. Used to sign transactions
  • debt_shares - total amount of debt shares. Together with user debt shares, it allows calculating debt. More on that here
  • assets_list - address used to confirm the correctness of asset list passed to a method
  • health_factor - ratio of mint limit to max debt as a decimal
  • max_delay - maximum amount of slots a price can be outdated by
  • fee - percentage paid as a fee on swap
  • swap_tax_ratio - percentage of the fee going to the tax reserve
  • swap_tax_reserve - part of the total amount of charged tax. Can be withdrawn by admin
  • liquidation_rate - maximum part of user's debt repaid on liquidation
  • penalty_to_liquidator - penalty on liquidation going to the user that is liquidating
  • penalty_to_exchange - liquidation penalty going to liquidation fund
  • liquidation_buffer - number of slots between exceeding max debt and liquidation
  • debt_interest_rate - amount of interest rate charged on debt (yearly percentage, charged minutely)
  • accumulated_debt_interest - total amount charged as interest
  • last_debt_adjustment - timestamp of the last charge of interest
  • staking - structure with all data needed for staking. Details are here
  • exchange_authority - pubkey belonging to the exchange, used to sign transactions
  • bump - seed used to ensure the generated address doesn't collide with any other existing one
  • padding - used as padding to reserve space up to 2kB for future use

The state is initialized here. It can be changed later using admin methods signed by the admin.


All assets used in the platform are stored here. Data about prices comes from Pyth and is aggregated here. It also keeps data about decimal point's placing, addresses of tokens and total supply.

Structure of AssetsList#

Data related to assets is kept inside AssetsList:

struct AssetsList {
pub head_assets: u8,
pub head_collaterals: u8,
pub head_synthetics: u8,
pub assets: [Asset; 255],
pub collaterals: [Collateral; 255],
pub synthetics: [Synthetic; 255],

The first three are indexes of corresponding arrays, pointing to the last element and used as length. The next three keep data and are described below:


Synthetify uses Pyth oracles to get accurate prices of all assets and stores them in one place for ease of use. Data related to the prices is kept inside Asset structure:

pub struct Asset {
pub feed_address: Pubkey,
pub price: Decimal,
pub last_update: u64,
pub twap: Decimal,
pub twac: Decimal,
pub status: u8,
pub confidence: Decimal,
  • feed_address - address of Pyth oracle account
  • price - price multiplied by 10 to the power of PRICE OFFSET equaling 8
  • last_update - the slot of the last price update
  • twap - stands for Time-weighted average price
  • twac - stands for Time-weighted average confidence
  • status - status taken from oracle and saved as PriceStatus. Tokens can be swapped only if status is equal to 1
  • confidence - confidence interval representing asset's price uncertainty. The tighter the interval the lower possible price variation.

Every collateral and synthetic asset has to have a corresponding Asset but they can share it. For example, BTC and xBTC will have common Asset as they share the same price.

Collateral asset#

Data representing collateral is stored inside a Collateral structure:

pub struct Collateral {
pub asset_index: u8,
pub collateral_address: Pubkey,
pub reserve_address: Pubkey,
pub liquidation_fund: Pubkey,
pub reserve_balance: Decimal,
pub collateral_ratio: Decimal,
pub max_collateral: Decimal,
  • asset_index - index of the corresponding asset used to get its price
  • collateral_address - address of a token used as collateral
  • reserve_address - address of an account, where the exchange keeps deposited tokens
  • liquidation_fund - address of an account, where liquidation penalty is kept until it is withdrawn
  • reserve_balance - amount of tokens in the reserve account
  • collateral_ratio - ratio of collateral to debt user can have
  • max_collateral - maximum amount that can be used as collateral

Synthetic asset#

Synthetic assets created by Synthetify keep their data inside this structure:

pub struct Synthetic {
pub asset_index: u8,
pub asset_address: Pubkey,
pub supply: Decimal,
pub max_supply: Decimal,
pub borrowed_supply: Decimal,
pub swapline_supply: Decimal,
p ub settlement_slot: u64,
  • asset_index - index of the corresponding asset
  • asset_address - address of the synthetic token
  • supply - total amount of minted tokens
  • max_supply - limit of tokens that can be minted. It exists to increase safety of the platform (can be changed by the admin)
  • borrowed_supply - amount of tokens minted using vaults
  • swapline_supply - amount of tokens swapped using the swapline
  • settlement_slot - slot, when an asset will have a settlement (never by default)

AssetsList inside SDK#

AssetsList can be fetched by using:

await exchange.getAssetsList(assetsList)

Where the exchange is an instance of Exchange singleton. The argument of the assetsList is PublicKey, which can be found in the state. The whole structure is similar, but arrays are trimmed to the correct length.


In many places in the Synthetify code, there is a need for numbers with decimal point, ie. fractions of tokens, the interest rate percentage. To avoid floating point numbers Decimal was created.


pub struct Decimal {
pub val: u128,
pub scale: u8,

Here val is the value of the decimal. Scale can be interpreted as a position of the point in decimal notation. Val can be divided by 10 to the power of scale to get a regular number.

To make Decimal easier to use it also contains a few methods defined here, ie. simple math methods like add and div and their rounding up counterparts like mul_up. It also contains few factory methods like from_price and from_percent.

Inside SDK, Decimal is stored as a simple object of the following interface:

interface Decimal {
val: BN
scale: number