Example

Suppose there are 2 assets (ETH, USDT) and 3 users, and use USDT as the base denominated asset. Assume following user behaviors:

The user's balance sheet is as following:

ETH (price:2000 USDT) ETH USDT (price: 1 USDT) USDT Total Net Balance (USDT)
Equity Debt Equity Debt
Alice 1 2 13000 1000 10000
Bob 11 0 8000 0 30000
Carl 10 0 1000 1000 20000

The assets CEX holds equal to the summation of every user net asset balance (Equity-Debt). So the CEX needs to hold 20 ETH and 20000 USDT at least.

In proof of solvency, the following properties are guaranteed:

Design

The main idea of the design is to ensure the correctness of the process of building the world state tree through zksnark.

Suppose there are ASSET_NUM assets and ACCOUNT_NUM accounts. Define following structures:

type CexAssetInfo {
	total_equity    u64
  total_debt      u64
  usdt_price      u64
}

type AssetInfo {
	equity    u64
	debt      u64
}

type CreateUserOp {
  before_account_tree_root  Hash
	assets                    [ASSET_NUM]AssetInfo
  after_account_tree_root   Hash
  account_index             u32
  account_proof             [ACCOUNT_TREE_DEPTH]Hash
}

type AccountTreeLeafNode {
  equity_usdt          u64
  debt_usdt            u64
	assets_commitment    Hash
}

type CexAssetInfoList  [ASSET_NUM]CexAssetInfo
type AssetInfoList     [ASSET_NUM]AssetInfo
type CreateUserOpList  [BATCH_NUM]CreateUserOp

CEX can construct CexAssetInfoList and AssetInfoList for each account based on user balance sheet snapshot defined above. And CexAssetInfoList is published, AssetInfoList keeps private to each user.

In this design, CEX use index to represent user and asset type, such as:

0 1 n
alice bob dummy account
0 1 n
ETH USDT dummy asset