MerkleTree

Git Source

MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0 link. With the following changes:

  • Adapted for Solidity 0.8.x.
  • Amount of tree leaves stored externally.
  • Added thorough documentation.
  • H(0,0) = 0 optimization from ER forum post.

Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0 link. With the following changes:

  • Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).
  • H() = keccak256() is used as the hashing function instead of sha256().

State Variables

MAX_LEAVES

For root calculation we need at least one empty leaf, thus the minus one in the formula.

uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;

Functions

insertBase

Inserts node into merkle tree

Reverts if tree is full

function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal;

Parameters

NameTypeDescription
treeBaseTree
newCountuint256Amount of inserted leaves in the tree after the insertion (i.e. current + 1)
nodebytes32Element to insert into tree

rootBase

Calculates and returns current root of the merkle tree.

function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current);

Parameters

NameTypeDescription
treeBaseTree
countuint256Current amount of inserted leaves in the tree

Returns

NameTypeDescription
currentbytes32Calculated root of tree

initializeRoots

Initializes the historical roots for the tree by inserting an empty root.

function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot);

insert

Inserts a new leaf into the merkle tree.

Reverts if tree is full.

function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot);

Parameters

NameTypeDescription
treeHistoricalTree
nodebytes32Element to insert into tree

Returns

NameTypeDescription
newRootbytes32Merkle root after the leaf was inserted

root

Returns the historical root of the merkle tree.

Reverts if not enough leafs have been inserted.

function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot);

Parameters

NameTypeDescription
treeHistoricalTree
countuint256Amount of leafs in the tree at some point of time

Returns

NameTypeDescription
historicalRootbytes32Merkle root after count leafs were inserted

update

Updates the value for the leaf with the given index in the Dynamic Merkle Tree.

Will revert if incorrect proof of inclusion for old value is supplied.

function update(DynamicTree storage tree, uint256 index, bytes32 oldValue, bytes32[] memory branch, bytes32 newValue)
    internal
    returns (bytes32 newRoot);

Parameters

NameTypeDescription
treeDynamicTreeDynamic merkle tree
indexuint256Index of the leaf to update
oldValuebytes32Previous value of the leaf
branchbytes32[]Proof of inclusion of previous value into the tree
newValuebytes32New leaf value to assign

Returns

NameTypeDescription
newRootbytes32New value for the Merkle Root after the leaf is updated