Recent events like the FTX meltdown have sparked interest and conversations about how the incident could have been prevented. In the case of FTX, the primary problem was that the platform did not hold sufficient assets to cover its user deposits and liabilities.
Proof of Reserves and Proof of Liabilities can use Merkle trees to prove certain facts while keeping data anonymous. To understand how these schemes work, it is useful to understand Merkle trees first.
A Merkle tree is designed to securely summarize a set of data. This means that, given the root value of the tree and some internal node values, it is possible to prove that a particular piece of data is included in the tree. One application of Merkle trees is to prove that a set of transactions are included in a particular block in the digital ledger.
The image above shows a Merkle tree that summarizes the various transactions that are included within a block. Each internal node within the tree contains the hash of its children. For example, the node labeled Hash 0 contains the hash of Transaction 0, and the node labeled Hash 0-1 contains the hash of the concatenated values of nodes Hash 0 and Hash 1.
Merkle trees are able to securely summarize data because of hash function collision resistance. With a secure, cryptographic hash function, it is infeasible to find two different inputs that produce the same hash output. Since Merkle trees are built of hash functions, it’s infeasible to find two Merkle trees of the same size with the same root value.
This property makes it possible to prove that a particular piece of data exists within a Merkle tree without the need to reveal any of the other values. For example, it is possible to prove that Transaction 0 is included in the tree above given the values of Hash 1, Hash 2-3, and the root hash via the following process:
- Calculate Hash 0 as the hash of Transaction 0
- Calculate Hash 0-1 by concatenating the values of Hash 0 and Hash 1 and hashing the result
- Calculate the root hash by concatenating the values of Hash 0-1 and Hash 2-3 and hashing the result
- Validate that the calculated root hash value matches the provided root hash value
By following this process, a user can verify that Transaction 0 was included in the block as long as the provided root hash is correct. Since root hashes are included in block headers and are protected by blockchain immutability, this is a safe assumption.
For Proof of Reserves and Proof of Liability, another important feature of hash functions is that they are one-way functions. This means that, given the value of Hash 1, it is impossible to calculate the value of Transaction 1. This is a useful feature when the set of data being proven is sensitive and shouldn’t be disclosed.
Many of the failed custodial cryptocurrency platforms maintained fractional reserves, meaning that they only retained enough assets to cover a fraction of user deposits. This is problematic because a bank run on the platform could quickly drain these reserves, leaving users unable to withdraw their deposits.
A Proof of Reserves (PoR) audit is performed by a third-party auditor and provides an anonymized cryptographic proof that a custodian holds adequate reserves to cover deposits and that an individual’s deposit is covered by those reserves. Proof of Reserves uses a Merkle tree like the one described above to prove the set of user balances deposited in the protocol.
This starts by snapshotting the set of user balances at a particular point in time and then anonymizing that list of balances. This anonymization can be accomplished by concatenating the balance with a unique identifier known to the exchange and the user. From this set of anonymized balances, the auditor builds a Merkle tree like the one above.
Once the tree has been generated, the auditor or custodial platform can publish the tree without the associated balances — i.e. publishing only the values labeled as Hash X in the tree above. With knowledge of their own balance and unique identifier, a user can easily determine that their deposit was correctly recorded in the Proof of Reserves audit. If many users individually validate that their balance is correct and attest to this, then the Merkle Tree is likely accurate and the platform has revealed all of the balances that it has received to the auditor.
If the auditor knows the complete deposited value and users have validated that this value is correct, the other half of a Proof of Reserves audit is the custodian proving that they have sufficient assets to cover these deposits. This can be accomplished by digitally signing messages using private keys associated with accounts that hold sufficient reserves. Since anyone can verify the value of an account on the blockchain, this is also a publicly verifiable proof.
This approach to a Proof of Reserves scheme relies on an auditor to tabulate and publish the total balance of user deposits. Alternatively, a Proof of Reserves audit could use a Merkle sum tree, in which each node contains both the hash of its children and the sum of their values. However, publishing such a tree either leaks information about users’ balances or provides imperfect information. The use of zero-knowledge proofs for Proof of Reserves audits is an area of research that could address these issues.
Proof of Reserves is a useful tool for proving that a custodian holds enough assets to cover its deposits; however, it isn’t enough. A custodian could easily take out a loan to accumulate sufficient assets to pass a PoR audit. However, the custodian may then lack enough assets to repay both the loan and the user deposits.
A Proof of Liabilities (PoL) is an audit of a custodial platform’s debts and liabilities. Essentially, this involves a third-party auditor creating a complete list of a custodial platform’s liabilities just like a Proof of Reserves audit tabulates assets and user deposits. If the total number of assets exceeds the total amount of user deposits and liabilities, then the company is solvent.
It is also common to verify that depositors have precedence over creditors in the event of a bankruptcy declaration. This would ensure that, if a custodian lacked the resources needed to cover both user deposits and loans, depositors would be paid back before creditors.
Proof of Solvency (PoS) is an all-in-one audit that combines Proof of Reserves and Proof of Solvency audits. Users of a custodial platform should look for a PoS audit performed by a third-party auditor. Proof of Reserves is not enough on its own because it lacks visibility into a custodian’s debts, and a third-party audit is essential to prove that all deposits and liabilities were included in the audit.
However, a PoS audit, like any security audit, is only a snapshot. A company that undergoes an audit one day could invest and lose assets the next. This is why some platforms are working to provide users with ongoing visibility into the state of their deposits.
Operating at a fractional reserve can be appealing for custodial platforms and is not necessarily a bad thing. Many traditional financial institutions hold only a fractional reserve, freeing up capital to use for investments that offer the potential for either rewards or losses. However, these institutions may also be bailed out by the government if something goes wrong.
Cryptocurrency custodians likely lack the same guarantees, so users should know whether or not their assets are secure and whether the platform holds full reserves. A Proof of Solvency audit can provide valuable information for users’ risk calculations.
Cryptosec is a leading provider of security solutions in the rapidly evolving world of blockchain, cryptocurrency, DeFi. Their specialist investigations arm, Crypto Investigators, offers expert services in blockchain forensics and legal investigations, leveraging deep industry knowledge and advanced investigative techniques to navigate the complexities of the digital age.