> For the complete documentation index, see [llms.txt](https://calnix.gitbook.io/eth-dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://calnix.gitbook.io/eth-dev/smart-contract-security/merkle-tree-shortened-proof-attack.md).

# Merkle Tree: shortened proof attack

The *second preimage attack* in Merkle trees can happen when an intermediate node in a merkle tree is presented as a leaf.

### Valid example

<figure><img src="/files/53VKtf9Wx6gKARpaJLih" alt=""><figcaption></figcaption></figure>

* we want to create a merkle proof for the leaf ℓ₂, in yellow text.
* we will need all the hashes in green.

The proof to the root is

```bash
h(a) = h(h(ℓ₁) + h(ℓ₂))
h(e) = h(h(a) + h(b))
h(g) = h(h(e) + h(f))
return root == h(g)
```

### Attack

What if the attacker provides an intermediate node as a leaf, along with the shortened proof?

Essentially, if a merkle proof is valid, then a shortened version of it is also valid if we pass the first value in the original proof as a leaf.

<figure><img src="/files/DmFMnlvi7x0f71aI5IzC" alt=""><figcaption></figcaption></figure>

* attacker provides a as the leaf, and the green hashes as the merkle proof
* the merkle can be correctly generated from this truncated offering, and therefore verification will pass

### Prevention

#### 1. The attack requires 64 byte leaves <a href="#viewer-50dao" id="viewer-50dao"></a>

For this attack to work, the attacker must pass in the preimage of the intermediate node, not its hash value. This means it must pass **a** as the leaf, not **hash(a)**. Since Solidity uses 32 byte hashes, **a = h(ℓ₁) + h(ℓ₂)** will be 64 bytes long.

* If the contract does not accept 64 byte leaves as input, then the attack will not work.
* That is, if the input to the leaf has a length other than 64 bytes, it is impossible to pass **h(ℓ₁) + h(ℓ₂)** as a false leaf value.

#### 2. Using a different hash for the leaf as a defense <a href="#viewer-9ol37" id="viewer-9ol37"></a>

If our application need to accept 64 byte leaves for some reason, then we can prevent the attack by using a different hash for the leaves than for the proof.

* That is, when the leaf is first hashed, we used a different hash than what we use for hashing to the root.&#x20;
* This will prevent the attacker from “reconstructing” an intermediate node as if it were a leaf. Using the diagram above, the attacker is using **h(a)** to create the false “leaf.” However, if leaves are passed through **h’(a)**, then the intermediate value cannot be reconstructed.

**OpenZeppelin uses a double hash as a "different hash"**

Instead of using a different hash function (such as via a [precompile](https://www.rareskills.io/post/solidity-precompiles)) which would cost more gas, Openzeppelin simply hashes the leaf twice. That is, **h’(x) = h(h(x))**.

We've used green underlines to show where the hash is taken twice to construct the leaf node from the underlying data.

<figure><img src="/files/sHYPKgfACCanO9Mdfs4e" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
The attack is easy to defend against — simply do not allow non-leaf values to be interpreted as leafs.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://calnix.gitbook.io/eth-dev/smart-contract-security/merkle-tree-shortened-proof-attack.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
