packages/contracts-core/test/suite/libs/merkle/MerkleTree.t.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import {AGENT_TREE_HEIGHT, ORIGIN_TREE_HEIGHT} from "../../../../contracts/libs/merkle/MerkleTree.sol";
import {MerkleMathHarness} from "../../../harnesses/libs/merkle/MerkleMathHarness.t.sol";
import {MerkleTreeHarness} from "../../../harnesses/libs/merkle/MerkleTreeHarness.t.sol";
import {Random} from "../../../utils/libs/Random.t.sol";
import {SynapseLibraryTest} from "../../../utils/SynapseLibraryTest.t.sol";
// solhint-disable func-name-mixedcase
contract MerkleTreeTest is SynapseLibraryTest {
uint256 public constant RUNS = 1000;
uint256 public constant DYNAMIC_AMOUNT = 200;
MerkleTreeHarness public libHarness;
MerkleMathHarness public mathHarness;
bytes32[] public leafs;
function setUp() public {
libHarness = new MerkleTreeHarness();
mathHarness = new MerkleMathHarness();
}
function test_baseTree() public {
assertEq(libHarness.rootBase(0), 0);
for (uint256 i = 0; i < RUNS; ++i) {
bytes32 leaf = getLeaf(i);
leafs.push(leaf);
libHarness.insertBase(i + 1, leaf);
assertEq(libHarness.rootBase(i + 1), mathHarness.calculateRoot(leafs, ORIGIN_TREE_HEIGHT));
}
}
function test_historicalTree() public {
bytes32[] memory roots = new bytes32[](RUNS + 1);
roots[0] = 0;
libHarness.initializeRoots();
for (uint256 i = 0; i < RUNS; ++i) {
bytes32 leaf = getLeaf(i);
leafs.push(leaf);
libHarness.insert(leaf);
roots[i + 1] = mathHarness.calculateRoot(leafs, ORIGIN_TREE_HEIGHT);
}
for (uint256 i = 0; i <= RUNS; ++i) {
assertEq(libHarness.root(i), roots[i]);
}
}
function test_historicalTree_revert_initializeTwice() public {
libHarness.initializeRoots();
vm.expectRevert();
libHarness.initializeRoots();
}
function test_dynamicTree() public {
for (uint256 i = 0; i < DYNAMIC_AMOUNT; ++i) {
leafs.push(0);
}
Random memory random = Random("very random seed");
for (uint256 i = 0; i < RUNS; ++i) {
uint256 index = random.nextUint256() % DYNAMIC_AMOUNT;
bytes32 oldValue = leafs[index];
bytes32 newValue = random.next();
bytes32[] memory proof = mathHarness.calculateProof(leafs, index);
bytes32 newRoot = libHarness.update(index, oldValue, proof, newValue);
leafs[index] = newValue;
assertEq(newRoot, mathHarness.calculateRoot(leafs, AGENT_TREE_HEIGHT));
}
}
function getLeaf(uint256 index) public pure returns (bytes32) {
return keccak256(abi.encode("Leaf", index));
}
}