{"id":18929751,"url":"https://github.com/kevincharm/sparse-merkle-tree","last_synced_at":"2026-03-16T16:30:19.221Z","repository":{"id":185142498,"uuid":"672736099","full_name":"kevincharm/sparse-merkle-tree","owner":"kevincharm","description":"Optimised SMT implementation in Solidity \u0026 accompanying JS lib","archived":false,"fork":false,"pushed_at":"2023-08-25T13:18:21.000Z","size":134,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-13T19:41:31.449Z","etag":null,"topics":["cryptography","ethereum","evm","merkle-tree","solidity","sparse-merkle-tree"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kevincharm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-31T03:43:48.000Z","updated_at":"2023-08-14T15:37:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"2976113b-c87f-445e-a3e1-baf07a7e397f","html_url":"https://github.com/kevincharm/sparse-merkle-tree","commit_stats":{"total_commits":19,"total_committers":1,"mean_commits":19.0,"dds":0.0,"last_synced_commit":"e9bc6c6ad5ba485a9584184221cb447a7434cc1c"},"previous_names":["kevincharm/sparse-merkle-tree"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kevincharm%2Fsparse-merkle-tree","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kevincharm%2Fsparse-merkle-tree/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kevincharm%2Fsparse-merkle-tree/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kevincharm%2Fsparse-merkle-tree/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kevincharm","download_url":"https://codeload.github.com/kevincharm/sparse-merkle-tree/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239927825,"owners_count":19719835,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cryptography","ethereum","evm","merkle-tree","solidity","sparse-merkle-tree"],"created_at":"2024-11-08T11:34:52.876Z","updated_at":"2026-03-16T16:30:19.180Z","avatar_url":"https://github.com/kevincharm.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sparse Merkle Tree\n\nSparse Merkle Tree (SMT) implementation in Solidity with accompanying JavaScript library. This SMT implementation uses `bytes32(0)` as the empty node value so that paths representing empty subtrees in the Merkle proof may be omitted. This proof compression technique is described by Vitalik in [Optimizing sparse Merkle trees](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751).\n\n## Installation\n\n```sh\nyarn add @kevincharm/sparse-merkle-tree @noble/hashes\n```\n\n`@noble/hashes` is required as a peer dependency for the JS library.\n\n## Onchain usage\n\nBelow is an example contract that keeps track of only the current SMT root, and allows updating any leaf with a new value given the old leaf value and the Merkle proof.\n\n```solidity\nimport { SparseMerkleTree } from '@kevincharm/sparse-merkle-tree/contracts/SparseMerkleTree.sol';\n\n/// @notice Example SparseMerkleTree consumer\ncontract SMTConsumer {\n    /// @notice Depth of Merkle tree\n    uint16 immutable treeDepth;\n    /// @notice Current Merkle root\n    bytes32 public root;\n\n    /// @param treeDepth_ The tree depth determines the capacity of the tree,\n    ///     and must not change. `capacity = 2**treeDepth`\n    constructor(uint16 treeDepth_) {\n        treeDepth = treeDepth_;\n    }\n\n    function computeRoot(\n        bytes32 leaf,\n        uint256 index,\n        uint256 enables,\n        bytes32[] calldata path\n    ) public view returns (bytes32) {\n        return SparseMerkleTree.computeRoot(treeDepth, leaf, index, enables, path);\n    }\n\n    /// @notice Update a leaf in the tree, producing a new root.\n    /// @param newLeaf New value of leaf\n    /// @param oldLeaf Current leaf\n    /// @param index Index of leaf in list; determines hashing direction for\n    ///     proof path elements\n    /// @param enables Each bit determines whether a proof path element should\n    ///     be used (1) or a zero-value hash (0)\n    /// @param siblings Proof path; elements only need to be defined for non-zero\n    ///     siblings\n    function updateRoot(\n        bytes32 newLeaf,\n        bytes32 oldLeaf,\n        uint256 index,\n        uint256 enables,\n        bytes32[] calldata siblings\n    ) public returns (bytes32) {\n        if (root != computeRoot(oldLeaf, index, enables, siblings)) {\n            revert InvalidProof(oldLeaf, index, enables, siblings);\n        }\n        // Replace with new leaf and compute new root\n        return (root = computeRoot(newLeaf, index, enables, siblings));\n    }\n}\n```\n\n## Offchain usage\n\nBelow is an example JavaScript snippet that instantiates an SMT, then inserts a new leaf into the SMT, and finally submits the update to a contract using the generated Merkle proofs.\n\n```ts\nimport { SparseMerkleTreeKV } from '@kevincharm/sparse-merkle-tree'\nimport { ZeroHash, keccak256, concat, hashMessage, Wallet, Contract } from 'ethers'\n\n// Initialise client representation of an empty SMT\nconst smt = new SparseMerkleTreeKV()\n\n// Insert a new (K,V) entry\nconst key = keccak256(Wallet.createRandom().address)\nconst value = hashMessage('Fred Fredburger')\nconst { newLeaf, leaf: oldLeaf, index, enables, siblings } = smt.insert(key, value)\n// Connect to the contract that is consuming the SMT library\nconst smtConsumer = new Contract(/** ... */)\n// We update the SMT onchain by providing:\n//  - The new value of the leaf\n//  - The proof of membership of the old leaf value\nawait smtConsumer.updateRoot(newLeaf, oldLeaf, index, enables, siblings)\n// The onchain SMT should now be synced with the client-side\nassert((await smtConsumer.root()) === smt.root)\n```\n\n## Disclaimer\n\nThis software is unaudited and probably contains bugs. Use at your own risk.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkevincharm%2Fsparse-merkle-tree","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkevincharm%2Fsparse-merkle-tree","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkevincharm%2Fsparse-merkle-tree/lists"}