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:
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 |