---
# System prepended metadata

title: 'Block #7280595: Storage root must match that calculated'

---

# Block #7280595: Storage root must match that calculated

- TLDR; Gossamer was not updating the re-calculated merkle-root of child trie when deleting an entry in the parent trie.

### Debugging the problem

After block `#7075269` we can see that they started to test the `crowdloan` pallet, they were testing a specific index `#2084`

- https://westend.subscan.io/extrinsic?address=&module=crowdloan&call=all&result=all&signedChecked=signed%20only&startDate=&endDate=&startBlock=7000000&timeType=block&version=9430&endBlock=7280595
![](https://hackmd.io/_uploads/H1ziwebyp.png)

The problematic block `#7280595` contains a call to `refund` which is a `crowdloan` pallet method.

Investigating a bit the `crowdloan` pallet we can see that they stores the contributions in the `default_child_storage` like a map between `index -> account -> value`, and the contributions are made by calling `crowdloan::contribute`, and in the image above there is no call to `crowdloan::contribute` method which made my life harder because if there is no contributes where is the problem?

Then I remembered to see `crowdloan::contribute` call once but in the `proxy` pallet, then I searched there and the guilt extrinsic was there

![](https://hackmd.io/_uploads/By9dtl-1p.png)

To make it easy to understand I will list the timelapse:

- They created a `crowdloan` at block `#7165072` (second line in the first image)
- They contributed to the created `crowdloan` through `proxy` pallet at block `#7165794` (second image)
- They refounded the created `crowdloan` at block `#7280595` (first  line in the first image)

Now that I have the pieces I jump straight into the `refund` method (https://github.com/paritytech/polkadot/blob/52209dcfe546ff39cc031b92d64e787e7e8264d4/runtime/common/src/crowdloan/mod.rs#L518). Basically, the `refund` method retrieves the contributions and clear them from the default child storage using `Self::contribution_kill(fund.fund_index, &who);` which calls `sp_io::default_child_storage::clear` which in turn calls the host function `ext_default_child_storage_clear_version_1`. 

And the first intuition was to check the hashes after cleaning a default child storage entry, I wrote some tests and here was the outputs before the fix:

```
With the entry: Parent Trie Hash 0x9ff7f05844b22de1489b86f374bca1d86a5336d4199ab16c56632796f5f08b90
With the entry: Child Trie Hash 0xc35c79edc448779a9d8022f9bf7fc4445989b2cfc124a530502324eab150cedf

After Clear: Parent Trie Hash 0x9ff7f05844b22de1489b86f374bca1d86a5336d4199ab16c56632796f5f08b90
After Clear: Child Trie Hash 0x03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314
```

Basically, cleaning an entry in the default child trie was not affecting the hash of the parent trie that holds the child trie, and after applying the fix we can see that the parent trie contains a different hash.

```
Empty parent trie 0x03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314
With Value: Parent Trie Hash 0x9ff7f05844b22de1489b86f374bca1d86a5336d4199ab16c56632796f5f08b90
Child Trie Hash 0xc35c79edc448779a9d8022f9bf7fc4445989b2cfc124a530502324eab150cedf

After Clear Parent Trie Hash 0x03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314
```

So after after cleaning a child trie that contains only one value the parent trie jump back to the same hash it had when empty