儲備金證明

隨時證明你的資金安全無虞。

快照日期

BTC icon

BTC

儲備比率*

100.3%

ETH icon

ETH

儲備比率*

101.3%

SOL icon

SOL

儲備比率*

101.1%

USDC icon

USDC

儲備比率*

105%+

USDT icon

USDT

儲備比率*

105%+

XRP icon

XRP

儲備比率*

100.6%

ADA icon

ADA

儲備比率*

102.2%

落實問責制度並執行定期審核

Kraken 不僅協助你交易前沿數碼資產,更致力於發揮這些資產所屬開源區塊鏈技術的透明特性。

我們定期開展的儲備金證明審核,幫助客戶在帳戶中點擊幾下,就能輕鬆驗證持有的相關餘額是否獲真實資產支持。

儲備金證明是由值得信賴的會計師定期執行的高級加密會計流程。你可利用這一流程,驗證 Kraken 是否符合嚴格的問責標準,以及透明度是否超越傳統金融機構。

常見問題

儲備金證明是甚麼?

儲備金證明 (PoR) 審核係由獨立第三方會計師執行的程序。其旨在驗證託管人確實持有其所聲稱代表客戶保管的資產。會計師會對所有持有的餘額進行匿名截圖,並將這些餘額彙總至 Merkle 樹中。這是一種兼顧私隱的數據結構,可將所有客戶餘額納入其中。

Merkle Root Hash

之後,會計師會生成 Merkle 根:這種加密指紋是能專門辨識快照建立時這些餘額的組合狀態。

然後,會計師會收集由 Kraken 生成的數碼簽名,以用於證明對餘額可供公開驗證的鏈上地址的所有權。最後,會計師會比較並驗證這些鏈上餘額是否大於或等於 Merkle 樹中所體現的客戶餘額,進而確認客戶資產確實處於 Kraken 的控制之下。

任何客戶皆可透過比較特定數據與 Merkle 根,獨立驗證自身餘額是否已納入儲備金證明流程中。無論對其餘數據進行多微小的修改,都可影響根,並使篡改行為無所遁形。

請參閱此處,查閱我們的儲備金證明報告。

儲備金證明涵蓋哪些內容?

現貨餘額

審核範圍將涵蓋你在快照拍攝當下所持有的所有符合條件的資產餘額。最新一輪審核對象的資產項目如下:Bitcoin (BTC)、Ether (ETH)、Solana (SOL)、USD Coin (USDC)、Tether (USDT) 和 Ripple (XRP)。

質押餘額

若你於快照拍攝當下有參與鏈上質押的資產餘額,該筆質押餘額的價值將與你的現貨餘額合併計入總餘額。

孖展交易

若你於快照拍攝當下持有孖展倉位,你的總餘額將依據倉位的正數價值進行調整。

示例 1

若你透過孖展以 30,000 美元的價格買入 1 BTC/USD,且該倉位尚未平倉,則你的儲備金證明餘額將顯示一筆 +1 BTC 的 BTC 餘額正向調整。美元餘額不會產生任何負向調整。你於 Kraken Custody 託管服務下持有的 BTC 資產餘額,將涵蓋你當時的 BTC 餘額,且孖展倉位將依據 +1 BTC 的正向調整數值進行調整。你的美元資產餘額將保持不變。

示例 2

若你透過孖展以 15 ETH 的價格賣出 1 BTC/ETH,且該倉位尚未平倉,則你的儲備金證明餘額將顯示一筆 +15 ETH 的 ETH 餘額正向調整。BTC 餘額不會產生任何負向調整。你於 Kraken Custody 託管服務下持有的 ETH 資產餘額,將涵蓋你當時的 ETH 餘額,且孖展倉位將依據 + 15 ETH 的正向調整數值進行調整。你於 Kraken Custody 託管服務下持有的 BTC 資產餘額將保持不變。

註:上述期貨計算方式自 2023 年 5 月的儲備金證明審核起正式生效。

期貨餘額

若你於審核期間的期貨錢包內有餘額,我們將為你單獨生成一份針對期貨抵押品餘額的儲備金證明紀錄。針對單一抵押品期貨交易,餘額將依據未實現損益進行調整。相關資產涵蓋範圍與現貨及孖展交易的適用資產一致,並納入同一棵 Merkle 樹(擁有其專屬的 Merkle Leaf ID)之中。 

示例 1

若你的期貨錢包中有 1 BTC,且你透過單一抵押品 BTC 永續合約開立倉位,當前未實現損益為 -0.1 BTC,則你於 Kraken Custody 託管服務下持有的 BTC 餘額將為 0.9 BTC(你的 1 BTC 將依據 -0.1 BTC 的未實現損益進行調整)。

示例 2

若你的期貨錢包中有 1 BTC,且你透過多抵押品 BTC 永續合約開立倉位,當前未實現損益為 -100.0 美元,則你於 Kraken Custody 託管服務下持有的 BTC 餘額將為 1 BTC(由於該損益以美元計價,且美元不納入本次審核範圍,因此無須依據未實現損益調整你的 1 BTC)。

註:上述期貨計算方式自 2023 年 5 月的儲備金證明審核起正式生效。 

如何確認我的帳戶是否納入儲備金證明審核範圍?

快速驗證指引

請依循以下步驟,透過密碼學驗證方式,確認你的 Kraken 帳戶餘額是否已納入最新的儲備金證明審核範圍。

註:本次驗證僅體現審核當下你帳戶內符合範圍的資產餘額。既不反映審核後的任何交易紀錄,亦不體現未納入範圍的資產餘額。

1.請登入你的 Kraken 帳戶,進入 Kraken Pro 操作介面 (pro.kraken.com),並導航至「儲備金證明」專頁(帳戶圖示 > 儲備金證明)。 

Kraken Proof of Reserves review list

2.選擇儲備金證明選項卡。頁面將顯示我們近期已驗證的儲備金率,以及與你帳戶相關的特定資訊。你的帳戶會列出近期已驗證帳戶餘額的儲備金證明報告,包含報告日期、審核機構以及評估範圍。 

Kraken Proof of Reserves review list

3.選擇日期後,點按自行驗證按鈕。你可於本頁面檢視審核當下所持資產餘額的確認資訊,以及驗證個人資訊的完整操作指引。

Kraken audit details

經第三方會計師驗證

  • 使用你的 Merkle Leaf ID —— 複製前 16 個字元,並貼至第三方會計師的審核工具中,即可檢索你的資產餘額,並於 Merkle 樹路徑中查看你的識別碼。第三方會計師的審核工具將於獨立視窗中開啟。 

註:此功能適用於 2023 年起的各次審核作業。若為更早的審核,請前往我們合作夥伴的網站查詢對應的審核工具。

Kraken audit details

完成 Kraken 驗證

  • 驗證你的紀錄 ID —— 依循步驟重新生成專屬紀錄 ID,此代碼將唯一識別你的帳戶詳情以及審核 ID(每個報告日期對應一個 ID)
  • 驗證你的 Merkle Leaf ID —— 依循步驟重新生成 Merkle Leaf ID,此代碼將唯一識別你的帳戶,以及審核快照拍攝當下所持有的資產餘額 
  • 於 Merkle 樹中確認你的 Merkle Leaf ID —— 確認你的 ID 隸屬於該 Merkle 樹,並驗證通往 Merkle 樹根的路徑;此路徑經由我們的第三方會計師驗證,並由所有客戶共享

註:此功能適用於 2023 年起的各次審核作業。若為更早的審核,請前往我們合作夥伴的網站查詢對應的審核工具。

Kraken audit details
Kraken audit details
Kraken audit details

進階驗證

技術熟練的使用者可能不希望依賴 Kraken 或第三方會計師提供的視覺化工具,而是透過程式設計的方式自行重建特定的 Merkle 樹葉節點雜湊值,並在 Merkle 樹中查詢餘額。 

你可透過程式碼執行下列驗證步驟:

  1. 依循以下流程驗證個人帳戶的 Merkle Tree Leaf ID 生成過程。  

  2. 接著驗證該 Leaf ID 對應的 Merkle 樹路徑,並重建從你的倉位到根節點的完整路徑。我們將提供完全透明的資訊,同時給出對應的兄弟葉節點 ID。 

下文概述了根據你的帳戶代碼、Kraken IIBAN、審核 ID 以及資產餘額,透過虛擬程式碼重建紀錄 ID 與 Merkle 葉節點的必要步驟。請注意:驗證結果對於餘額的字串格式,以及「儲備金證明」頁面所顯示的已審核資產排序方式極為敏感。

  • 紀錄 ID = SHA256(concatenate(Account Code, Kraken IIBAN, Review ID))
  • 餘額 = ""
  • 對於每種資產:
    • 餘額 = concatenate(Asset, ":", AssetBalances[asset])
  • Merkle 雜湊值 = concatenate(Record ID, “,”, Balances)
  • Merkle 葉節點 = substring(SHA256(Merkle Hash), 0, 16)

在確認你的 Merkle 葉節點後,即可透過採用十六進位值的 SHA256 演算法驗證並重建 Merkle 樹路徑。

下方程式碼片段亦提供具體範例供參考。經計算得出的 Merkle 葉節點值,亦會顯示於審核詳情頁面,供你確認是否已正確完成重建。

python

Python

import hashlib

# Merkle Leaf ID calculation
account_code = "8dc20f34da8cea8dd0f46b001694f5123ecd30d786c5eb92ad1a013703a4f8d1"
iiban = "AB12C34DEFG5KSQI"
review_id = "PR30SEP24"
record_id = hashlib.sha256((account_code + iiban + review_id).encode('utf-8')).hexdigest()

balances = "BTC:0.00093799,ETH:0.0422125592,SOL:0.0,USDC:0.0,USDT:6.72754,XRP:0.0"

print("Record ID: {}".format(record_id))
print("Merkle Hash: {}".format((record_id + "," + balances)))
hash_result = hashlib.sha256((record_id + "," + balances).encode('utf-8')).hexdigest()
print("SHA Result: {}".format(hash_result))
print("Merkle Leaf: {}".format(hash_result[0:16]))

#Merkle Tree Path function 
def mix(x, y):
    a = bytes.fromhex(x)
    b = bytes.fromhex(y)

    d = hashlib.sha256()
    d.update(a)
    d.update(b)
    return d.hexdigest()
rust

Rust

use sha2::{Digest, Sha256};

//Merkle Leaf ID calculation
const ACCOUNT_CODE: &str = "8dc20f34da8cea8dd0f46b001694f5123ecd30d786c5eb92ad1a013703a4f8d1";
const IIBAN: &str = "AB12C34DEFG5KSQI";
const REVIEW_ID: &str = "PR30SEP24";
const BALANCES: &str = "BTC:0.00093799,ETH:0.0422125592,SOL:0.0,USDC:0.0,USDT:6.72754,XRP:0.0";

fn main() {
    let mut record_hasher: Sha256 = Default::default();

    record_hasher.update(ACCOUNT_CODE);
    record_hasher.update(IIBAN);
    record_hasher.update(REVIEW_ID);

    let record_id = format!("{:x}", record_hasher.finalize());
    let merkle_hash = format!("{},{}", record_id, BALANCES);

    let mut merkle_hasher: Sha256 = Default::default();
    merkle_hasher.update(&merkle_hash);
    let merkle_result = format!("{:x}", merkle_hasher.finalize());

    println!("Record ID: {}", record_id);
    println!("Merkle Hash: {}", merkle_hash);
    println!("SHA Result: {}", merkle_result);
    println!("Merkle Leaf: {}", &merkle_result[..16]);
}

//Merkle Tree Path function
fn mix(x: &str, y: &str) -> Result<String, hex::FromHexError> {
    let mut leaves_hasher: Sha256 = Default::default();
    let a = hex::decode(x)?;
    let b = hex::decode(y)?;
    leaves_hasher.update(&a);
    leaves_hasher.update(&b);
    Ok(hex::encode(leaves_hasher.finalize()))
}

fn main() {
    println!("{}", mix("f42372aeb1be7296", "dfcced6ec3235f5e").unwrap());
    assert_eq!(
        mix("f42372aeb1be7296", "dfcced6ec3235f5e").unwrap(),
        "ad86a5ee2f21347403ce07e365530604690454fa76787e76be9d2f6efdceeabf"
    );
}
go

Go

package main

import (
	"crypto/sha256"
	"fmt"
)

//Merkle Leaf ID Calculation
func main() {

	accountCode := "8dc20f34da8cea8dd0f46b001694f5123ecd30d786c5eb92ad1a013703a4f8d1"
	iiban := "AB12C34DEFG5KSQI"
	reviewId := "PR30SEP24"

	secret := accountCode + iiban + reviewId

	data := []byte(secret)
	hash := sha256.Sum256(data)
	recordId := string(hash[:])
	fmt.Printf("Record ID: %x\n", recordId)

	balances := "BTC:0.00093799,ETH:0.0422125592,SOL:0.0,USDC:0.0,USDT:6.72754,XRP:0.0"

	merkleHash := fmt.Sprintf("%x%s%s", recordId, ",", balances)
	fmt.Printf("Merkle Hash: %s\n", merkleHash)

	hashResult := sha256.Sum256([]byte(merkleHash))
	hashResultStr := string(hashResult[:])
	fmt.Printf("SHA Result: %x\n", hashResultStr)
	fmt.Printf("Merkle Leaf: %x\n", hashResultStr[0:8])

}

//Merkle Tree path hashing
func mix(x, y string) (string, error) {
        // Convert the hex strings to bytes
        a, err := hex.DecodeString(x)
        if err != nil {
                return "", err
        }

        b, err := hex.DecodeString(y)
        if err != nil {
                return "", err
        }

        h := sha256.New()

        h.Write(a)
        h.Write(b)

        // Get the final hash value as a byte slice
        hashed := h.Sum(nil)

        // Convert the hash to a hex string and return it
        return hex.EncodeToString(hashed), nil
}

func main() {
        result, _ := mix("f42372aeb1be7296", "dfcced6ec3235f5e")
        fmt.Println(result)
}
bash

Bash

#!/bin/bash

#Merkle Leaf ID calculation
ACCOUNT_CODE="8dc20f34da8cea8dd0f46b001694f5123ecd30d786c5eb92ad1a013703a4f8d1"
IIBAN="AB12C34DEFG5KSQI"
REVIEW_ID="PR30SEP24"
RECORD_ID=$(echo -n "${ACCOUNT_CODE}${IIBAN}${REVIEW_ID}" | sha256sum | head -c 64)
BALANCES="BTC:0.00093799,ETH:0.0422125592,SOL:0.0,USDC:0.0,USDT:6.72754,XRP:0.0"
MERKLE_HASH="${RECORD_ID},${BALANCES}"
HASH_RESULT=$(echo -n ${MERKLE_HASH} | sha256sum | head -c 64)

echo "Record ID: ${RECORD_ID}"
echo "Merkle Hash: ${MERKLE_HASH}"
echo "SHA Result: ${HASH_RESULT}"
echo "Merkle Leaf: $(echo -n ${HASH_RESULT} | head -c 16)"

#Merkle Tree Path function
hex_string1="f42372aeb1be7296"
hex_string2="dfcced6ec3235f5e"

# convert hex strings to binary, concatenate them and then hash
hash_result=$(echo -n "$(echo -n $hex_string1 | xxd -r -p)$(echo -n $hex_string2 | xxd -r -p)" | sha256sum | awk '{ print $1 }')

echo $hash_result

現有不足與未來優化方向

為提升資訊透明度,我們願意公開當前在儲備金證明流程中發現的若干不足之處。

  • 儲備金證明僅能於審核當下驗證鏈上資金處於受控狀態,卻無法從理論上排除私鑰已遭攻擊者複製的可能性。
  • 此程序無法識別任何隱匿債務,亦無法證明相關資金並非為通過審核而臨時借入。同理,自最近一次審核作業完成後,金鑰亦有可能遺失,或資金已遭盜用。
  • 會計師必須具備充足專業能力並保持獨立性,才能將受審單位進行欺詐或相關各方串謀舞弊的風險降至最低。
  • 為盡量彌補上述缺失,我們已委請一家聲譽卓著的獨立第三方機構負責執行儲備金證明流程,並定期辦理審核作業。同時,我們亦於客戶平台上直接公開審核數據,以確保資訊透明可查。 
建立帳戶

若與 Kraken 的儲備金證明報告比較,上面標註星號 (*) 之儲備金證明數據可能會因產品變更及我們託管基礎設施的持續優化而出現重大變動。此類變動或將影響此類錢包中部分持倉資產的分類。依循現行慣例,所有報告中均載有儲備金證明驗證方法的詳細說明。